Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

libpod,netavark: correctly set /etc/resolv.conf for custom dns server and make --dns functional #16297

Merged
merged 4 commits into from
Jan 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 17 additions & 6 deletions libpod/container_internal_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -1993,24 +1993,35 @@ 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
keepHostServers := false
if len(nameservers) == 0 {
keepHostServers = true
// first add the nameservers from the networks status
nameservers = networkNameServers
// when we add network dns server we also have to add the search domains
search = networkSearchDomains
// slirp4netns has a built in DNS forwarder.
nameservers = c.addSlirp4netnsDNS(nameservers)
}

// Set DNS search domains
search := networkSearchDomains

if len(c.config.DNSSearch) > 0 || len(c.runtime.config.Containers.DNSSearches) > 0 {
customSearch := make([]string, 0, len(c.config.DNSSearch)+len(c.runtime.config.Containers.DNSSearches))
customSearch = append(customSearch, c.runtime.config.Containers.DNSSearches...)
Expand Down
6 changes: 6 additions & 0 deletions libpod/networking_common.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,15 @@ func (c *Container) convertPortMappings() []types.PortMapping {
}

func (c *Container) getNetworkOptions(networkOpts map[string]types.PerNetworkOptions) types.NetworkOptions {
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())
}
opts := types.NetworkOptions{
ContainerID: c.config.ID,
ContainerName: getNetworkPodName(c),
DNSServers: nameservers,
}
opts.PortMappings = c.convertPortMappings()

Expand Down
31 changes: 31 additions & 0 deletions test/e2e/run_networking_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"})
Expand Down
12 changes: 8 additions & 4 deletions test/system/500-networking.bats
Original file line number Diff line number Diff line change
Expand Up @@ -651,7 +651,7 @@ EOF
"

CONTAINERS_CONF=$containersconf run_podman run --rm $IMAGE cat /etc/resolv.conf
is "$output" "search example.com$nl.*" "correct search domain"
is "$output" "search example.com.*" "correct search domain"
is "$output" ".*nameserver 1.1.1.1${nl}nameserver $searchIP${nl}nameserver 1.0.0.1${nl}nameserver 8.8.8.8" "nameserver order is correct"

# create network with dns
Expand All @@ -660,9 +660,13 @@ EOF
run_podman network create --subnet "$subnet.0/24" $netname
# custom server overwrites the network dns server
CONTAINERS_CONF=$containersconf run_podman run --network $netname --rm $IMAGE cat /etc/resolv.conf
is "$output" "search example.com$nl.*" "correct search domain"
is "$output" ".*nameserver 1.1.1.1${nl}nameserver $searchIP${nl}nameserver 1.0.0.1${nl}nameserver 8.8.8.8" "nameserver order is correct"

is "$output" "search example.com.*" "correct search domain"
local store=$output
if is_netavark; then
is "$store" ".*nameserver $subnet.1.*" "integrated dns nameserver is set"
else
is "$store" ".*nameserver 1.1.1.1${nl}nameserver $searchIP${nl}nameserver 1.0.0.1${nl}nameserver 8.8.8.8" "nameserver order is correct"
fi
# we should use the integrated dns server
run_podman run --network $netname --rm $IMAGE cat /etc/resolv.conf
is "$output" "search dns.podman.*" "correct search domain"
Expand Down