mirror of
https://github.com/moby/moby.git
synced 2026-07-15 20:12:07 +00:00
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 <rob.murray@docker.com>
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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: []
|
||||
@@ -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: []
|
||||
@@ -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: []
|
||||
@@ -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: []
|
||||
@@ -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: []
|
||||
@@ -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: []
|
||||
@@ -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: []
|
||||
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user