From 344039b9ae771f9ac431baba583ff0ded3d5da80 Mon Sep 17 00:00:00 2001 From: Rob Murray Date: Mon, 29 Jul 2024 18:36:16 +0100 Subject: [PATCH 1/3] Populate DNS records for IPv6-only endpoints Also, return IPv6 records from Network.getSvcRecords() so that /etc/hosts entries are deleted when an IPv6-only endpoint is removed. Signed-off-by: Rob Murray --- libnetwork/etchosts/etchosts.go | 4 ++ libnetwork/libnetwork_internal_test.go | 86 ++++++++++++++++++++++++++ libnetwork/network.go | 79 +++++++++++++---------- 3 files changed, 135 insertions(+), 34 deletions(-) diff --git a/libnetwork/etchosts/etchosts.go b/libnetwork/etchosts/etchosts.go index 35845fe94aa0d..945451820af7f 100644 --- a/libnetwork/etchosts/etchosts.go +++ b/libnetwork/etchosts/etchosts.go @@ -143,6 +143,10 @@ func mergeRecords(path string, recs []Record) ([]byte, error) { } // Delete deletes an arbitrary number of Records already existing in /etc/hosts file +// +// FIXME(robmry) - this only matches on hostname, not address. So, if a container +// is connected to two networks then disconnected from one of them, the hosts +// entries for both networks are deleted. func Delete(path string, recs []Record) error { defer pathLock(path)() diff --git a/libnetwork/libnetwork_internal_test.go b/libnetwork/libnetwork_internal_test.go index cb60804fde9a8..523fa93245786 100644 --- a/libnetwork/libnetwork_internal_test.go +++ b/libnetwork/libnetwork_internal_test.go @@ -13,6 +13,7 @@ import ( "github.com/docker/docker/internal/testutils/netnsutils" "github.com/docker/docker/libnetwork/config" "github.com/docker/docker/libnetwork/driverapi" + "github.com/docker/docker/libnetwork/etchosts" "github.com/docker/docker/libnetwork/ipams/defaultipam" "github.com/docker/docker/libnetwork/ipamutils" "github.com/docker/docker/libnetwork/netlabel" @@ -358,6 +359,91 @@ func TestAuxAddresses(t *testing.T) { } } +func TestUpdateSvcRecord(t *testing.T) { + skip.If(t, runtime.GOOS == "windows", "bridge driver and IPv6, only works on linux") + + tests := []struct { + name string + epName string + addr4 string + addr6 string + expSvcRecs []etchosts.Record + }{ + { + name: "v4only", + epName: "ep4", + addr4: "172.16.0.2/24", + expSvcRecs: []etchosts.Record{ + {Hosts: "id-ep4", IP: "172.16.0.2"}, + }, + }, + /* TODO(robmry) - add this test when the bridge driver understands v6-only + { + name: "v6only", + epName: "ep6", + addr6: "fde6:045d:b2aa::2/64", + expSvcRecs: []etchosts.Record{ + {Hosts: "id-ep6", IP: "fde6:45d:b2aa::2"}, + }, + }, + */ + { + name: "dual-stack", + epName: "ep46", + addr4: "172.16.1.2/24", + addr6: "fd60:8677:5a4c::2/64", + expSvcRecs: []etchosts.Record{ + {Hosts: "id-ep46", IP: "172.16.1.2"}, + {Hosts: "id-ep46", IP: "fd60:8677:5a4c::2"}, + }, + }, + } + + for _, tc := range tests { + tc := tc + t.Run(tc.name, func(t *testing.T) { + defer netnsutils.SetupTestOSContext(t)() + ctrlr, err := New(OptionBoltdbWithRandomDBFile(t)) + assert.NilError(t, err) + defer ctrlr.Stop() + + var ipam4, ipam6 []*IpamConf + var ip4, ip6 net.IP + if tc.addr4 != "" { + var net4 *net.IPNet + ip4, net4, err = net.ParseCIDR(tc.addr4) + assert.NilError(t, err) + ipam4 = []*IpamConf{{PreferredPool: net4.String()}} + } + if tc.addr6 != "" { + var net6 *net.IPNet + ip6, net6, err = net.ParseCIDR(tc.addr6) + assert.NilError(t, err) + ipam6 = []*IpamConf{{PreferredPool: net6.String()}} + } + n, err := ctrlr.NewNetwork("bridge", "net1", "", nil, + NetworkOptionEnableIPv4(tc.addr4 != ""), + NetworkOptionEnableIPv6(tc.addr6 != ""), + NetworkOptionIpam(defaultipam.DriverName, "", ipam4, ipam6, nil), + ) + assert.NilError(t, err) + ep, err := n.CreateEndpoint(context.Background(), tc.epName, + CreateOptionDNSNames([]string{tc.epName, "id-" + tc.epName}), + CreateOptionIpam(ip4, ip6, nil, nil), + ) + assert.NilError(t, err) + + n.updateSvcRecord(context.Background(), ep, true) + recs := n.getSvcRecords(ep) + assert.Check(t, is.DeepEqual(recs, tc.expSvcRecs)) + + n.updateSvcRecord(context.Background(), ep, false) + recs = n.getSvcRecords(ep) + assert.Check(t, is.Nil(recs)) + }) + } +} + func TestSRVServiceQuery(t *testing.T) { skip.If(t, runtime.GOOS == "windows", "test only works on linux") diff --git a/libnetwork/network.go b/libnetwork/network.go index dc51eac48c8e3..40972f0aa9f03 100644 --- a/libnetwork/network.go +++ b/libnetwork/network.go @@ -1329,11 +1329,14 @@ func (n *Network) updateSvcRecord(ctx context.Context, ep *Endpoint, isAdd bool) defer span.End() iface := ep.Iface() - if iface == nil || iface.Address() == nil { + if iface == nil { return } - var ipv6 net.IP + var ipv4, ipv6 net.IP + if iface.Address() != nil { + ipv4 = iface.Address().IP + } if iface.AddressIPv6() != nil { ipv6 = iface.AddressIPv6().IP } @@ -1347,12 +1350,12 @@ func (n *Network) updateSvcRecord(ctx context.Context, ep *Endpoint, isAdd bool) if isAdd { for i, dnsName := range dnsNames { ipMapUpdate := i == 0 // ipMapUpdate indicates whether PTR records should be updated. - n.addSvcRecords(ep.ID(), dnsName, serviceID, iface.Address().IP, ipv6, ipMapUpdate, "updateSvcRecord") + n.addSvcRecords(ep.ID(), dnsName, serviceID, ipv4, ipv6, ipMapUpdate, "updateSvcRecord") } } else { for i, dnsName := range dnsNames { ipMapUpdate := i == 0 // ipMapUpdate indicates whether PTR records should be updated. - n.deleteSvcRecords(ep.ID(), dnsName, serviceID, iface.Address().IP, ipv6, ipMapUpdate, "updateSvcRecord") + n.deleteSvcRecords(ep.ID(), dnsName, serviceID, ipv4, ipv6, ipMapUpdate, "updateSvcRecord") } } } @@ -1392,14 +1395,14 @@ func delNameToIP(svcMap *setmatrix.SetMatrix[svcMapEntry], name, serviceID strin } // TODO(aker): remove ipMapUpdate param and add a proper method dedicated to update PTR records. -func (n *Network) addSvcRecords(eID, name, serviceID string, epIP, epIPv6 net.IP, ipMapUpdate bool, method string) { +func (n *Network) addSvcRecords(eID, name, serviceID string, epIPv4, epIPv6 net.IP, ipMapUpdate bool, method string) { // Do not add service names for ingress network as this is a // routing only network if n.ingress { return } networkID := n.ID() - log.G(context.TODO()).Debugf("%s (%.7s).addSvcRecords(%s, %s, %s, %t) %s sid:%s", eID, networkID, name, epIP, epIPv6, ipMapUpdate, method, serviceID) + log.G(context.TODO()).Debugf("%s (%.7s).addSvcRecords(%s, %s, %s, %t) %s sid:%s", eID, networkID, name, epIPv4, epIPv6, ipMapUpdate, method, serviceID) c := n.getController() c.mu.Lock() @@ -1412,26 +1415,30 @@ func (n *Network) addSvcRecords(eID, name, serviceID string, epIP, epIPv6 net.IP } if ipMapUpdate { - addIPToName(&sr.ipMap, name, serviceID, epIP) + if epIPv4 != nil { + addIPToName(&sr.ipMap, name, serviceID, epIPv4) + } if epIPv6 != nil { addIPToName(&sr.ipMap, name, serviceID, epIPv6) } } - addNameToIP(&sr.svcMap, name, serviceID, epIP) + if epIPv4 != nil { + addNameToIP(&sr.svcMap, name, serviceID, epIPv4) + } if epIPv6 != nil { addNameToIP(&sr.svcIPv6Map, name, serviceID, epIPv6) } } -func (n *Network) deleteSvcRecords(eID, name, serviceID string, epIP net.IP, epIPv6 net.IP, ipMapUpdate bool, method string) { +func (n *Network) deleteSvcRecords(eID, name, serviceID string, epIPv4, epIPv6 net.IP, ipMapUpdate bool, method string) { // Do not delete service names from ingress network as this is a // routing only network if n.ingress { return } networkID := n.ID() - log.G(context.TODO()).Debugf("%s (%.7s).deleteSvcRecords(%s, %s, %s, %t) %s sid:%s ", eID, networkID, name, epIP, epIPv6, ipMapUpdate, method, serviceID) + log.G(context.TODO()).Debugf("%s (%.7s).deleteSvcRecords(%s, %s, %s, %t) %s sid:%s ", eID, networkID, name, epIPv4, epIPv6, ipMapUpdate, method, serviceID) c := n.getController() c.mu.Lock() @@ -1443,15 +1450,17 @@ func (n *Network) deleteSvcRecords(eID, name, serviceID string, epIP net.IP, epI } if ipMapUpdate { - delIPToName(&sr.ipMap, name, serviceID, epIP) - + if epIPv4 != nil { + delIPToName(&sr.ipMap, name, serviceID, epIPv4) + } if epIPv6 != nil { delIPToName(&sr.ipMap, name, serviceID, epIPv6) } } - delNameToIP(&sr.svcMap, name, serviceID, epIP) - + if epIPv4 != nil { + delNameToIP(&sr.svcMap, name, serviceID, epIPv4) + } if epIPv6 != nil { delNameToIP(&sr.svcIPv6Map, name, serviceID, epIPv6) } @@ -1476,27 +1485,29 @@ func (n *Network) getSvcRecords(ep *Endpoint) []etchosts.Record { return nil } - svcMapKeys := sr.svcMap.Keys() - // Loop on service names on this network - for _, k := range svcMapKeys { - if strings.Split(k, ".")[0] == epName { - continue - } - // Get all the IPs associated to this service - mapEntryList, ok := sr.svcMap.Get(k) - if !ok { - // The key got deleted - continue - } - if len(mapEntryList) == 0 { - log.G(context.TODO()).Warnf("Found empty list of IP addresses for service %s on network %s (%s)", k, n.name, n.id) - continue - } + for _, svcMap := range []*setmatrix.SetMatrix[svcMapEntry]{&sr.svcMap, &sr.svcIPv6Map} { + svcMapKeys := svcMap.Keys() + // Loop on service names on this network + for _, k := range svcMapKeys { + if strings.Split(k, ".")[0] == epName { + continue + } + // Get all the IPs associated to this service + mapEntryList, ok := svcMap.Get(k) + if !ok { + // The key got deleted + continue + } + if len(mapEntryList) == 0 { + log.G(context.TODO()).Warnf("Found empty list of IP addresses for service %s on network %s (%s)", k, n.name, n.id) + continue + } - recs = append(recs, etchosts.Record{ - Hosts: k, - IP: mapEntryList[0].ip, - }) + recs = append(recs, etchosts.Record{ + Hosts: k, + IP: mapEntryList[0].ip, + }) + } } return recs From d29767431c1139f73a3a4def9c76c8e72c19e036 Mon Sep 17 00:00:00 2001 From: Rob Murray Date: Tue, 30 Jul 2024 18:26:17 +0100 Subject: [PATCH 2/3] Use host netns for host's ext-dns servers The internal resolver needs to know whether to make requets to external DNS servers from the container's network namespace or the host's. The original rule was that requests were always made from the container's namespace, unless the nameserver was on a localhost address on the host. IPv6 nameservers were left in the container's /etc/resolv.conf. Commit 4e8d9a4 modified that so that IPv6 nameservers were also used as external nameservers. The internal resolver accessed them from the host namespace if the container's initial set of endpoints were IPv4-only, or the nameserver address contained a zone-id, (or the nameserver was on the IPv6 loopback address). That would break if initial IPv6 endpoints were disconnected from the container, leaving it with no IPv6 address. Once IPv6-only networks are allowed, another exception would need to be made for IPv4 nameservers (they'd need to be accessed from the host's namespace). Instead of doing that ... this change simplifies things, if a nameserver address is read from the host's /etc/resolv.conf, it'll work in the host's namespace. So, the rule is now simply that nameservers read from the host's resolv.conf are accessed from the host's namespace. DNS servers added as overrides ('--dns') are accessed from the container's namespace (as before). Signed-off-by: Rob Murray --- libnetwork/internal/resolvconf/resolvconf.go | 25 ++++++++----------- .../internal/resolvconf/resolvconf_test.go | 12 ++++----- .../IPv4_and_IPv6,_ipv6_disabled.golden | 2 +- .../IPv4_and_IPv6,_ipv6_enabled.golden | 2 +- ...calhost,_IPv6_private,_IPv6_enabled.golden | 2 +- .../TestRCTransformForIntNS/IPv4_only.golden | 2 +- .../IPv6_addr,_IPv6_enabled.golden | 2 +- 7 files changed, 21 insertions(+), 26 deletions(-) diff --git a/libnetwork/internal/resolvconf/resolvconf.go b/libnetwork/internal/resolvconf/resolvconf.go index 6621de64eb3ea..3f6165c5019f3 100644 --- a/libnetwork/internal/resolvconf/resolvconf.go +++ b/libnetwork/internal/resolvconf/resolvconf.go @@ -239,10 +239,8 @@ func (rc *ResolvConf) TransformForLegacyNw(ipv6 bool) { // - Add internalNS as a nameserver. // - Remove other nameservers, stashing them as ExtNameServers for the // internal resolver to use. -// - Mark ExtNameServers that must be used in the host namespace. +// - Mark ExtNameServers that must be accessed from the host namespace. // - If no ExtNameServer addresses are found, use the defaults. -// - Return an error if an "ndots" option inherited from the host's config, or -// supplied in an override is not valid. // - Ensure there's an 'options' value for each entry in reqdOptions. If the // option includes a ':', and an option with a matching prefix exists, it // is not modified. @@ -251,24 +249,21 @@ func (rc *ResolvConf) TransformForIntNS( internalNS netip.Addr, reqdOptions []string, ) ([]ExtDNSEntry, error) { - // The transformed config must list the internal nameserver. - newNSs := []netip.Addr{internalNS} - // Filter out other nameservers, keeping them for use as upstream nameservers by the - // internal nameserver. + // Add each of the nameservers read from the host's /etc/hosts or supplied as an + // override to ExtNameServers, for the internal resolver to talk to. Addresses + // read from host config should be accessed from the host's network namespace + // (HostLoopback=true). Addresses supplied as overrides are accessed from the + // container's namespace. rc.md.ExtNameServers = nil for _, addr := range rc.nameServers { - // Extract this NS. Mark addresses that did not come from an override, but will - // definitely not work in the container's namespace as 'HostLoopback'. Upstream - // requests for these servers will be made in the host's network namespace. (So, - // '--dns 127.0.0.53' means use a nameserver listening on the container's - // loopback interface. But, if the host's resolv.conf contains 'nameserver - // 127.0.0.53', the host's resolver will be used.) rc.md.ExtNameServers = append(rc.md.ExtNameServers, ExtDNSEntry{ Addr: addr, - HostLoopback: !rc.md.NSOverride && (addr.IsLoopback() || (addr.Is6() && !ipv6) || addr.Zone() != ""), + HostLoopback: !rc.md.NSOverride, }) } - rc.nameServers = newNSs + + // The transformed config only lists the internal nameserver. + rc.nameServers = []netip.Addr{internalNS} // If there are no external nameservers, and the only nameserver left is the // internal resolver, use the defaults as ext nameservers. diff --git a/libnetwork/internal/resolvconf/resolvconf_test.go b/libnetwork/internal/resolvconf/resolvconf_test.go index fd843b10992e8..28c911b52bd2d 100644 --- a/libnetwork/internal/resolvconf/resolvconf_test.go +++ b/libnetwork/internal/resolvconf/resolvconf_test.go @@ -350,15 +350,15 @@ func TestRCTransformForIntNS(t *testing.T) { { name: "IPv4 only", input: "nameserver 10.0.0.1", - expExtServers: []ExtDNSEntry{mke("10.0.0.1", false)}, + expExtServers: []ExtDNSEntry{mke("10.0.0.1", true)}, }, { name: "IPv4 and IPv6, ipv6 enabled", input: "nameserver 10.0.0.1\nnameserver fdb6:b8fe:b528::1", ipv6: true, expExtServers: []ExtDNSEntry{ - mke("10.0.0.1", false), - mke("fdb6:b8fe:b528::1", false), + mke("10.0.0.1", true), + mke("fdb6:b8fe:b528::1", true), }, }, { @@ -366,7 +366,7 @@ func TestRCTransformForIntNS(t *testing.T) { input: "nameserver 10.0.0.1\nnameserver fdb6:b8fe:b528::1", ipv6: false, expExtServers: []ExtDNSEntry{ - mke("10.0.0.1", false), + mke("10.0.0.1", true), mke("fdb6:b8fe:b528::1", true), }, }, @@ -395,7 +395,7 @@ func TestRCTransformForIntNS(t *testing.T) { name: "IPv6 addr, IPv6 enabled", input: "nameserver fd14:6e0e:f855::1", ipv6: true, - expExtServers: []ExtDNSEntry{mke("fd14:6e0e:f855::1", false)}, + expExtServers: []ExtDNSEntry{mke("fd14:6e0e:f855::1", true)}, }, { name: "IPv4 and IPv6 localhost, IPv6 disabled", @@ -421,7 +421,7 @@ func TestRCTransformForIntNS(t *testing.T) { ipv6: true, expExtServers: []ExtDNSEntry{ mke("127.0.0.53", true), - mke("fd3e:2d1a:1f5a::1", false), + mke("fd3e:2d1a:1f5a::1", true), }, }, { diff --git a/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_and_IPv6,_ipv6_disabled.golden b/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_and_IPv6,_ipv6_disabled.golden index 23dec24ad20f0..04308659f30f7 100644 --- a/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_and_IPv6,_ipv6_disabled.golden +++ b/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_and_IPv6,_ipv6_disabled.golden @@ -1,5 +1,5 @@ nameserver 127.0.0.11 # Based on host file: '/etc/resolv.conf' (internal resolver) -# ExtServers: [10.0.0.1 host(fdb6:b8fe:b528::1)] +# ExtServers: [host(10.0.0.1) host(fdb6:b8fe:b528::1)] # Overrides: [] diff --git a/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_and_IPv6,_ipv6_enabled.golden b/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_and_IPv6,_ipv6_enabled.golden index f1f5ea0bcaa33..04308659f30f7 100644 --- a/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_and_IPv6,_ipv6_enabled.golden +++ b/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_and_IPv6,_ipv6_enabled.golden @@ -1,5 +1,5 @@ nameserver 127.0.0.11 # Based on host file: '/etc/resolv.conf' (internal resolver) -# ExtServers: [10.0.0.1 fdb6:b8fe:b528::1] +# ExtServers: [host(10.0.0.1) host(fdb6:b8fe:b528::1)] # Overrides: [] diff --git a/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_localhost,_IPv6_private,_IPv6_enabled.golden b/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_localhost,_IPv6_private,_IPv6_enabled.golden index 4d7ac5e73e94b..2f58161ae67a9 100644 --- a/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_localhost,_IPv6_private,_IPv6_enabled.golden +++ b/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_localhost,_IPv6_private,_IPv6_enabled.golden @@ -1,5 +1,5 @@ nameserver 127.0.0.11 # Based on host file: '/etc/resolv.conf' (internal resolver) -# ExtServers: [host(127.0.0.53) fd3e:2d1a:1f5a::1] +# ExtServers: [host(127.0.0.53) host(fd3e:2d1a:1f5a::1)] # Overrides: [] diff --git a/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_only.golden b/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_only.golden index 4479c5936980c..58dadc47fb7e9 100644 --- a/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_only.golden +++ b/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_only.golden @@ -1,5 +1,5 @@ nameserver 127.0.0.11 # Based on host file: '/etc/resolv.conf' (internal resolver) -# ExtServers: [10.0.0.1] +# ExtServers: [host(10.0.0.1)] # Overrides: [] diff --git a/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv6_addr,_IPv6_enabled.golden b/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv6_addr,_IPv6_enabled.golden index 36cbb47099ee6..3dd9cf69e88fc 100644 --- a/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv6_addr,_IPv6_enabled.golden +++ b/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv6_addr,_IPv6_enabled.golden @@ -1,5 +1,5 @@ nameserver 127.0.0.11 # Based on host file: '/etc/resolv.conf' (internal resolver) -# ExtServers: [fd14:6e0e:f855::1] +# ExtServers: [host(fd14:6e0e:f855::1)] # Overrides: [] From 925b484a40986535c537a7a7440816b4295536c9 Mon Sep 17 00:00:00 2001 From: Rob Murray Date: Tue, 30 Jul 2024 18:57:06 +0100 Subject: [PATCH 3/3] No fallback nameservers for internal resolver The internal resolver now uses any namesever found in the host's /etc/resolv.conf as an external nameserver, and it's accessed from the host's network namespace. Before this change, when no external nameservers were found (so the host had no entries in /etc/resolv.conf) Google's DNS servers were used as fallbacks, always accessed from the container's network namespace. If a container's initial set of endpoints had IPv6 enabled, the IPv6 nameservers were included. Now we have IPv6-only networks, a similar exception would be needed for Google's IPv4 nameservers... don't include them if there are no IPv4 endpoints. However, only the initial set of endpoints was considered. As networks are connected/disconnected, IPv4 or IPv6 connectivity may be lost. Unlike nameservers read from the host's /etc/resolv.conf, there is no way to tell which fallback nameservers (v4/v6) might work from the host's namespace. So, using the host's namespace isn't a good solution. Since we want to get away from using fallback nameservers anyway, this change removes them. If a host has no /etc/resolv.conf entries, but a container does need to use DNS, it'll need to be configured with servers via '--dns'. Signed-off-by: Rob Murray --- libnetwork/internal/resolvconf/resolvconf.go | 11 --- .../internal/resolvconf/resolvconf_test.go | 76 +------------------ .../IPv4_and_IPv6,_ipv6_disabled.golden | 5 -- ...v4_and_IPv6_localhost,_ipv6_enabled.golden | 5 -- ....golden => IPv4_and_IPv6_localhost.golden} | 0 ...alhost,_IPv6_private,_IPv6_disabled.golden | 5 -- ...calhost,_IPv6_private,_IPv6_enabled.golden | 5 -- .../IPv4_localhost,_ipv6_enabled.golden | 5 -- ...,_IPv6_enabled.golden => IPv6_only.golden} | 0 .../No_host_nameserver,_iv6.golden | 6 -- .../No_host_nameserver,_no_iv6.golden | 6 -- libnetwork/sandbox_dns_unix.go | 17 +---- 12 files changed, 5 insertions(+), 136 deletions(-) delete mode 100644 libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_and_IPv6,_ipv6_disabled.golden delete mode 100644 libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_and_IPv6_localhost,_ipv6_enabled.golden rename libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/{IPv4_and_IPv6_localhost,_IPv6_disabled.golden => IPv4_and_IPv6_localhost.golden} (100%) delete mode 100644 libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_localhost,_IPv6_private,_IPv6_disabled.golden delete mode 100644 libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_localhost,_IPv6_private,_IPv6_enabled.golden delete mode 100644 libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_localhost,_ipv6_enabled.golden rename libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/{IPv6_addr,_IPv6_enabled.golden => IPv6_only.golden} (100%) delete mode 100644 libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/No_host_nameserver,_iv6.golden delete mode 100644 libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/No_host_nameserver,_no_iv6.golden diff --git a/libnetwork/internal/resolvconf/resolvconf.go b/libnetwork/internal/resolvconf/resolvconf.go index 3f6165c5019f3..0973ff8fd477a 100644 --- a/libnetwork/internal/resolvconf/resolvconf.go +++ b/libnetwork/internal/resolvconf/resolvconf.go @@ -245,7 +245,6 @@ func (rc *ResolvConf) TransformForLegacyNw(ipv6 bool) { // option includes a ':', and an option with a matching prefix exists, it // is not modified. func (rc *ResolvConf) TransformForIntNS( - ipv6 bool, internalNS netip.Addr, reqdOptions []string, ) ([]ExtDNSEntry, error) { @@ -265,16 +264,6 @@ func (rc *ResolvConf) TransformForIntNS( // The transformed config only lists the internal nameserver. rc.nameServers = []netip.Addr{internalNS} - // If there are no external nameservers, and the only nameserver left is the - // internal resolver, use the defaults as ext nameservers. - if len(rc.md.ExtNameServers) == 0 && len(rc.nameServers) == 1 { - log.G(context.TODO()).Info("No non-localhost DNS nameservers are left in resolv.conf. Using default external servers") - for _, addr := range defaultNSAddrs(ipv6) { - rc.md.ExtNameServers = append(rc.md.ExtNameServers, ExtDNSEntry{Addr: addr}) - } - rc.md.UsedDefaultNS = true - } - // For each option required by the nameserver, add it if not already present. If // the option is already present, don't override it. Apart from ndots - if the // ndots value is invalid and an ndots option is required, replace the existing diff --git a/libnetwork/internal/resolvconf/resolvconf_test.go b/libnetwork/internal/resolvconf/resolvconf_test.go index 28c911b52bd2d..272cba2b2bcd0 100644 --- a/libnetwork/internal/resolvconf/resolvconf_test.go +++ b/libnetwork/internal/resolvconf/resolvconf_test.go @@ -340,7 +340,6 @@ func TestRCTransformForIntNS(t *testing.T) { name string input string intNameServer string - ipv6 bool overrideNS []string overrideOptions []string reqdOptions []string @@ -355,16 +354,6 @@ func TestRCTransformForIntNS(t *testing.T) { { name: "IPv4 and IPv6, ipv6 enabled", input: "nameserver 10.0.0.1\nnameserver fdb6:b8fe:b528::1", - ipv6: true, - expExtServers: []ExtDNSEntry{ - mke("10.0.0.1", true), - mke("fdb6:b8fe:b528::1", true), - }, - }, - { - name: "IPv4 and IPv6, ipv6 disabled", - input: "nameserver 10.0.0.1\nnameserver fdb6:b8fe:b528::1", - ipv6: false, expExtServers: []ExtDNSEntry{ mke("10.0.0.1", true), mke("fdb6:b8fe:b528::1", true), @@ -373,7 +362,6 @@ func TestRCTransformForIntNS(t *testing.T) { { name: "IPv4 localhost", input: "nameserver 127.0.0.53", - ipv6: false, expExtServers: []ExtDNSEntry{mke("127.0.0.53", true)}, }, { @@ -381,78 +369,22 @@ func TestRCTransformForIntNS(t *testing.T) { // loopback interface, not the host's. name: "IPv4 localhost override", input: "nameserver 10.0.0.1", - ipv6: false, overrideNS: []string{"127.0.0.53"}, expExtServers: []ExtDNSEntry{mke("127.0.0.53", false)}, }, { - name: "IPv4 localhost, ipv6 enabled", - input: "nameserver 127.0.0.53", - ipv6: true, - expExtServers: []ExtDNSEntry{mke("127.0.0.53", true)}, - }, - { - name: "IPv6 addr, IPv6 enabled", + name: "IPv6 only", input: "nameserver fd14:6e0e:f855::1", - ipv6: true, expExtServers: []ExtDNSEntry{mke("fd14:6e0e:f855::1", true)}, }, { - name: "IPv4 and IPv6 localhost, IPv6 disabled", - input: "nameserver 127.0.0.53\nnameserver ::1", - ipv6: false, - expExtServers: []ExtDNSEntry{ - mke("127.0.0.53", true), - mke("::1", true), - }, - }, - { - name: "IPv4 and IPv6 localhost, ipv6 enabled", + name: "IPv4 and IPv6 localhost", input: "nameserver 127.0.0.53\nnameserver ::1", - ipv6: true, expExtServers: []ExtDNSEntry{ mke("127.0.0.53", true), mke("::1", true), }, }, - { - name: "IPv4 localhost, IPv6 private, IPv6 enabled", - input: "nameserver 127.0.0.53\nnameserver fd3e:2d1a:1f5a::1", - ipv6: true, - expExtServers: []ExtDNSEntry{ - mke("127.0.0.53", true), - mke("fd3e:2d1a:1f5a::1", true), - }, - }, - { - name: "IPv4 localhost, IPv6 private, IPv6 disabled", - input: "nameserver 127.0.0.53\nnameserver fd3e:2d1a:1f5a::1", - ipv6: false, - expExtServers: []ExtDNSEntry{ - mke("127.0.0.53", true), - mke("fd3e:2d1a:1f5a::1", true), - }, - }, - { - name: "No host nameserver, no iv6", - input: "", - ipv6: false, - expExtServers: []ExtDNSEntry{ - mke("8.8.8.8", false), - mke("8.8.4.4", false), - }, - }, - { - name: "No host nameserver, iv6", - input: "", - ipv6: true, - expExtServers: []ExtDNSEntry{ - mke("8.8.8.8", false), - mke("8.8.4.4", false), - mke("2001:4860:4860::8888", false), - mke("2001:4860:4860::8844", false), - }, - }, { name: "ndots present and required", input: "nameserver 127.0.0.53\noptions ndots:1", @@ -496,7 +428,7 @@ func TestRCTransformForIntNS(t *testing.T) { rc.OverrideOptions(tc.overrideOptions) } intNS := netip.MustParseAddr(tc.intNameServer) - extNameServers, err := rc.TransformForIntNS(tc.ipv6, intNS, tc.reqdOptions) + extNameServers, err := rc.TransformForIntNS(intNS, tc.reqdOptions) if tc.expErr != "" { assert.Check(t, is.ErrorContains(err, tc.expErr)) return @@ -559,7 +491,7 @@ func TestRCTransformForIntNSInvalidNdots(t *testing.T) { content := "nameserver 8.8.8.8\n" + tc.options rc, err := Parse(bytes.NewBuffer([]byte(content)), "/etc/resolv.conf") assert.NilError(t, err) - _, err = rc.TransformForIntNS(false, netip.MustParseAddr("127.0.0.11"), tc.reqdOptions) + _, err = rc.TransformForIntNS(netip.MustParseAddr("127.0.0.11"), tc.reqdOptions) assert.NilError(t, err) val, found := rc.Option("ndots") diff --git a/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_and_IPv6,_ipv6_disabled.golden b/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_and_IPv6,_ipv6_disabled.golden deleted file mode 100644 index 04308659f30f7..0000000000000 --- a/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_and_IPv6,_ipv6_disabled.golden +++ /dev/null @@ -1,5 +0,0 @@ -nameserver 127.0.0.11 - -# Based on host file: '/etc/resolv.conf' (internal resolver) -# ExtServers: [host(10.0.0.1) host(fdb6:b8fe:b528::1)] -# Overrides: [] diff --git a/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_and_IPv6_localhost,_ipv6_enabled.golden b/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_and_IPv6_localhost,_ipv6_enabled.golden deleted file mode 100644 index 387cc713b7b36..0000000000000 --- a/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_and_IPv6_localhost,_ipv6_enabled.golden +++ /dev/null @@ -1,5 +0,0 @@ -nameserver 127.0.0.11 - -# Based on host file: '/etc/resolv.conf' (internal resolver) -# ExtServers: [host(127.0.0.53) host(::1)] -# Overrides: [] diff --git a/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_and_IPv6_localhost,_IPv6_disabled.golden b/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_and_IPv6_localhost.golden similarity index 100% rename from libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_and_IPv6_localhost,_IPv6_disabled.golden rename to libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_and_IPv6_localhost.golden diff --git a/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_localhost,_IPv6_private,_IPv6_disabled.golden b/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_localhost,_IPv6_private,_IPv6_disabled.golden deleted file mode 100644 index 2f58161ae67a9..0000000000000 --- a/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_localhost,_IPv6_private,_IPv6_disabled.golden +++ /dev/null @@ -1,5 +0,0 @@ -nameserver 127.0.0.11 - -# Based on host file: '/etc/resolv.conf' (internal resolver) -# ExtServers: [host(127.0.0.53) host(fd3e:2d1a:1f5a::1)] -# Overrides: [] diff --git a/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_localhost,_IPv6_private,_IPv6_enabled.golden b/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_localhost,_IPv6_private,_IPv6_enabled.golden deleted file mode 100644 index 2f58161ae67a9..0000000000000 --- a/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_localhost,_IPv6_private,_IPv6_enabled.golden +++ /dev/null @@ -1,5 +0,0 @@ -nameserver 127.0.0.11 - -# Based on host file: '/etc/resolv.conf' (internal resolver) -# ExtServers: [host(127.0.0.53) host(fd3e:2d1a:1f5a::1)] -# Overrides: [] diff --git a/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_localhost,_ipv6_enabled.golden b/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_localhost,_ipv6_enabled.golden deleted file mode 100644 index 926d44d49a12d..0000000000000 --- a/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv4_localhost,_ipv6_enabled.golden +++ /dev/null @@ -1,5 +0,0 @@ -nameserver 127.0.0.11 - -# Based on host file: '/etc/resolv.conf' (internal resolver) -# ExtServers: [host(127.0.0.53)] -# Overrides: [] diff --git a/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv6_addr,_IPv6_enabled.golden b/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv6_only.golden similarity index 100% rename from libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv6_addr,_IPv6_enabled.golden rename to libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/IPv6_only.golden diff --git a/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/No_host_nameserver,_iv6.golden b/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/No_host_nameserver,_iv6.golden deleted file mode 100644 index cde7c90bd9852..0000000000000 --- a/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/No_host_nameserver,_iv6.golden +++ /dev/null @@ -1,6 +0,0 @@ -nameserver 127.0.0.11 - -# Based on host file: '/etc/resolv.conf' (internal resolver) -# Used default nameservers. -# ExtServers: [8.8.8.8 8.8.4.4 2001:4860:4860::8888 2001:4860:4860::8844] -# Overrides: [] diff --git a/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/No_host_nameserver,_no_iv6.golden b/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/No_host_nameserver,_no_iv6.golden deleted file mode 100644 index c620d3442d1e2..0000000000000 --- a/libnetwork/internal/resolvconf/testdata/TestRCTransformForIntNS/No_host_nameserver,_no_iv6.golden +++ /dev/null @@ -1,6 +0,0 @@ -nameserver 127.0.0.11 - -# Based on host file: '/etc/resolv.conf' (internal resolver) -# Used default nameservers. -# ExtServers: [8.8.8.8 8.8.4.4] -# Overrides: [] diff --git a/libnetwork/sandbox_dns_unix.go b/libnetwork/sandbox_dns_unix.go index dc86ca645648b..ecf81e6d129f0 100644 --- a/libnetwork/sandbox_dns_unix.go +++ b/libnetwork/sandbox_dns_unix.go @@ -336,21 +336,6 @@ func (sb *Sandbox) rebuildDNS() error { return err } - // Check for IPv6 endpoints in this sandbox. If there are any, and the container has - // IPv6 enabled, upstream requests from the internal DNS resolver can be made from - // the container's namespace. - // TODO(robmry) - this can only check networks connected when the resolver is set up, - // the configuration won't be updated if the container gets an IPv6 address later. - ipv6 := false - for _, ep := range sb.endpoints { - if ep.network.enableIPv6 { - if en, ok := sb.ipv6Enabled(); ok { - ipv6 = en - } - break - } - } - intNS := sb.resolver.NameServer() if !intNS.IsValid() { return fmt.Errorf("no listen-address for internal resolver") @@ -360,7 +345,7 @@ func (sb *Sandbox) rebuildDNS() error { _, sb.ndotsSet = rc.Option("ndots") // Swap nameservers for the internal one, and make sure the required options are set. var extNameServers []resolvconf.ExtDNSEntry - extNameServers, err = rc.TransformForIntNS(ipv6, intNS, sb.resolver.ResolverOptions()) + extNameServers, err = rc.TransformForIntNS(intNS, sb.resolver.ResolverOptions()) if err != nil { return err }