5

I've set up several network namespaces on my Linux system (kernel version 3.10), and now I want to configure each network namespace to have its own DNS settings.

I created resolv.conf files in each /etc/netns/[namespace] directory, and now I want to make my system work in the following way:

In bash command line, whenever I enter the context of a particular network namespace with nsenter --net=/run/netns/[namespace name], I want all processes launched from command line (like nslookup, ping) to run with the DNS settings that I configured with the matching /etc/netns/[namespace name]/resolv.conf.

If I run my commands like this:

 "ip netns exec [namespace name] [command]"

then the DNS settings of the namespace apply.

However, when running the commands without "ip netns exec", the DNS settings are taken from /etc/resolv.conf, even though running "netns get cur" indicates that the context is set to the desired network namespace.

I tried doing mount --bind /etc/netns/[namespace name]/resolv.conf /etc/resolv.conf in the context of the appropriate network namespace, but this applies the mount in the entire system rather then only in the context of that network namespace.

I suspected that using mount namespaces may help, so I tried reading the man page of mount namespaces, however couldn't make anything out of it in the short time that I dedicated to it.

Is there an easy and elegant way to achieve this goal?

Any help/direction toward the solution will be greatly appreciated!

3

Just look at what is doing ip netns exec test ... in your situation, using strace.

Excerpt:

# strace  -f ip netns exec test sleep 1 2>&1|egrep '/etc/|clone|mount|unshare'|egrep -vw '/etc/ld.so|access'
unshare(CLONE_NEWNS)                    = 0
mount("", "/", 0x55f2f4c2584f, MS_REC|MS_SLAVE, NULL) = 0
umount2("/sys", MNT_DETACH)             = 0
mount("test", "/sys", "sysfs", 0, NULL) = 0
open("/etc/netns/test", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 5
mount("/etc/netns/test/resolv.conf", "/etc/resolv.conf", 0x55f2f4c2584f, MS_BIND, NULL) = 0

so to reproduce (partially, eg /sys isn't handled here) what ip netns exec test ... is doing:

~# ip netns id

~# head -1 /etc/resolv.conf 
# Generated by NetworkManager

~# nsenter --net=/var/run/netns/test unshare --mount sh -c 'mount --bind /etc/netns/test/resolv.conf /etc/resolv.conf; exec bash'

~# ip netns id
test
~# head -1 /etc/resolv.conf 
# For namespace test
~#

So that's right. nsenter alone isn't enough. unshare has to be used, to change to a newly created mount namespace (basing this new on a copy of the previous one) and alter it, and not just using verbatim an existing one, since there is no existing one yet that fits. That's what is doing the syscall of the same name as is telling strace.

4

Solution

You can use ip netns exec with bash instead of using nsenter, i.e.:

ip netns enter [namespace name] bash

This will allow you to enter an interactive shell session where the namespace-specific network configuration files are automatically bind-mounted to their default (global) locations (without affecting other sessions).

Explanation

The following is taken from the ip netns man page:

For applications that are aware of network namespaces, the convention is to look for global network configuration files first in /etc/netns/**NAME/ then in **/etc/. For example, if you want a different version of /etc/resolv.conf for a network namespace used to isolate your vpn you would name it /etc/netns/myvpn/resolv.conf.

ip netns exec automates handling of this configuration, file convention for network namespace unaware applications, by creating a mount namespace and bind mounting all of the per network namespace configure files into their traditional location in /etc.

Note in particular the distinction between network-namespace aware applications and network-namespace unaware applications.

The nsenter man pages, on the other hand, do not seem to mention this distinction (in particular I searched for the strings "aware", "resolv", ".conf" and "/etc" and found no results). This seems to suggest that the nsenter utility does not perform the same kind of automatic handling of namespace unaware applications.

Additional Comments

In addition to Network Namespaces, you might also want to look at User Namespaces and Mount Namespaces. And if you're going to want further isolation beyond DNS you might also want to consider containerization, e.g. LXC Containers or Docker.

  • 1
    nsenter is the CLI tool to the setns system call. As such, it only does exactly this: joining namespaces. It does not anything to it, like ip netns does, in particular it does not introduce complexity with additional config file locations. Please note that you should always keep the UTS namespace in mind, as it isolates the hostname as well as the domainname. – TheDiveO Jun 3 '18 at 15:10

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.