Spekii

Spekii

Sunday, September 15, 2013

Network labs with Linux namespaces...

If like me you need to build many network testing environments, and you feel that is a pain to spawn many virtual servers only to realize some little networking tests, namespaces are made for you !


Linux namespaces


The purpose of the namespaces is to wrap system resources in a way that makes that a process associated to the namespaces has its own version of these resources.

 Currently there are six kind of namespaces:

  •     network namespaces, we are going to use these ones.
  •     User namespaces
  •     PID namespaces
  •     UTS namespaces
  •     IPC namespaces
  •     Mount namespaces

Your first lab


First, assume we want to connect two virtual servers to a network. So to achieve this topology we are going to create two network namespaces which will act as two nodes.

The following lines create the two namespaces :

# ip netns add vm1
# ip netns add vm2

Now that we have two namespaces, we need to create the network interfaces for both of them.

Following lines create a virtual Ethernet (veth) pair :

# ip link add name vm1-eth0 type veth peer name vm1-eth0.1
# ip link add name vm2-eth0 type veth peer name vm2-eth0.1

Now we need to add one veth to a namespace for each node :

# ip link set vm1-eth0.1 netns vm1
# ip link set vm2-eth0.1 netns vm2

Every network namespace comes with its own loopback interface. We need to set all interfaces belonging to a namespace to up.

# ip netns exec vm1 ip l set lo up
# ip netns exec vm1 ip l set vm1-eth0.1 up
# ip netns exec vm2 ip l set lo up
# ip netns exec vm2 ip l set vm2-eth0.1 up

By the way, we can see above that to be able to execute a command in a namespace context, we just need to use the following command template :

# ip netns exec <NS> <COMMAND>

Now let's add addresses :

# ip netns exec vm1 ip a add 192.168.0.1 dev vm1-eth0.1
# ip netns exec vm2 ip a add 192.168.0.2 dev vm2-eth0.1

And the routes :

# ip netns exec vm1 ip r add 192.168.0.0/24 dev vm1-eth0.1
# ip netns exec vm2 ip r add 192.168.0.0/24 dev vm2-eth0.1

Now it's the time to connect both nodes together. To achieve this, we can either use a bridge or a virtual switch like Openvswitch.

Let's see with a bridge :

# brctl addbr br1
# ip l set br1 up

# ip l set vm1-eth0 up
# brctl addif br1 vm1-eth0

# ip l set vm2-eth0 up
# brctl addif br1 vm2-eth0

Or with Openvswitch :

# ovs-vsctl add-br br1
# ip l set br1 up

# ip l set vm1-eth0 up
# ovs-vsctl add-port br1 vm1-eth0

# ip l set vm2-eth0 up
# ovs-vsctl add-port br1 vm2-eth0

Finally you should be able to ping a node from the other one.

# ip netns exec vm1 ping 192.168.0.2

Here the full script :
#!/bin/sh

ip netns add vm1
ip netns add vm2
ip link add name vm1-eth0 type veth peer name vm1-eth0.1
ip link add name vm2-eth0 type veth peer name vm2-eth0.1
ip link set vm1-eth0.1 netns vm1
ip link set vm2-eth0.1 netns vm2
ip netns exec vm1 ip l set lo up
ip netns exec vm1 ip l set vm1-eth0.1 up
ip netns exec vm2 ip l set lo up
ip netns exec vm2 ip l set vm2-eth0.1 up
ip netns exec vm1 ip a add 192.168.0.1 dev vm1-eth0.1
ip netns exec vm2 ip a add 192.168.0.2 dev vm2-eth0.1
ip netns exec vm1 ip r add 192.168.0.0/24 dev vm1-eth0.1
ip netns exec vm2 ip r add 192.168.0.0/24 dev vm2-eth0.1
brctl addbr br1
ip l set br1 up
ip l set vm1-eth0 up
brctl addif br1 vm1-eth0
ip l set vm2-eth0 up
brctl addif br1 vm2-eth0

ip netns exec vm1 ping 192.168.0.2 -c 5

This article was just a little introduction of the huge possibilities offered by namespaces.