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.
Pingback: Binding applications to a specific IP - Daniel Lange's blog