Linux network namespaces- A beginners guide

What is a Linux namespace?

A Linux namespace is an abstraction over certain resources in the operating system. Currently Linux provides 7 types of namespaces: PID, Network, Mount, UTS, Time, User, IPC.Think of namespace as a box; the box(namespace) type emulates certain system resources, which makes the process within this namespace appear isolated. So, for instance, network namespace emulates/encapsulates the system resources related to network interfaces(eth0, wlan0), route tables.

So, what is a network namespace then? Say you're installing a new Linux distro on your PC; this shares a single set of network interfaces, route table entries, firewall rules etc... If you change the entires of these routing tables or firewall rules, this change is shared across the entire OS. With network namespace, you can have different and separate instances of network interfaces and routing tables that operate independently. So each namespace will have its own set of interfaces, routing tables and firewall rules. Resources of one namespace are not visible to other namespaces, but the root namespace has visibility to all the resources across all the namespaces.

This might seem complex now, but these are best illustrated by creating a few namespaces and playing with them. Namespaces aren't some add-on feature or some library that you need to install; they are provided by the Linux kernel itself and are a prerequisite to run any process on the system.

Ip route tools are necessary to manage the network namespaces. Throughout this blog, I will be using Ubuntu 20.04. Use sudo apt-get install -y iproute2 to install the iproute2 suite.

Let's Play with namespaces

Let's start with the typical server-client topology. We will create two namespaces that will act like two isolated machines and then ping one namespace from the other. You need to be root user or prepend sudo for the following commands.

ip netns add server

This command will create a new namespace called server. To view all the network namespaces available in the system:

ls /var/run/netns

or via ip

ip netns list

Now create a client.

ip netns add client

Now we have two namespaces, server and client, let's establish a connection between these two.

Assigning Interfaces to the Network namespaces

Once we create namespaces next part is to assign interfaces to the namespaces and then configure those interfaces for network connectivity. You can assign physical interfaces or virtual ethernet(Veth) interfaces to these namespaces. But we will stick to veth interfaces in this post. Virtual Ethernet interfaces are an interesting construct; they always come in pairs, and they are connected like a tube—whatever comes in one veth interface will come out the other peer veth interface. As a result, you can use veth interfaces to connect a network namespace to the outside world via the "default" or "global" namespace where physical interfaces exist.

Let's see how this is done. First, we will create a veth pair:

ip link add veth0 type veth peer name veth1

This command will create a link between the veth0 interface of type virtual ethernet (veth) and link it with the veth1 interface. When I was exploring the network namespaces, this command was repeated so that veth1 is connected to veth0, but when the above command creates two interfaces and links them automatically.

To verify whether the veth pair was created using the command:

ip link list

You might see a few interfaces other than the above veth interfaces; this is because the veth interfaces we created are in default or global namespace, which contains other physical interfaces. Now we will move these interfaces to the server and client namespaces.

ip link set veth0 netns server

This sets the veth0 interface to the sever namespace. Now, if you try to list all the interfaces in the global namespace, you'll see the veth0 has disappeared from the global namespace. This is because, through the above command, we moved the veth0 interface to the server namespace. Similarly we will move veth1 interface to client namespace.

ip link set veth1 netns client

So how can we confirm that the veth0 and veth1 interfaces were moved to the namespaces? Again we will run ip link list command, but this time inside the namespace.

ip netns exec server ip link list

That looks like a complicated command; let's break it down.

  1. The first part, ip netns exec, is how we run different commands inside a particular namespace.
  2. server is the name of the namespace where you want to run the command.
  3. Final part is the actual command to be executed inside the namespace. In this case, to list all the interfaces, so ip link list.

When you execute this command, you should see the loopback and veth0 interface that we moved earlier.

configuring the interfaces in network namespaces

Now we have moved the interfaces to their namespaces; now, we need to configure this interface. Once again, we'll use ip netns exec command, this time to configure the interface.

ip netns exec server ip addr add 10.0.0.2/24 dev veth0

The above command ip addr add 10.0.0.2/24 dev veth0 assigns the specified IP(10.0.0.2) to the veth0 interface. Similarly, we assign a IP to veth1 in client namespace.

ip netns exec client ip addr add 10.0.0.3/24 dev veth1

Now we have configured the interface in the namespace. But still if you list the interfaces(ip netns exec client ip addr you'll see the interface veth1 has been assigned IP address, but the interface itself is DOWN.

veth1@if27: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
    link/ether da:83:ce:d6:09:f4 brd ff:ff:ff:ff:ff:ff link-netns server
    inet 10.0.0.2/24 scope global veth1

So next step would be to bring the interfaces UP

sudo ip netns exec server ip link set dev veth0 up
sudo ip netns exec client ip link set dev veth1 up

Now everything's set up and working fine. How do we test this though? Simple, following our goal, we will ping one namespace from the other. Similar to how we ping a particular IP to see whether we are connected.

Summary

A network namespace is logically another copy of the network stack, with its own routes, firewall rules, and network devices. Network namespaces are a lightweight mechanism for resource isolation. Processes attached to a network namespace see their own network stack while not interfering with the rest of the system's network stack. Network namespaces are easy to use too.

Similar network-level isolation could have been set up using a VM. However, that seems a much more expensive solution for system resources and time investment to build up such an environment. If you only need process isolation at the networking level, network namespaces are definitively something to consider.

Did you find this article valuable?

Support Balajinaidu by becoming a sponsor. Any amount is appreciated!