Skip to content

Commit d8c7c03

Browse files
committed
Merge pull request #1039 from sanimej/fixes
Avoid V6 queries in docker domain going to external nameservers
2 parents 4d070f4 + be35317 commit d8c7c03

3 files changed

Lines changed: 51 additions & 25 deletions

File tree

libnetwork_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1216,8 +1216,8 @@ func (f *fakeSandbox) SetKey(key string) error {
12161216
return nil
12171217
}
12181218

1219-
func (f *fakeSandbox) ResolveName(name string, ipType int) []net.IP {
1220-
return nil
1219+
func (f *fakeSandbox) ResolveName(name string, ipType int) ([]net.IP, bool) {
1220+
return nil, false
12211221
}
12221222

12231223
func (f *fakeSandbox) ResolveIP(ip string) string {

resolver.go

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -186,18 +186,29 @@ func shuffleAddr(addr []net.IP) []net.IP {
186186
return addr
187187
}
188188

189+
func createRespMsg(query *dns.Msg) *dns.Msg {
190+
resp := new(dns.Msg)
191+
resp.SetReply(query)
192+
setCommonFlags(resp)
193+
194+
return resp
195+
}
196+
189197
func (r *resolver) handleIPQuery(name string, query *dns.Msg, ipType int) (*dns.Msg, error) {
190-
addr := r.sb.ResolveName(name, ipType)
198+
addr, ipv6Miss := r.sb.ResolveName(name, ipType)
199+
if addr == nil && ipv6Miss {
200+
// Send a reply without any Answer sections
201+
log.Debugf("Lookup name %s present without IPv6 address", name)
202+
resp := createRespMsg(query)
203+
return resp, nil
204+
}
191205
if addr == nil {
192206
return nil, nil
193207
}
194208

195209
log.Debugf("Lookup for %s: IP %v", name, addr)
196210

197-
resp := new(dns.Msg)
198-
resp.SetReply(query)
199-
setCommonFlags(resp)
200-
211+
resp := createRespMsg(query)
201212
if len(addr) > 1 {
202213
addr = shuffleAddr(addr)
203214
}

sandbox.go

Lines changed: 33 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,11 @@ type Sandbox interface {
3737
Rename(name string) error
3838
// Delete destroys this container after detaching it from all connected endpoints.
3939
Delete() error
40-
// ResolveName resolves a service name to an IPv4 or IPv6 address by searching the
41-
// networks the sandbox is connected to.
42-
ResolveName(name string, iplen int) []net.IP
40+
// ResolveName resolves a service name to an IPv4 or IPv6 address by searching
41+
// the networks the sandbox is connected to. For IPv6 queries, second return
42+
// value will be true if the name exists in docker domain but doesn't have an
43+
// IPv6 address. Such queries shouldn't be forwarded to external nameservers.
44+
ResolveName(name string, iplen int) ([]net.IP, bool)
4345
// ResolveIP returns the service name for the passed in IP. IP is in reverse dotted
4446
// notation; the format used for DNS PTR records
4547
ResolveIP(name string) string
@@ -419,9 +421,7 @@ func (sb *sandbox) execFunc(f func()) {
419421
sb.osSbox.InvokeFunc(f)
420422
}
421423

422-
func (sb *sandbox) ResolveName(name string, ipType int) []net.IP {
423-
var ip []net.IP
424-
424+
func (sb *sandbox) ResolveName(name string, ipType int) ([]net.IP, bool) {
425425
// Embedded server owns the docker network domain. Resolution should work
426426
// for both container_name and container_name.network_name
427427
// We allow '.' in service name and network name. For a name a.b.c.d the
@@ -454,21 +454,29 @@ func (sb *sandbox) ResolveName(name string, ipType int) []net.IP {
454454
log.Debugf("To resolve: %v in %v", reqName[i], networkName[i])
455455

456456
// First check for local container alias
457-
ip = sb.resolveName(reqName[i], networkName[i], epList, true, ipType)
457+
ip, ipv6Miss := sb.resolveName(reqName[i], networkName[i], epList, true, ipType)
458458
if ip != nil {
459-
return ip
459+
return ip, false
460+
}
461+
if ipv6Miss {
462+
return ip, ipv6Miss
460463
}
461464

462465
// Resolve the actual container name
463-
ip = sb.resolveName(reqName[i], networkName[i], epList, false, ipType)
466+
ip, ipv6Miss = sb.resolveName(reqName[i], networkName[i], epList, false, ipType)
464467
if ip != nil {
465-
return ip
468+
return ip, false
469+
}
470+
if ipv6Miss {
471+
return ip, ipv6Miss
466472
}
467473
}
468-
return nil
474+
return nil, false
469475
}
470476

471-
func (sb *sandbox) resolveName(req string, networkName string, epList []*endpoint, alias bool, ipType int) []net.IP {
477+
func (sb *sandbox) resolveName(req string, networkName string, epList []*endpoint, alias bool, ipType int) ([]net.IP, bool) {
478+
var ipv6Miss bool
479+
472480
for _, ep := range epList {
473481
name := req
474482
n := ep.getNetwork()
@@ -507,17 +515,24 @@ func (sb *sandbox) resolveName(req string, networkName string, epList []*endpoin
507515

508516
var ip []net.IP
509517
n.Lock()
518+
ip, ok = sr.svcMap[name]
519+
510520
if ipType == netutils.IPv6 {
511-
ip, ok = sr.svcIPv6Map[name]
512-
} else {
513-
ip, ok = sr.svcMap[name]
521+
// If the name resolved to v4 address then its a valid name in
522+
// the docker network domain. If the network is not v6 enabled
523+
// set ipv6Miss to filter the DNS query from going to external
524+
// resolvers.
525+
if ok && n.enableIPv6 == false {
526+
ipv6Miss = true
527+
}
528+
ip = sr.svcIPv6Map[name]
514529
}
515530
n.Unlock()
516-
if ok {
517-
return ip
531+
if ip != nil {
532+
return ip, false
518533
}
519534
}
520-
return nil
535+
return nil, ipv6Miss
521536
}
522537

523538
func (sb *sandbox) SetKey(basePath string) error {

0 commit comments

Comments
 (0)