Skip to content
C Codeloom
Linux

Linux Network Namespaces Tutorial

Hands-on guide to Linux network namespaces. Create isolated network stacks, connect them with veth pairs, and understand how containers get networking.

·4 min read · By Codeloom
Intermediate 9 min read

What you'll learn

  • What network namespaces actually isolate
  • How to create and inspect netns
  • How veth pairs bridge two namespaces
  • How NAT and routing work across netns
  • How containers reuse these primitives

Prerequisites

  • Familiar with shell
  • Root access on a Linux box

What and Why

A network namespace is a Linux kernel feature that gives a process its own private view of the network stack: interfaces, routing table, ARP cache, iptables rules, sockets. Two processes in different netns might both bind to port 80 without conflict, because each sees its own loopback and its own interfaces.

This is one of the primitives behind container runtimes like Docker, containerd, and Kubernetes. Understanding netns directly demystifies a huge chunk of “how does container networking work”.

Mental Model

By default every process lives in the host network namespace, which sees the physical NIC, the host routing table, and the host firewall rules. When you create a new netns, you get a completely empty network stack: no interfaces (not even loopback up), no routes, no rules. From there, you wire it up to the host using virtual cables called veth pairs.


 +---------------+        +---------------+
 |  host netns   |        |  ns1 netns    |
 |               |        |               |
 |   veth-host---+========+---veth-ns1    |
 |   10.0.0.1/24 |        |   10.0.0.2/24 |
 |               |        |               |
 |  default GW   |        |  default GW   |
 |   eth0 ---> internet   |   10.0.0.1    |
 +---------------+        +---------------+
Two namespaces wired with a veth pair

Hands-on Example

Create a namespace and inspect it:

sudo ip netns add ns1
sudo ip netns list
sudo ip netns exec ns1 ip addr

You will see only a lo interface that is DOWN. Bring it up:

sudo ip netns exec ns1 ip link set lo up

Now create a veth pair and move one end into ns1:

sudo ip link add veth-host type veth peer name veth-ns1
sudo ip link set veth-ns1 netns ns1
sudo ip addr add 10.0.0.1/24 dev veth-host
sudo ip link set veth-host up
sudo ip netns exec ns1 ip addr add 10.0.0.2/24 dev veth-ns1
sudo ip netns exec ns1 ip link set veth-ns1 up

Test connectivity:

sudo ip netns exec ns1 ping -c1 10.0.0.1

To reach the internet from inside ns1, add a default route and enable forwarding and NAT on the host:

sudo ip netns exec ns1 ip route add default via 10.0.0.1
sudo sysctl -w net.ipv4.ip_forward=1
sudo iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -o eth0 -j MASQUERADE

Now ip netns exec ns1 curl https://example.com works. You have essentially built what Docker calls a bridge network, by hand.


 ns1 app
    |
    v
 veth-ns1 (10.0.0.2)
    |
    v
 veth-host (10.0.0.1) in host
    |
    v
 host routing -> eth0
    |
    v
 POSTROUTING MASQUERADE
    |
    v
 internet
Outbound packet path from a namespace

Common Pitfalls

Forgetting that lo is DOWN by default in a new netns. Many apps bind to 127.0.0.1; if loopback is down, they error immediately.

Veth pairs are bidirectional, but if one end has no IP, packets go nowhere. Both ends need addresses and link set up.

Removing a namespace while a veth exists leaks the host side. Always ip link del veth-host before or after ip netns del ns1.

Conntrack confusion across netns. Each namespace has its own conntrack table, so port mappings or NAT rules on the host do not apply inside the namespace.

Permissions: ip netns commands need root or the CAP_NET_ADMIN capability. Inside a netns, your view of /proc/net reflects only that namespace, which can confuse monitoring agents.

Practical Tips

Use nsenter -t <pid> -n to drop into the network namespace of any running process. It is invaluable for debugging containers: find the container PID with docker inspect and nsenter into its netns to run ss, tcpdump, or iptables -L from inside.

For repeatable lab setups, script the namespace creation. Tools like ip-netns integrate cleanly with systemd if you want a long-lived isolated network for a service.

When experimenting with Kubernetes networking (CNI plugins, kube-proxy modes), recreate the topology by hand first. Once you understand which veth talks to which bridge, the CNI diagrams click instantly.

Combine netns with cgroups to build container-like isolation in a few lines. unshare --net --pid --mount --fork bash gives you a quick sandbox.

Wrap-up

Network namespaces are the kernel building block for container networking. With ip netns, ip link, and a couple of iptables rules, you can recreate a Docker bridge network from scratch. The same primitives underpin Kubernetes CNI plugins, VPN tunnels, and security sandboxes. Once you can build the topology by hand, the abstractions on top stop feeling magical.