Using Linux Network Namespaces for per processes routing
Linux Linux Desktop Namespaces Networking Routing Sysadmin
7 minutes
The use case for this article may seem a bit strange in year 2013 but I swear it’s real. I have a (relatively) fast connection but I have a traffic cap on it and a (really) slow one which is flat. I would like to run not interactive task like “aptitude safe-upgrade” on the slow one but the bulk of my connections should go through the fast one. The work is done on a Debian Wheezy system, check that the “ip” command is not too old and lacks network namespace support.
Linux namespaces are a cool feature that permit process groups to have a limited view of system resource. See the superb LWN article for more information. In this article we will use network namespaces which permits different process groups to have a different view of the networking system. Processes in a network namespace cannot see the physical network adapter but only a virtual one. We can create 2 of them as the endpoints of a pipe to make the processes in a network namespace speak with the outer net. For this we will use the simplest approach, a bridge. Other, more complicate, setups like NAT are of course possible.
First of all lets define some convenience variables:
BASE_IP=10.0.10.253 FAST_GW=10.0.10.58 NETMASK=255.255.255.0 SLOW_IP=10.0.10.149 SLOW_GW=10.0.10.57
These define the physical IP address of my machine, the fast connection gateway, the netmask of my setup, the IP that will be seen by processes in the network container and the gatway for the slow network.
Next we have to create the network namespace. Its name is slow for obvious reasons:
ip netns add slow
and the virtual ethernets that act as the endpoints for the pipe from it to the “real world”:
ip link add veth0 type veth peer name veth1 ifconfig veth0 0.0.0.0 up ip link set veth1 netns slow
we have to unconfigure the physical network card because it will be part of the bridge:
ifdown eth0 ifconfig eth0 0.0.0.0 up
and then we bridge it to one endpoint of the pipe to the network namespace:
brctl addbr br0 brctl addif br0 eth0 veth0
we reassign the base ip to the bridge interface so we can continue working as before for processes not in network namespace:
ifconfig br0 $BASE_IP netmask $NETMASK up route add default gw $FAST_GW
the configuration of the host is finished, now we have to turn our attention to what happens in the network namespace. To execute a process there we have to use the command ip netns exec [namespace] [command]. Here we setup the IP address of the interface in the namespace and define the default route pointing to the slow gateway:
ip netns exec slow ifconfig veth1 $SLOW_IP netmask $NETMASK up ip netns exec slow route add default gw $SLOW_GW
and voilà, we can now run our favorite long-running network command in the newly created namespace:
ip netns exec slow aptitude safe-upgrade
we can also start a shell there, so everything we will do there will be routed to the slow gateway. We can also relogin as a non privileged user (ip nets commands need root privileges):
ip netns exec slow bash ip netns exec slow su - chri
Linux namespaces are a very powerful tool. Their primary use are containers but they are useful in many other situations such as this.
Comments #
- gag on 2014-01-27 07:50:45 +0100
Hi,
nice tute . but there is a problem when i create a namespace and then logout and log in again in linux kernal.there is no namespace there and namespace automatically deleted. how i can solve this problem please help.thanks
- Christian Pellegrin on 2014-01-31 10:45:45 +0100
Yes, the namespace configuration, like all other ones, must be reissued on every restart. Where it’s done depends on distribution. Under Debian Wheezy (the one I use) you have to configure /etc/network/interfaces. Another, easier but not so clean, solution is to run the commands from /etc/rc.local.
- gag on 2014-02-05 07:12:55 +0100
thanks for reply. i got it. hi everything is ok before line
ip netns exec slow aptitude safe-upgrade
but when i run above command there is unknown host error . then i try to ping google.com in new network namespace again same error. then i try ping 8.8.8.8 its working. also in local namespace ping google.com is working but not in new network namespace . please can u tell me why this and how i can resolve this.?
- gag on 2014-02-05 07:24:56 +0100
can u give me some code to write in /etc/network/interfaces or rc.local
thanks
- Christian Pellegrin on 2014-02-06 07:54:00 +0100
If you just created a newtork namespace (and not others) the /etc/resolv.conf and /etc/gai.conf file should be the same so the resolver library should work. Which distribution are you using? For /etc/rc.local it’s easy: just copy the command you use there.
- gag on 2014-02-06 09:29:18 +0100
thank you . my dns resolving problem solved after setting same nameserver in /etc/gai.conf as in /etc/resolv.conf.
what its mean “created a network namespace (not others) here what the mean of “not other.”
i am using ubuntu 13 in virtualbox . i think when we create a namespace there is /var/run/netns/ file is created using command “ip netns add ”
but on reboot the ubuntu /var/run/netns directory automatically deleted . now i want to know which command i copy in rc.localthanks
- gag on 2014-02-06 11:32:06 +0100
hi
after these commands
ip netns exec slow bash
ip netns exec slow su – chriwe will enter in the slow network namespace .then how we can exit from this i mean how we can again enter in default namespace
- Christian Pellegrin on 2014-02-09 08:43:34 +0100
I mean that you can have also file-system namespaces for example. Perfect, in newer Linux distros gai is used in place of older resolver. To exit a namespace just exit the shell.
- gag on 2014-02-10 07:40:49 +0100
can i use mount namespace and pid namespace along with network namespace such that files in new mount namespace only accessible through network namespace . if yes how i create a mount and pid namespace and how to use in network namespace?
thanks
- Christian Pellegrin on 2014-02-10 08:14:28 +0100
Yes, you can do with the setns tool but I don’t know if it makes sense. Perhaps if you need PID and FS isolation too it’s better to go for a fully fledged solution like LXC
- Hubert on 2014-02-20 15:14:47 +0100
Many thanks for the infos..
One question though: Is it also possible to force a process to use a specific name server using namespaces, or is that more difficult?
- Christian Pellegrin on 2014-02-21 22:31:57 +0100
The resolver is configured by using
/etc/resolv.conf or
/etc/gai.conf
so a file-system namespace can be used to present different /etc/ directories to a process.
- Christian Pellegrin on 2014-02-22 07:30:21 +0100
Another clever trick to use a different DNS is to use NAT to rewrite the destination/source address only for DNS queries. Let’s say that in the global net namespace I use Google DNS
8.8.8.8
but in my specific net namespace I want to be a good Italian citizen and let Telecom Italia DNS85.37.17.51
decide what is good and what is evil. Now I can just do:
`
OLD_IP=8.8.8.8
NEW_IP=85.37.17.51iptables -t nat -A OUTPUT -p tcp -d $OLD_IP -j DNAT --dport 53 --to-destination $NEW_IP
iptables -t nat -A INPUT -p tcp -s $OLD_IP --sport 53 -j SNAT --to-source $NEW_IP
iptables -t nat -A OUTPUT -p udp -d $OLD_IP -j DNAT --dport 53 --to-destination $NEW_IP
iptables -t nat -A INPUT -p udp -s $OLD_IP --sport 53 -j SNAT --to-source $NEW_IP
` Now you can check that uploaded.net resolves to 127.0.0.1 for example by using wireshark with a filter like `(tcp.port == 53 || udp.port==53) && ip.addr == 10.0.10.149` on the physical `eth0` interface, assumed that the IP for your net namespace is `10.0.10.149`. In this way you don’t have to mess with different configuration files.
- Federico Pellegrin on 2014-02-22 07:52:09 +0100
In quite old iptables version there was also the –cmd-owner flag to apply a rule to a process (per name) that could suit also the question. But this was removed at some point in 2.6 kernels. There is still –pid-owner that could fit with a little of scripting.
Otherwise there is still the possibility to filter on UID/GID (with –uid-owner and -gid-owner).
They are all related to the owner module (so use -m owner)
Ciao!