You have two questions in one:
- what are the empty files in
/var/run/netns/
?
- how to use
/etc/netns/
which doesn't even exist?
What are the empty files in /var/run/netns/
?
Some understanding of namespaces is needed. I can't explain it in detail here. Suffice to say that a namespace once created will (partition some kernel resource such as network, and) exist as long as something is using it. Mostly two thing will use it: processes, or mountpoints in the special pseudo-filesystem nsfs
. Once they stop using it or disappear, the namespace also disappears.
ip netns
(which specializes in network namespaces) chooses to keep network namespaces by mounting a reference to them. Those references are all avalable in /proc/<pid>/net/
as symlinks. Example:
$ ls -l /proc/$$/ns/net
lrwxrwxrwx. 1 user user 0 Sep 25 01:05 /proc/19120/ns/net -> net:[4026531992]
$ stat -L -f -c %T /proc/19120/ns/net # filesystem type. "df" on this would be confused and point to the wrong mountpoint anyway.
nsfs
$ stat -L -c %i /proc/19120/ns/net # inode
4026531992
ip netns add
just bind-mounts them in /var/run/netns/<NAME>
. Note that while you usually bind-mount a directory over a directory, you can also bind-mount a file over a file. Note also that this file is a pseudo-file in the nsfs
filesystem. It's not designed to be read, and can't be. It's mostly used to be passed around as a reference, by opening (but not reading or writing) it or mounting it:
# strace -e unshare,mount ip netns add ns1
mount("", "/var/run/netns", 0x5625f6ca80e3, MS_REC|MS_SHARED, NULL) = 0
unshare(CLONE_NEWNET) = 0
mount("/proc/self/ns/net", "/var/run/netns/ns1", 0x5625f6ca80e3, MS_BIND, NULL) = 0
+++ exited with 0 +++
# ip netns list
ns1
# ls -l /var/run/netns/ns1
-r--r--r--. 1 root root 0 Sep 25 01:08 /var/run/netns/ns1
# cat /var/run/netns/ns1
cat: /var/run/netns/ns1: Invalid argument
# stat -f -c %T /var/run/netns/ns1
nsfs
# stat -c %i /var/run/netns/ns1
4026532824
# ip netns exec ns1 sleep 99 &
[1] 19620
# ls -l /proc/19620/ns/net
lrwxrwxrwx. 1 root root 0 Sep 25 01:23 /proc/19620/ns/net -> net:[4026532824]
So sleep 99
's network namespace is the one from the mountpoint /var/run/netns/ns1
.
With this method, for example, it's possible to have a network namespace with a bridge linked to other namespaces with veth
interfaces and not running any process, because none are needed.
You can manually delete namespaces created by ip netns
with:
# umount /var/run/netns/ns1
# rm /var/run/netns/ns1
# ip netns list
#
Of course the network namespace will really only disappear once the last reference using it (eg: process) will also disappear. You could even put it back, if the previous sleep command is still running:
# touch /var/run/netns/ns1
# mount --bind /proc/19620/ns/net /var/run/netns/ns1
# ip netns
ns1
This can be used to "copy" the network namespace's part of a full container, you just need to know some pid on the host side (eg: lxc-info -Hp -n container
or docker inspect --format '{{.State.Pid}}' container
) and mount its network namespace. Handy to run debug commands not available inside the container (tcpdump
...).
Everything above is ephemeral, eg it disappears after a reboot.
How to use /etc/netns/
which doesn't even exist?
The ip netns
manpage tells (bold emphasis mine):
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
.
Now, is dnsmasq
"aware" of network namespaces? If it was (with ip netns
's definition) it would check for /etc/netns/
somehow. There's no mention of "netns" in its manpage. The current Debian's (similar to Raspberry's) source doesn't include the word netns
anywhere: it's not network namespace aware.
That's why ip netns
manpage's following sentence tells:
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
.
It's not really explained, but together with the previous sentence this really means that ip netns exec
will bind-mount, if both the source and target exist, /etc/netns/<NAME>/whatever
on /etc/whatever
. /etc/netns
and the chosen network namespace names inside, which will contain the configurations have to be created first, manually, and actual configuration content probably copied inside and edited: ip netns exec
will use them if found, but not create them.
Example:
# mkdir -p /etc/netns/ns1
# echo something > /etc/netns/ns1/whatever
# : > /etc/whatever
# ip netns add ns1
# cat /etc/whatever
# ip netns exec ns1 cat /etc/whatever
something
What really happened behind:
# strace -e open,unshare,setns,mount,umount2 ip netns exec ns1 cat /etc/whatever 2>&1 |egrep '^(open.*/etc/netns|unshare|setns|mount|umount|something)'
setns(5, CLONE_NEWNET) = 0
unshare(CLONE_NEWNS) = 0
mount("", "/", 0x55947eb550e3, MS_REC|MS_SLAVE, NULL) = 0
umount2("/sys", MNT_DETACH) = 0
mount("ns1", "/sys", "sysfs", 0, NULL) = 0
open("/etc/netns/ns1", O_RDONLY|O_NONBLOCK|O_DIRECTORY|O_CLOEXEC) = 5
mount("/etc/netns/ns1/whatever", "/etc/whatever", 0x55947eb550e3, MS_BIND, NULL) = 0
something
Of course this works the same for directories inside /etc/netns/ns1
instead of files: the whole directory will appear directly in /etc/
masking the host's directory of the same name, only if it exists.
So if dnsmasq's default configuration unless told otherwise is /etc/dnsmasq.conf
, You can create an alternate configuration for ns1
as /etc/netns/ns1/dnsmasq.conf
and ip netns exec
will make it appear as /etc/dnsmasq.conf
to dnsmasq
, if there's also already a /etc/dnsmasq.conf
file, even if it was empty. Since it's in /etc
this isn't ephemeral and will be reused whenever you're recreating the same network namspace name. Same for hostapd
and the whole /etc/hostapd/
directory which can be copied as /etc/netns/ns1/hostapd/
and its files then modified inside. Be careful with symlinks pointing outside. You can now run the commands as usual inside ip netns exec ns1
: they'll use the new configuration file.
Best Answer
http://man7.org/linux/man-pages/man8/ip-netns.8.html
So you need something like this: Iptables to redirect DNS lookup IP and Port