Linux network namespaces

Recently I've been spending time playing with Linux network namespaces, and I REALLY like what I've been seeing.

Essentially, Linux network namespaces (netns) is very similar to virtual routing and forwarding in Cisco routers. NetNS allows me to have multiple virtual IP stacks / IPTables firewalls / routing tables / etc. all without the overhead of a full virtual machine. Many people may be aware that NetNS is used by things like LXC and Docker, but I doubt that many people will use NetNS by its self.

Below is a relatively simple scenario that I labed with NetNS this morning to make sure that something worked the way that I wanted it to. Specifically, what I was testing for Linux IP / subnet migrations.

Note:

Here's the command sequence...

alias ip='sudo ip'                                  # ip alias created for dotFiles readers convenience
alias vrf1='ip netns exec vrf1'                     # Create the vrf# aliases because I'm too layz to
alias vrf2='ip netns exec vrf2'                     # type 'ip netns exec vrf#' all the time.
alias vrf3='ip netns exec vrf3'                     #
ip netns add vrf1                                   # Create three new network namespaces
ip netns add vrf2                                   #
ip netns add vrf3                                   #
vrf1 ip link add vrf2 type veth peer name vrf1      # Create a pair of virtual ethernet interfaces in the vrf1 NetNS.
vrf1 ip link set vrf1 netns vrf2                    # Move the vrf1 interface into the vrf2 NetNS.
vrf2 ip link add vrf3 type veth peer name vrf2      #
vrf2 ip link set vrf2 netns vrf3                    #
vrf1 ip link set lo up                              # Bring up the interfaces in the vrf1 NetNS.
vrf1 ip link set vrf2 up                            #
vrf2 ip link set lo up                              # vrf2 ...
vrf2 ip link set vrf1 up                            #
vrf2 ip link set vrf3 up                            #
vrf3 ip link set lo up                              # vrf3 ...
vrf3 ip link set vrf2 up                            #
vrf1 ip addr add dev vrf2 10.0.0.1/24               # Assing some IP addresses to interfaces.
vrf2 ip addr add dev vrf1 10.0.0.2/24               #
vrf2 ip addr add dev vrf3 10.0.1.2/24               #
vrf3 ip addr add dev vrf2 10.0.1.3/24               #
vrf1 ip route add default via 10.0.0.2              # Set the default gateway in vrf1 & vrf3 to be vrf2.
vrf3 ip route add default via 10.0.1.2              #
echo "1" | vrf2 tee /proc/sys/net/ipv4/ip_forward   # Make sure that IP forwarding is enabled in vrf2.
vrf1 ping -c 1 10.0.0.2                             # Make sure that vrf1 can ping vrf2 - direct
vrf2 ping -c 1 10.0.0.1                             # Make sure that vrf2 can ping vrf1 - direct
vrf2 ping -c 1 10.0.1.3                             # Make sure that vrf2 can ping vrf3 - direct
vrf3 ping -c 1 10.0.1.2                             # Make sure that vrf3 can ping vrf2 - direct
vrf1 ping -c 1 10.0.1.3                             # Make sure that vrf1 can ping vrf3 - routed
vrf3 ping -c 1 10.0.0.1                             # Make sure that vrf3 can ping vrf1 - routed

You should be able to copy and paste those lines into your terminal verbatim. Even the comments are Bash friendly.

The astute reader might be wondering how creating three NetNS that could ping each other helped me test things for my Linux IP / subnet migrations article. The following commands add the new IP address on the machine, specifically vrf3.

vrf3 ip addr add dev vrf2 10.0.2.3/24                            # Add the new IP address to vrf3
vrf3 ip route add 10.0.2.0/24 dev vrf2 src 10.0.2.3 table test   # Populate the test routing table
vrf3 ip route add default via 10.0.2.2 table test                #
vrf3 ip rule add from 10.0.2.3 table test                        # Tell the kernel to use the test table for 10.0.2.3.
vrf1 ping -c 4 10.0.2.3                                          # This should fail.

Remember that we have to reconfigure the other equipment in the subnet.

vrf2 ip addr add 10.0.2.2/24 dev vrf3                            # Add the new IP address to vrf2
vrf1 ping -c 4 10.0.2.3                                          # This should succeed.

Finally, don't forget to clean up after testing.

ip netns del vrf1                                   # Delete the network namespaces.
ip netns del vrf2                                   #
ip netns del vrf3                                   #

As you can see, it's trivial to use Linux network namespaces (netns) to test things with very little setup. Further, you don't have to bother with spinning up a VM or a LXC.

Finally, here's a copy of the Linux network namespaces - Command Output if you want to take a look at it.