From 925b484a40986535c537a7a7440816b4295536c9 Mon Sep 17 00:00:00 2001 From: Rob Murray Date: Tue, 30 Jul 2024 18:57:06 +0100 Subject: [PATCH] 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 3f6165c501..0973ff8fd4 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 28c911b52b..272cba2b2b 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", + name: "IPv4 and IPv6 localhost", 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", - 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 04308659f3..0000000000 --- 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 387cc713b7..0000000000 --- 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 2f58161ae6..0000000000 --- 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 2f58161ae6..0000000000 --- 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 926d44d49a..0000000000 --- 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 cde7c90bd9..0000000000 --- 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 c620d3442d..0000000000 --- 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 dc86ca6456..ecf81e6d12 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 }