Using Linux Network Namespaces for per processes routing

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.

 

This entry was posted in Linux desktop and tagged , , , , . Bookmark the permalink.

15 Responses to Using Linux Network Namespaces for per processes routing

  1. Pingback: Binding applications to a specific IP - Daniel Lange's blog

Leave a Reply to gag Cancel reply

Your email address will not be published. Required fields are marked *

*