libnetwork/resolvconf: fallback to loopback nameservers for internal resolver

When the host has no valid external nameservers (or /etc/resolv.conf is
missing/dangling), TransformForIntNS previously left ExtNameServers empty
and appended 'NO EXTERNAL NAMESERVERS DEFINED'. This caused the embedded
DNS resolver (127.0.0.11) in user-defined networks to have no upstream
nameservers, causing external queries to fail with SERVFAIL.

As already documented in TransformForIntNS:
'If no ExtNameServer addresses are found, use the defaults.'

Fallback to host loopback addresses (127.0.0.1, ::1) with HostLoopback: true,
matching host libc resolver fallback behavior when resolv.conf is missing.

Signed-off-by: arsalanyavari <arya48.yavari79@gmail.com>
This commit is contained in:
arsalanyavari committed 2026-11-06 00:02:06 +03:30
1 parent e110701fe7
commit e4df2a2608
3 files changed
+17 -2

No files matched your search

@@ -44,6 +44,10 @@ var (
netip.MustParseAddr("2001:4860:4860::8888"),
netip.MustParseAddr("2001:4860:4860::8844"),
}
defaultLoopbackNSs = []netip.Addr{
netip.MustParseAddr("127.0.0.1"),
netip.MustParseAddr("::1"),
}
)
// ResolvConf represents a resolv.conf file. It can be constructed by
@@ -286,7 +290,13 @@ func (rc *ResolvConf) TransformForIntNS(
rc.md.Transform = "internal resolver"
if len(rc.md.ExtNameServers) == 0 {
rc.md.Warnings = append(rc.md.Warnings, "NO EXTERNAL NAMESERVERS DEFINED")
for _, addr := range defaultLoopbackNSs {
rc.md.ExtNameServers = append(rc.md.ExtNameServers, ExtDNSEntry{
Addr: addr,
HostLoopback: true,
})
}
rc.md.Warnings = append(rc.md.Warnings, "Used default nameservers.")
}
return slices.Clone(rc.md.ExtNameServers), nil
}
@@ -404,6 +404,10 @@ func TestRCTransformForIntNS(t *testing.T) {
{
name: "No config",
input: "",
expExtServers: []ExtDNSEntry{
mke("127.0.0.1", true),
mke("::1", true),
},
},
}
@@ -1,5 +1,6 @@
nameserver 127.0.0.11
# Based on host file: '/etc/resolv.conf' (internal resolver)
# NO EXTERNAL NAMESERVERS DEFINED
# Used default nameservers.
# ExtServers: [host(127.0.0.1) host(::1)]
# Overrides: []