From 6a618abe2ff7603c22e87ecf9a42f8b6efbb832b Mon Sep 17 00:00:00 2001 From: Brad Davidson Date: Thu, 31 Jul 2025 22:09:08 +0000 Subject: [PATCH] Fix fallback DNS for IMDS and IPV6-only Signed-off-by: Brad Davidson --- pkg/agent/config/config.go | 24 ++++++++++++++++++++---- pkg/agent/config/config_internal_test.go | 3 ++- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/pkg/agent/config/config.go b/pkg/agent/config/config.go index 14e92fa2f1..5eae845ca6 100644 --- a/pkg/agent/config/config.go +++ b/pkg/agent/config/config.go @@ -47,6 +47,8 @@ const ( DefaultPodManifestPath = "pod-manifests" ) +var InstanceMetadataServiceIP = net.ParseIP("169.254.169.254") + // Get returns a pointer to a completed Node configuration struct, // containing a merging of the local CLI configuration with settings from the server. // Node configuration includes client certificates, which requires node password verification, @@ -390,8 +392,7 @@ func isValidResolvConf(resolvConfFile string) bool { for scanner.Scan() { ipMatch := nameserver.FindStringSubmatch(scanner.Text()) if len(ipMatch) == 2 { - ip := net.ParseIP(ipMatch[1]) - if ip == nil || !ip.IsGlobalUnicast() { + if !isValidNameserver(ipMatch[1]) { return false } else { foundNameserver = true @@ -404,6 +405,21 @@ func isValidResolvConf(resolvConfFile string) bool { return foundNameserver } +// isValidNameserver returns a boolean indicating whether or not the IP is a valid +// upstream resolver address. Resolver IPs must be valid global unicast addresses, with +// the exception of the instance metadata service IP, which some cloud providers require +// traffic be forwarded to in order for private DNS to work properly. +func isValidNameserver(addr string) bool { + ip := net.ParseIP(addr) + if ip == nil { + return false + } + if !ip.IsGlobalUnicast() && !ip.Equal(InstanceMetadataServiceIP) { + return false + } + return true +} + func locateOrGenerateResolvConf(envInfo *cmds.Agent) string { if envInfo.ResolvConf != "" { return envInfo.ResolvConf @@ -416,11 +432,11 @@ func locateOrGenerateResolvConf(envInfo *cmds.Agent) string { } resolvConf := filepath.Join(envInfo.DataDir, "agent", "etc", "resolv.conf") - if err := agentutil.WriteFile(resolvConf, "nameserver 8.8.8.8\n"); err != nil { + if err := agentutil.WriteFile(resolvConf, "nameserver 8.8.8.8\nnameserver 2001:4860:4860::8888\n"); err != nil { logrus.Errorf("Failed to write %s: %v", resolvConf, err) return "" } - logrus.Warnf("Host resolv.conf includes loopback or multicast nameservers - kubelet will use autogenerated resolv.conf with nameserver 8.8.8.8") + logrus.Warnf("Host resolv.conf includes loopback, multicast, or link-local nameservers - kubelet will use autogenerated resolv.conf with nameservers 8.8.8.8 2001:4860:4860::8888") return resolvConf } diff --git a/pkg/agent/config/config_internal_test.go b/pkg/agent/config/config_internal_test.go index 167f150730..653229c014 100644 --- a/pkg/agent/config/config_internal_test.go +++ b/pkg/agent/config/config_internal_test.go @@ -13,9 +13,10 @@ func Test_isValidResolvConf(t *testing.T) { }{ {name: "Valid ResolvConf", fileContent: "nameserver 8.8.8.8\nnameserver 2001:4860:4860::8888\n", expectedResult: true}, {name: "Invalid ResolvConf", fileContent: "nameserver 999.999.999.999\nnameserver not.an.ip\n", expectedResult: false}, - {name: "Wrong Nameserver", fileContent: "search example.com\n", expectedResult: false}, + {name: "No Nameserver", fileContent: "search example.com\n", expectedResult: false}, {name: "One valid nameserver", fileContent: "test test.com\nnameserver 8.8.8.8", expectedResult: true}, {name: "Non GlobalUnicast", fileContent: "nameserver ::1\nnameserver 169.254.0.1\nnameserver fe80::1\n", expectedResult: false}, + {name: "Instance Metadata", fileContent: "nameserver 169.254.169.254", expectedResult: true}, {name: "Empty File", fileContent: "", expectedResult: false}, }