I have a Linux network namespace bind mounted at ~/mynamespace as follows:

unshare -mrn;
touch ~/mynamespace; # executed in the console opened by the first command
unshare --net=~/mynamespace true; # executed in the console opened by the first command

How can I move an interface from the anonymous network namespace created by command #1 into the namespace bind mounted at ~/mynamespace?

Note that bind mounting the inner namespace or a copy of it into /var/run/netns is not an option in my case, not even temporarily. I think that the ip ... netns related commands will only accept a network namespace which is bind mounted in the more standard /var/run/netns/ directory. So I don't think the ip command will work in this case.

Also note that all commands above are run without root as an unprivileged user.


1 Answer 1

unshare -mrn # which implies -U

Everything else below is run from the namespace(s) entered from above unless told otherwise.

Without using ip netns

touch $HOME/mynamespace
unshare --net=$HOME/mynamespace true

Here true ended, losing any PID reference but a mount reference was kept allowing this namespace to still exist.

The ip link set ... netns command can take a mountpoint or a process id as reference:


move the device to the network namespace associated with name NETNSNAME or process PID.

ip link add veth0 type veth peer name veth1

Without using ip netns we can still create a PID with a temporary sleep command to get a PID reference with the ip link command and use it:

nsenter --net=$HOME/mynamespace sleep 99 & pid=$!

ip link set veth1 netns $pid

which gets:

# ip -br link
lo               DOWN           00:00:00:00:00:00 <LOOPBACK> 
veth0@if2        DOWN           86:c2:bc:ba:1a:01 <BROADCAST,MULTICAST> 
# nsenter --net=$HOME/mynamespace ip -br link
lo               DOWN           00:00:00:00:00:00 <LOOPBACK> 
veth1@if3        DOWN           86:e3:a1:ce:48:4e <BROADCAST,MULTICAST> 

Using ip netns

ip netns requires using a shared mounted /run/netns to work, or will create and mount one if not already mounted (which happens on first use). If it detects one already mounted, it won't create it and this will fail later (Cannot create namespace file "/run/netns/foo": Permission denied) because it belongs to real initial user namespace root and thus can't be written into. If it's not created it can't create it because it can't write in /run which belongs to real initial user namespace root. Etc. in all various cases, ip netns fails when run from an user namespace without privileges.

Just manually mount one over the previous one, so ip netns will be happy:

  • if /run/netns exists and one wants to keep the current /run for some reason:

    mount -t tmpfs --make-rshared tmpfs /run/netns
  • if /run/netns doesn't even exist or even if it exists one can override the whole /run:

    One can't create a directory in the current /run so it also has to be mounted over, losing access to some other useful information, but opening access to other failing tools (like iptables-legacy -w which would otherwise tell Fatal: can't open lock file /run/xtables.lock: Permission denied).

    mount -t tmpfs tmpfs /run

Now every standard ip netns, ip link or ip -n foo ... command will work as usual in the user namespace:

ip netns add mynamespace
ip link add name veth0 type veth peer netns mynamespace name veth1

which gets:

# ip -br link
lo               DOWN           00:00:00:00:00:00 <LOOPBACK> 
veth0@if2        DOWN           2a:98:7f:83:bf:9e <BROADCAST,MULTICAST> 
# ip -n mynamespace -br link
lo               DOWN           00:00:00:00:00:00 <LOOPBACK> 
veth1@if2        DOWN           96:3c:5e:a6:a4:4a <BROADCAST,MULTICAST> 

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .