In this article we will demonstrate the use of the “network” namespace which enables a process to have independent IPv4 and IPv6 stacks, network interfaces, IP routing tables, iptables firewall rules, the /proc/net and /sys/class/net directory trees, sockets, etc.
First we start by creating a pair of “veth” network interfaces:
ip link add v-eth1 type veth peer name v-peer1 ip link set v-eth1 up ip link set v-peer1 up
One of those interfaces will be used as a communication point from the side of the original default network namespace. We will assign “10.200.1.1” for IP address:
ifconfig v-eth1 10.200.1.1 netmask 255.255.255.0 up
It is time to enter the new network namespace. Once we have created the new namespace, we will associate the second interface “v-peer1” with it, then we will configure an IP address “10.200.1.2” and add a default route through the first interface which will act as a router:
export MAIN_NS_PID="$$" unshare -n /bin/bash # # We are in a "/bin/bash" session in the NEW network namespace now. # ip link set lo up # activate the "loopback" interface nsenter --net="/proc/$MAIN_NS_PID/ns/net" ip link set v-peer1 netns "$$" # join "v-peer1" into this namespace ifconfig v-peer1 10.200.1.2 netmask 255.255.255.0 up route add default gw 10.200.1.1 dev v-peer1 # # Setup is done. # You can now drop privileges and launch a daemon which will use this confined network namespace. # sudo -u www-data /etc/init.d/my-net-daemon start
The original default namespace, our original Linux installation, must be configured to act as a router. Otherwise the processes inside the new network namespace won’t have any Internet access. Configuring a Linux network router is a straightforward task:
echo 1 > /proc/sys/net/ipv4/ip_forward iptables -P FORWARD DROP iptables -F FORWARD iptables -t nat -F iptables -t nat -A POSTROUTING -s 10.200.1.0/255.255.255.0 -o eth0 -j MASQUERADE iptables -A FORWARD -i eth0 -o v-eth1 -j ACCEPT iptables -A FORWARD -o eth0 -i v-eth1 -j ACCEPT
Finally, you can enable inbound connections to the processes in the confined new network namespace. Let’s assume that you have a daemon listening on TCP port 10105. Here is how you can forward any new incoming connections to the processes inside the new network namespace:
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 10105 -j DNAT --to-destination 10.200.1.2
Pros: Using separate network namespaces gives us full network isolation and control over a group of processes. Additionally, we can match incoming packets against a process which is not possible in a standard “iptables” setup using the “-m owner” match extension. These are huge security benefits.
Cons: The technical implications are that the Linux host has to do (a lot) more work because of the DNAT/SNAT operations and their related connection tracking overhead. If you are running a high traffic server, you should plan and test accordingly. Furthermore, one additional network interfaces pair is created for each new network namespace. Linux can handle hundreds of network devices but still this is a factor to be considered.
The better security features outweigh the drawbacks in most use-cases though. Last but not least, it is very easily to run a process with completely detached network and this won’t cost us anything on the Linux host.
- Some notes on veth interfaces [main source of technical inspiration]
- Block network access of a process? [lists all different approaches]
- Command to run a child process “offline” (no external network) on Linux
- Introducing Linux Network Namespaces
- man page of “nsenter” [run program with namespaces of other processes]