From dc1795b4b2864f379b67d4cc50930febd8e64b3c Mon Sep 17 00:00:00 2001 From: Paul Holzinger Date: Thu, 14 Mar 2024 14:59:05 +0100 Subject: [PATCH] use new c/common pasta2 setup logic to fix dns By default we just ignored any localhost reolvers, this is problematic for anyone with more complicated dns setups, i.e. split dns with systemd-reolved. To address this we now make use of the build in dns proxy in pasta. As such we need to set the default nameserver ip now. A second change is the option to exclude certain ips when generating the host.containers.internal ip. With that we no longer set it to the same ip as is used in the netns. The fix is not perfect as it could mean on a system with a single ip we no longer add the entry, however given the previous entry was incorrect anyway this seems like the better behavior. Fixes #22044 Signed-off-by: Paul Holzinger --- libpod/container.go | 2 ++ libpod/container_internal_common.go | 32 ++++++++++++++++++--------- libpod/container_internal_freebsd.go | 2 +- libpod/container_internal_linux.go | 7 +++++- libpod/networking_freebsd.go | 4 ---- libpod/networking_linux.go | 11 --------- libpod/networking_pasta_linux.go | 7 +++++- test/system/505-networking-pasta.bats | 7 ++++-- 8 files changed, 41 insertions(+), 31 deletions(-) diff --git a/libpod/container.go b/libpod/container.go index 45ec75a2f6..00616ccfa3 100644 --- a/libpod/container.go +++ b/libpod/container.go @@ -12,6 +12,7 @@ import ( "strings" "time" + "github.com/containers/common/libnetwork/pasta" "github.com/containers/common/libnetwork/types" "github.com/containers/common/pkg/config" "github.com/containers/common/pkg/secrets" @@ -127,6 +128,7 @@ type Container struct { restoreFromCheckpoint bool slirp4netnsSubnet *net.IPNet + pastaResult *pasta.SetupResult } // ContainerState contains the current state of the container diff --git a/libpod/container_internal_common.go b/libpod/container_internal_common.go index c6fa07e086..3bb6dfe1eb 100644 --- a/libpod/container_internal_common.go +++ b/libpod/container_internal_common.go @@ -8,6 +8,7 @@ import ( "fmt" "io" "math" + "net" "os" "os/user" "path" @@ -2116,8 +2117,8 @@ func (c *Container) addResolvConf() error { // first add the nameservers from the networks status nameservers = networkNameServers - // slirp4netns has a built in DNS forwarder. - nameservers = c.addSlirp4netnsDNS(nameservers) + // pasta and slirp4netns have a built in DNS forwarder. + nameservers = c.addSpecialDNS(nameservers) } // Set DNS search domains @@ -2167,6 +2168,10 @@ func (c *Container) checkForIPv6(netStatus map[string]types.StatusBlock) bool { } } + if c.pastaResult != nil { + return c.pastaResult.IPv6 + } + return c.isSlirp4netnsIPv6() } @@ -2225,11 +2230,10 @@ func (c *Container) getHostsEntries() (etchosts.HostEntries, error) { case c.config.NetMode.IsBridge(): entries = etchosts.GetNetworkHostEntries(c.state.NetworkStatus, names...) case c.config.NetMode.IsPasta(): - ip, err := getPastaIP(c.state) - if err != nil { - return nil, err + // this should never be the case but check just to be sure and not panic + if len(c.pastaResult.IPAddresses) > 0 { + entries = etchosts.HostEntries{{IP: c.pastaResult.IPAddresses[0].String(), Names: names}} } - entries = etchosts.HostEntries{{IP: ip.String(), Names: names}} case c.config.NetMode.IsSlirp4netns(): ip, err := getSlirp4netnsIP(c.slirp4netnsSubnet) if err != nil { @@ -2276,12 +2280,18 @@ func (c *Container) addHosts() error { return err } + var exclude []net.IP + if c.pastaResult != nil { + exclude = c.pastaResult.IPAddresses + } + return etchosts.New(&etchosts.Params{ - BaseFile: baseHostFile, - ExtraHosts: c.config.HostAdd, - ContainerIPs: containerIPsEntries, - HostContainersInternalIP: etchosts.GetHostContainersInternalIP(c.runtime.config, c.state.NetworkStatus, c.runtime.network), - TargetFile: targetFile, + BaseFile: baseHostFile, + ExtraHosts: c.config.HostAdd, + ContainerIPs: containerIPsEntries, + HostContainersInternalIP: etchosts.GetHostContainersInternalIPExcluding( + c.runtime.config, c.state.NetworkStatus, c.runtime.network, exclude), + TargetFile: targetFile, }) } diff --git a/libpod/container_internal_freebsd.go b/libpod/container_internal_freebsd.go index 0f8bca0a3d..995d519299 100644 --- a/libpod/container_internal_freebsd.go +++ b/libpod/container_internal_freebsd.go @@ -279,7 +279,7 @@ func (c *Container) setCgroupsPath(g *generate.Generator) error { return nil } -func (c *Container) addSlirp4netnsDNS(nameservers []string) []string { +func (c *Container) addSpecialDNS(nameservers []string) []string { return nameservers } diff --git a/libpod/container_internal_linux.go b/libpod/container_internal_linux.go index 9e279116ca..bbe88f209c 100644 --- a/libpod/container_internal_linux.go +++ b/libpod/container_internal_linux.go @@ -616,7 +616,12 @@ func (c *Container) setCgroupsPath(g *generate.Generator) error { return nil } -func (c *Container) addSlirp4netnsDNS(nameservers []string) []string { +// addSpecialDNS adds special dns servers for slirp4netns and pasta +func (c *Container) addSpecialDNS(nameservers []string) []string { + if c.pastaResult != nil { + nameservers = append(nameservers, c.pastaResult.DNSForwardIPs...) + } + // slirp4netns has a built in DNS forwarder. if c.config.NetMode.IsSlirp4netns() { slirp4netnsDNS, err := slirp4netns.GetDNS(c.slirp4netnsSubnet) diff --git a/libpod/networking_freebsd.go b/libpod/networking_freebsd.go index 2d5c5e4885..4dc0ff25e0 100644 --- a/libpod/networking_freebsd.go +++ b/libpod/networking_freebsd.go @@ -268,7 +268,3 @@ func (c *Container) reloadRootlessRLKPortMapping() error { func (c *Container) setupRootlessNetwork() error { return nil } - -func getPastaIP(state *ContainerState) (net.IP, error) { - return nil, fmt.Errorf("pasta networking is Linux only") -} diff --git a/libpod/networking_linux.go b/libpod/networking_linux.go index a8a057d991..3ffc9d7159 100644 --- a/libpod/networking_linux.go +++ b/libpod/networking_linux.go @@ -11,7 +11,6 @@ import ( "github.com/containernetworking/plugins/pkg/ns" "github.com/containers/common/libnetwork/types" - netUtil "github.com/containers/common/libnetwork/util" "github.com/containers/common/pkg/netns" "github.com/containers/podman/v5/libpod/define" "github.com/containers/podman/v5/pkg/rootless" @@ -300,13 +299,3 @@ func (c *Container) inspectJoinedNetworkNS(networkns string) (q types.StatusBloc }) return result, err } - -func getPastaIP(state *ContainerState) (net.IP, error) { - var ip string - err := ns.WithNetNSPath(state.NetNS, func(_ ns.NetNS) error { - // get the first ip in the netns - ip = netUtil.GetLocalIP() - return nil - }) - return net.ParseIP(ip), err -} diff --git a/libpod/networking_pasta_linux.go b/libpod/networking_pasta_linux.go index 97e8118e7c..7934bc5917 100644 --- a/libpod/networking_pasta_linux.go +++ b/libpod/networking_pasta_linux.go @@ -12,10 +12,15 @@ package libpod import "github.com/containers/common/libnetwork/pasta" func (r *Runtime) setupPasta(ctr *Container, netns string) error { - return pasta.Setup(&pasta.SetupOptions{ + res, err := pasta.Setup2(&pasta.SetupOptions{ Config: r.config, Netns: netns, Ports: ctr.convertPortMappings(), ExtraOptions: ctr.config.NetworkOptions[pasta.BinaryName], }) + if err != nil { + return err + } + ctr.pastaResult = res + return nil } diff --git a/test/system/505-networking-pasta.bats b/test/system/505-networking-pasta.bats index ea968393ac..229b0adfeb 100644 --- a/test/system/505-networking-pasta.bats +++ b/test/system/505-networking-pasta.bats @@ -431,9 +431,12 @@ function pasta_test_do() { @test "Local forwarder, IPv4" { skip_if_no_ipv4 "IPv4 not routable on the host" - run_podman run --dns 198.51.100.1 \ - --net=pasta:--dns-forward,198.51.100.1 $IMAGE nslookup 127.0.0.1 || : + # pasta is the default now so no need to set it + run_podman run --rm $IMAGE grep nameserver /etc/resolv.conf + assert "${lines[0]}" == "nameserver 169.254.0.1" "default dns forward server" + run_podman run --rm --net=pasta:--dns-forward,198.51.100.1 \ + $IMAGE nslookup 127.0.0.1 || : assert "$output" =~ "1.0.0.127.in-addr.arpa" "No answer from resolver" }