Testing Network Daemons
As a maintainer of many Open Source projects where networking is key, a side quest has emerged – how to test network applications without root?
The following writeup is part of my series; Reminders to self. Please let me know if there’s anything you’d like me to delve further into.
Depending on your needs, of course, you can use Qemu, and if needed, connect multiple Qemu instances with Qeneth. However, this requires quite a bit of overhead to test a single application.
Enter Linux namespaces, they are the building blocks for what is more commonly referred to as containers. A container usally employ all available namespaces to box in one or more applications, but they also make use of cgroups and various security barriers. In this blog post we’ll only be looking at namespaces, and in particular network namespaces.
As in programming, a namespace is like a new context, a carte blanche so to speak. For example, a PID namespace hides all other PIDs in the system. Similarily, a network namespace hides all the system network interfaces. But you can move interfaces between network namespaces, and that is what we’ll make use of here.
Tools of the Trade
The tools we’ll be using are probably already available on your system. You just don’t know about them …
Well, the last one you probably should know about if you’re an active
Linux user since we’ve replaced the classic UNIX ifconfig
tool (and
a few others) with the iproute2 sute.
Privileged Ports
Running system level services usually means using privileged ports
so testing such services can be a hassle. We all want to avoid running
as root, and even sudo
requires a password (unless you disable it on
your system). What we want is to be able to run make check
or similar
in our project to verify that our application works on the standard port
it runs on.
This brings us to our first example use-case for network namespaces:
$ cd ~/src/my-project/
$ unshare -mrun
#
There you go, a root prompt in a dedicated network namespace, meaning you can now go ahead and start your application :-)
Oh wait, you need one last thing:
# ip link set lo up state up
Not much networking in UNIX works unless the loopback interfaces is up.
In Linux this brings up the interface, sets the IPv4 and IPv6 loopback
addresses, and state up
ensure that we se UP
instead of UNKNOWN
link status.
LAN Communication
Most projects do well with just the basics, shown in the first example. However, some may need a bit more, like a proper layer-2 network, i.e., a cable between two NICs. We can emulate that with a VETH pair.
# ip link add veth0a type veth peer veth0b
This gives us a virtual Ethernet cable with an a
and a b
side. Now,
we need to move one end of that cable into a separate network namespace,
yes another unshare
inside the first one. Only problem is that they
need a live process to exist, in our first case this is covered by the
shell we use in the terminal. Ideally, the process in the new unshare
could be the network daemon we want to test, but to keep things simple
in this example we’ll use sleep
.
# unshare -run sleep infinity &
# pid=$!
The PID of the sleep
process is our handle into the new namespace.
Here’s how the ip link
command can be used to move veth0b
:
# ip link set veth0b netns $pid
# ip -br l
lo DOWN 00:00:00:00:00:00 <LOOPBACK>
veth0a@if2 DOWN 8a:2f:99:38:a7:6c <BROADCAST,MULTICAST>
We can peek into the nested unshare using the nsenter
command:
# nsenter -t 1646509 -n ip -br l
lo DOWN 00:00:00:00:00:00 <LOOPBACK>
veth0b@if3 DOWN fa:e3:0f:a6:dd:77 <BROADCAST,MULTICAST>
Final Notes
For scripting purposes you may want to look into more of the options for
both unshare
and nsenter
. For the latter in particular you may want
to use nsenter -t $pid -n -U --preserve-credentials [CMD]
.
Also, and this bears repeating, you should not need to use sudo
for
any of these commands. You may need to set up capabilities though,
but that’s a good thing to learn about anyway.
Finally, as of late many Linux distributions have started locking down namespaces for regular users. Read more about what you may need to do, and know about, here.
That’s it, this is all the tools you need to get started, good luck!