Skip to content

Commit 8081491

Browse files
authored
Merge pull request #93 from tobiaskohlbau/master
add support for ipv6 addresses
2 parents f4eeb20 + 8d88b13 commit 8081491

File tree

12 files changed

+162
-56
lines changed

12 files changed

+162
-56
lines changed

Tiltfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ k8s_yaml('./test/backend.yml')
4141

4242
# Metallb
4343
helm_remote('metallb',
44-
version="0.11.0",
44+
version="0.12.1",
4545
repo_name='metallb',
4646
values=['./test/metallb-values.yaml'],
4747
repo_url='https://metallb.github.io/metallb')

apex_dual_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ package gateway
22

33
import (
44
"context"
5-
"net"
5+
"net/netip"
66
"testing"
77

88
"github.com/coredns/coredns/plugin/pkg/dnstest"
@@ -15,13 +15,13 @@ import (
1515
func setupEmptyLookupFuncs() {
1616

1717
if resource := lookupResource("HTTPRoute"); resource != nil {
18-
resource.lookup = func(_ []string) []net.IP { return []net.IP{} }
18+
resource.lookup = func(_ []string) []netip.Addr { return []netip.Addr{} }
1919
}
2020
if resource := lookupResource("Ingress"); resource != nil {
21-
resource.lookup = func(_ []string) []net.IP { return []net.IP{} }
21+
resource.lookup = func(_ []string) []netip.Addr { return []netip.Addr{} }
2222
}
2323
if resource := lookupResource("Service"); resource != nil {
24-
resource.lookup = func(_ []string) []net.IP { return []net.IP{} }
24+
resource.lookup = func(_ []string) []netip.Addr { return []netip.Addr{} }
2525
}
2626
}
2727

charts/k8s-gateway/templates/deployment.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,10 @@ spec:
2020
image: "{{ .Values.image.registry }}/{{ .Values.image.repository }}:{{ .Values.image.tag }}"
2121
imagePullPolicy: {{ .Values.image.pullPolicy }}
2222
args: [ "-conf", "/etc/coredns/Corefile" ]
23+
{{- if .Values.secure }}
2324
securityContext:
2425
runAsUser: 1000
26+
{{- end }}
2527
volumeMounts:
2628
- name: config-volume
2729
mountPath: /etc/coredns

charts/k8s-gateway/templates/service.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,10 @@ spec:
3232
externalIPs:
3333
{{- toYaml . | nindent 4 }}
3434
{{- end }}
35+
{{- if .Values.service.ipFamilyPolicy }}
36+
ipFamilyPolicy: {{ .Values.service.ipFamilyPolicy }}
37+
{{- end }}
38+
{{- with .Values.service.ipFamilies }}
39+
ipFamilies:
40+
{{- toYaml . | nindent 6 }}
41+
{{- end -}}

charts/k8s-gateway/values.yaml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,13 @@ service:
5151
# externalTrafficPolicy: Local
5252
# externalIPs:
5353
# - 192.168.1.3
54+
# One of SingleStack, PreferDualStack, or RequireDualStack.
55+
# ipFamilyPolicy: SingleStack
56+
# List of IP families (e.g. IPv4 and/or IPv6).
57+
# ref: https://kubernetes.io/docs/concepts/services-networking/dual-stack/#services
58+
# ipFamilies:
59+
# - IPv4
60+
# - IPv6
5461

5562
nodeSelector: {}
5663

@@ -63,3 +70,5 @@ priorityClassName: ""
6370

6471
debug:
6572
enabled: false
73+
74+
secure: true

gateway.go

Lines changed: 51 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"fmt"
66
"net"
7+
"net/netip"
78
"strings"
89

910
"github.com/coredns/coredns/plugin"
@@ -12,14 +13,14 @@ import (
1213
"github.com/miekg/dns"
1314
)
1415

15-
type lookupFunc func(indexKeys []string) []net.IP
16+
type lookupFunc func(indexKeys []string) []netip.Addr
1617

1718
type resourceWithIndex struct {
1819
name string
1920
lookup lookupFunc
2021
}
2122

22-
var noop lookupFunc = func([]string) (result []net.IP) { return }
23+
var noop lookupFunc = func([]string) (result []netip.Addr) { return }
2324

2425
var orderedResources = []*resourceWithIndex{
2526
{
@@ -143,7 +144,7 @@ func (gw *Gateway) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Ms
143144
}
144145
}
145146

146-
var addrs []net.IP
147+
var addrs []netip.Addr
147148

148149
// Iterate over supported resources and lookup DNS queries
149150
// Stop once we've found at least one match
@@ -163,10 +164,40 @@ func (gw *Gateway) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Ms
163164
m := new(dns.Msg)
164165
m.SetReply(state.Req)
165166

167+
var ipv4Addrs []netip.Addr
168+
var ipv6Addrs []netip.Addr
169+
170+
for _, addr := range addrs {
171+
if addr.Is4() {
172+
ipv4Addrs = append(ipv4Addrs, addr)
173+
}
174+
if addr.Is6() {
175+
ipv6Addrs = append(ipv6Addrs, addr)
176+
}
177+
}
178+
166179
switch state.QType() {
167180
case dns.TypeA:
168181

169-
if len(addrs) == 0 {
182+
if len(ipv4Addrs) == 0 {
183+
184+
if !isRootZoneQuery {
185+
// No match, return NXDOMAIN
186+
m.Rcode = dns.RcodeNameError
187+
}
188+
189+
m.Ns = []dns.RR{gw.soa(state)}
190+
191+
} else {
192+
193+
m.Answer = gw.A(state.Name(), ipv4Addrs)
194+
// Force to true to fix broken behaviour of legacy glibc `getaddrinfo`.
195+
// See https://github.com/coredns/coredns/pull/3573
196+
m.Authoritative = true
197+
}
198+
case dns.TypeAAAA:
199+
200+
if len(ipv6Addrs) == 0 {
170201

171202
if !isRootZoneQuery {
172203
// No match, return NXDOMAIN
@@ -177,11 +208,12 @@ func (gw *Gateway) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Ms
177208

178209
} else {
179210

180-
m.Answer = gw.A(state.Name(), addrs)
211+
m.Answer = gw.AAAA(state.Name(), ipv6Addrs)
181212
// Force to true to fix broken behaviour of legacy glibc `getaddrinfo`.
182213
// See https://github.com/coredns/coredns/pull/3573
183214
m.Authoritative = true
184215
}
216+
185217
case dns.TypeSOA:
186218

187219
// Force to true to fix broken behaviour of legacy glibc `getaddrinfo`.
@@ -218,12 +250,23 @@ func (gw *Gateway) ServeDNS(ctx context.Context, w dns.ResponseWriter, r *dns.Ms
218250
func (gw *Gateway) Name() string { return thisPlugin }
219251

220252
// A does the A-record lookup in ingress indexer
221-
func (gw *Gateway) A(name string, results []net.IP) (records []dns.RR) {
253+
func (gw *Gateway) A(name string, results []netip.Addr) (records []dns.RR) {
254+
dup := make(map[string]struct{})
255+
for _, result := range results {
256+
if _, ok := dup[result.String()]; !ok {
257+
dup[result.String()] = struct{}{}
258+
records = append(records, &dns.A{Hdr: dns.RR_Header{Name: name, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: gw.ttlLow}, A: net.ParseIP(result.String())})
259+
}
260+
}
261+
return records
262+
}
263+
264+
func (gw *Gateway) AAAA(name string, results []netip.Addr) (records []dns.RR) {
222265
dup := make(map[string]struct{})
223266
for _, result := range results {
224267
if _, ok := dup[result.String()]; !ok {
225268
dup[result.String()] = struct{}{}
226-
records = append(records, &dns.A{Hdr: dns.RR_Header{Name: name, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: gw.ttlLow}, A: result})
269+
records = append(records, &dns.AAAA{Hdr: dns.RR_Header{Name: name, Rrtype: dns.TypeAAAA, Class: dns.ClassINET, Ttl: gw.ttlLow}, AAAA: net.ParseIP(result.String())})
227270
}
228271
}
229272
return records
@@ -232,7 +275,7 @@ func (gw *Gateway) A(name string, results []net.IP) (records []dns.RR) {
232275
// SelfAddress returns the address of the local k8s_gateway service
233276
func (gw *Gateway) SelfAddress(state request.Request) (records []dns.RR) {
234277

235-
var addrs1, addrs2 []net.IP
278+
var addrs1, addrs2 []netip.Addr
236279
for _, resource := range gw.Resources {
237280
results := resource.lookup([]string{gw.apex})
238281
if len(results) > 0 {

gateway_test.go

Lines changed: 29 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package gateway
33
import (
44
"context"
55
"errors"
6-
"net"
6+
"net/netip"
77
"strings"
88
"testing"
99

@@ -105,7 +105,7 @@ func TestPluginFallthrough(t *testing.T) {
105105
}
106106

107107
var tests = []test.Case{
108-
// Existing Service | Test 0
108+
// Existing Service IPv4 | Test 0
109109
{
110110
Qname: "svc1.ns1.example.com.", Qtype: dns.TypeA, Rcode: dns.RcodeSuccess,
111111
Answer: []dns.RR{
@@ -210,6 +210,13 @@ var tests = []test.Case{
210210
test.A("shadow.example.com. 60 IN A 192.0.2.4"),
211211
},
212212
},
213+
// Existing Service IPv6 | Test 15
214+
{
215+
Qname: "svc1.ns1.example.com.", Qtype: dns.TypeAAAA, Rcode: dns.RcodeSuccess,
216+
Answer: []dns.RR{
217+
test.AAAA("svc1.ns1.example.com. 60 IN AAAA fd12:3456:789a:1::"),
218+
},
219+
},
213220
}
214221

215222
var testsFallthrough = []FallthroughCase{
@@ -240,53 +247,53 @@ var testsFallthrough = []FallthroughCase{
240247
},
241248
}
242249

243-
var testServiceIndexes = map[string][]net.IP{
244-
"svc1.ns1": {net.ParseIP("192.0.1.1")},
245-
"svc2.ns1": {net.ParseIP("192.0.1.2")},
250+
var testServiceIndexes = map[string][]netip.Addr{
251+
"svc1.ns1": {netip.MustParseAddr("192.0.1.1"), netip.MustParseAddr("fd12:3456:789a:1::")},
252+
"svc2.ns1": {netip.MustParseAddr("192.0.1.2")},
246253
"svc3.ns1": {},
247254
}
248255

249-
func testServiceLookup(keys []string) (results []net.IP) {
256+
func testServiceLookup(keys []string) (results []netip.Addr) {
250257
for _, key := range keys {
251258
results = append(results, testServiceIndexes[strings.ToLower(key)]...)
252259
}
253260
return results
254261
}
255262

256-
var testIngressIndexes = map[string][]net.IP{
257-
"domain.example.com": {net.ParseIP("192.0.0.1")},
258-
"svc2.ns1.example.com": {net.ParseIP("192.0.0.2")},
259-
"example.com": {net.ParseIP("192.0.0.3")},
260-
"shadow.example.com": {net.ParseIP("192.0.0.4")},
261-
"shadow-vs.example.com": {net.ParseIP("192.0.0.5")},
263+
var testIngressIndexes = map[string][]netip.Addr{
264+
"domain.example.com": {netip.MustParseAddr("192.0.0.1")},
265+
"svc2.ns1.example.com": {netip.MustParseAddr("192.0.0.2")},
266+
"example.com": {netip.MustParseAddr("192.0.0.3")},
267+
"shadow.example.com": {netip.MustParseAddr("192.0.0.4")},
268+
"shadow-vs.example.com": {netip.MustParseAddr("192.0.0.5")},
262269
}
263270

264-
func testIngressLookup(keys []string) (results []net.IP) {
271+
func testIngressLookup(keys []string) (results []netip.Addr) {
265272
for _, key := range keys {
266273
results = append(results, testIngressIndexes[strings.ToLower(key)]...)
267274
}
268275
return results
269276
}
270277

271-
var testVirtualServerIndexes = map[string][]net.IP{
272-
"vs1.example.com": {net.ParseIP("192.0.3.1")},
273-
"shadow.example.com": {net.ParseIP("192.0.3.4")},
274-
"shadow-vs.example.com": {net.ParseIP("192.0.3.5")},
278+
var testVirtualServerIndexes = map[string][]netip.Addr{
279+
"vs1.example.com": {netip.MustParseAddr("192.0.3.1")},
280+
"shadow.example.com": {netip.MustParseAddr("192.0.3.4")},
281+
"shadow-vs.example.com": {netip.MustParseAddr("192.0.3.5")},
275282
}
276283

277-
func testVirtualServerLookup(keys []string) (results []net.IP) {
284+
func testVirtualServerLookup(keys []string) (results []netip.Addr) {
278285
for _, key := range keys {
279286
results = append(results, testVirtualServerIndexes[strings.ToLower(key)]...)
280287
}
281288
return results
282289
}
283290

284-
var testHTTPRouteIndexes = map[string][]net.IP{
285-
"domain.gw.example.com": {net.ParseIP("192.0.2.1")},
286-
"shadow.example.com": {net.ParseIP("192.0.2.4")},
291+
var testHTTPRouteIndexes = map[string][]netip.Addr{
292+
"domain.gw.example.com": {netip.MustParseAddr("192.0.2.1")},
293+
"shadow.example.com": {netip.MustParseAddr("192.0.2.4")},
287294
}
288295

289-
func testHTTPRouteLookup(keys []string) (results []net.IP) {
296+
func testHTTPRouteLookup(keys []string) (results []netip.Addr) {
290297
for _, key := range keys {
291298
results = append(results, testHTTPRouteIndexes[strings.ToLower(key)]...)
292299
}

0 commit comments

Comments
 (0)