From 06241077ccf32fc82724ee4442e9b2ccdfa74ffe Mon Sep 17 00:00:00 2001 From: Aditya R Date: Sun, 20 Nov 2022 07:33:33 +0530 Subject: [PATCH] libpod,netavark: correctly populate /etc/resolv.conf with custom dns server After https://github.com/containers/netavark/pull/452 `netavark` is incharge of deciding `custom_dns_servers` if any so lets honor that and libpod should not set these manually. This also ensures docker parity Podman populates container's `/etc/resolv.conf` with custom DNS servers ( specified via `--dns` or `dns_server` in containers.conf ) even when container is connected to a network where `dns_enabled` is `true`. Current behavior does not matches with docker, hence following commit ensures that podman only populates custom DNS server when container is not connected to any network where DNS is enabled and for the cases where `dns_enabled` is `true` the resolution for custom DNS server will happen via ( `aardvark-dns` or `dnsname` ). Reference: https://docs.docker.com/config/containers/container-networking/#dns-services Closes: containers#16172 Signed-off-by: Aditya R --- libpod/container_internal_common.go | 17 +++++++++++++--- test/e2e/run_networking_test.go | 31 +++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/libpod/container_internal_common.go b/libpod/container_internal_common.go index 05a36e49b8..9e93188fd3 100644 --- a/libpod/container_internal_common.go +++ b/libpod/container_internal_common.go @@ -1993,10 +1993,21 @@ func (c *Container) generateResolvConf() error { return err } + networkBackend := c.runtime.config.Network.NetworkBackend nameservers := make([]string, 0, len(c.runtime.config.Containers.DNSServers)+len(c.config.DNSServer)) - nameservers = append(nameservers, c.runtime.config.Containers.DNSServers...) - for _, ip := range c.config.DNSServer { - nameservers = append(nameservers, ip.String()) + + // If NetworkBackend is `netavark` do not populate `/etc/resolv.conf` + // with custom dns server since after https://github.com/containers/netavark/pull/452 + // netavark will always set required `nameservers` in statsBlock and libpod + // will correctly populate `networkNameServers`. Also see https://github.com/containers/podman/issues/16172 + + // Exception: Populate `/etc/resolv.conf` if container is not connected to any network + // ( i.e len(netStatus)==0 ) since in such case netavark is not invoked at all. + if networkBackend != string(types.Netavark) || len(netStatus) == 0 { + nameservers = append(nameservers, c.runtime.config.Containers.DNSServers...) + for _, ip := range c.config.DNSServer { + nameservers = append(nameservers, ip.String()) + } } // If the user provided dns, it trumps all; then dns masq; then resolv.conf var search []string diff --git a/test/e2e/run_networking_test.go b/test/e2e/run_networking_test.go index 3880fbc5b5..9bb2eac3c7 100644 --- a/test/e2e/run_networking_test.go +++ b/test/e2e/run_networking_test.go @@ -126,6 +126,37 @@ var _ = Describe("Podman run networking", func() { Expect(session).Should(Exit(0)) }) + It("podman verify resolv.conf with --dns + --network", func() { + // Following test is only functional with netavark and aardvark + // since new behaviour depends upon output from of statusBlock + SkipIfCNI(podmanTest) + net := createNetworkName("IntTest") + session := podmanTest.Podman([]string{"network", "create", net}) + session.WaitWithDefaultTimeout() + defer podmanTest.removeNetwork(net) + Expect(session).Should(Exit(0)) + + session = podmanTest.Podman([]string{"run", "--name", "con1", "--dns", "1.1.1.1", "--network", net, ALPINE, "cat", "/etc/resolv.conf"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + // Must not contain custom dns server in containers + // `/etc/resolv.conf` since custom dns-server is + // already expected to be present and processed by + // Podman's DNS resolver i.e ( aarvark-dns or dnsname ). + Expect(session.OutputToString()).ToNot(ContainSubstring("nameserver 1.1.1.1")) + // But /etc/resolve.conf must contain othe nameserver + // i.e dns server configured for network. + Expect(session.OutputToString()).To(ContainSubstring("nameserver")) + + session = podmanTest.Podman([]string{"run", "--name", "con2", "--dns", "1.1.1.1", ALPINE, "cat", "/etc/resolv.conf"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + // All the networks being used by following container + // don't have dns_enabled in such scenario `/etc/resolv.conf` + // must contain nameserver which were specified via `--dns`. + Expect(session.OutputToString()).To(ContainSubstring("nameserver 1.1.1.1")) + }) + It("podman run network expose port 222", func() { SkipIfRootless("iptables is not supported for rootless users") session := podmanTest.Podman([]string{"run", "-dt", "--expose", "222-223", "-P", ALPINE, "/bin/sh"})