Unshare is a linux command that is used to execute commands (and shells) in new namespaces. This can be useful to isolate this command from the main namespaces. Among others, namespaces you can isolate are the PID namespace, the user namespace, and the network namespace.
What is especially nice is that you can change the network namespace without being root!
The command to do that is:
unshare -rn
This executes a new shell by default.
As ifconfig
or ip addr
will show, this new shell will live in a new namespace that doesn’t contain any of your usual network interfaces. It contains the interface lo
, but be aware that the interface is down by default.
You will notice that you are root in the new shell. I don’t know what is happening exactly behind the scenes, but, while you seem to be root in this new shell, you are still the same user as usual for the host machine.
What can you do with this network namespace that contains no interface ? One use might be to execute commands that you don’t trust.
In this first post, I will explain how you can use these network namespaces to simulate a network of 2 machines:
- The first machine will have IP
10.42.0.2
- The second machine will have IP
10.42.0.3
- Both machines are on the same local network, and cannot access the real network.
In practice, you will have two shells opened (possibly in two terminals), one corresponding to each machine. The filesystem of both machines is still your nominal filesystem, which is usually useful for experiments.
Here is how to do it, first open two shells/terminals and type the command
unshare -rn
unshare creates two namespaces, one for each shell, but these namespaces are anonymous. To reference an anonymous namespace, you can reference it by the PID of one application in that namespace. Therefore we will execute the command
echo $$
in both shells to know the PID of the bash process (or your favorite shell, if it is not bash)
In the following, FIRST_PID
is the PID of the first bash process, and SECOND_PID
the PID of the second bash process.
Now in the first shell, type
ip link add veth00 netns FIRST_PID type veth peer veth11 netns SECOND_PID
This will create an interface veth00
in the first namespace (the first shell) that is linked to the interface veth11
in the second namespace.
Now you can add IP to these interfaces, put them up, and do some networking!
firstshell# ip addr add 10.42.0.2/24 dev veth00
firstshell# ip link set veth00 up
secondshell# ip addr add 10.42.0.3/24 dev veth11
secondshell# ip link set veth11 up
And that’s it! You can test everything is working as it should by pinging the machines. You can also try to see the traffic using wireshark, remember to launch wireshark from inside one of the two shells, and to use the interfaces veth00 and veth11.
Remarks
If you try to
ping 10.42.0.2
from the firstshell, this will not work, because this implicitely uses thelo
interface that is down. If you want to be able to ping yourself, you can doip link set lo up
.The interface is only visible in the shell if they share the same namespace. When the previous command is typed,
veth00
is visible in the first shell, butveth11
is visible only in the second shell.You can try the command
ip link add veth00 netns FIRST_PID type veth peer veth11 netns 1
to link the device veth00
to the namespace of the process of PID 1. What is that process ? Well it’s init
on your host machine, so this way you are making a link between your sandboxed namespace and your real namespace. However, you have now created a device veth11
in your real namespace but you cannot add an IP address to this one, because you’re not root on this namespace.
- It won’t surprise anyone that most of these features are very useful to make containers. The important thing here is that we can do this in user mode. This does not provide a real sandboxing, but it is very useful if you just want to test some small networking scripts as a user which is not root.