In modern Linux system administration, network virtualization is not limited to bulky hypervisors and heavy virtual machines. The Linux kernel features network namespaces—a lightweight, native isolation primitive that provides independent network stacks complete with their own routing tables, loopback adapters, firewall packet filters, interface listings, and socket allocations. Network namespaces form the foundational networking fabric powering container runtimes like Docker, Podman, and Kubernetes, as well as split-tunnel VPN configurations. Using the ip netns utility in Ubuntu, system administrators can create isolated network sandboxes, interconnect them with virtual ethernet cables, and run network daemons without risking host network cross-contamination.
Understanding Linux Network Namespaces
By default, all processes on a Linux host share the global (root) network namespace. When a service binds to 0.0.0.0:80, it claims port 80 across all physical adapters in that root namespace.
When an administrator provisions a new network namespace:
- The kernel instantiates a completely blank network stack containing only an unconfigured, down loopback interface.
- Processes spawned inside that namespace can only communicate over network interfaces explicitly moved into that namespace.
- Routing rules, iptables/nftables chains, and listening ports inside the namespace are totally invisible to the host and vice versa.
The ip netns command automates the management of these namespaces by binding persistent namespace descriptors under /var/run/netns/, enabling execution of standard POSIX utilities inside the sandbox via ip netns exec.
Creating and Listing Network Namespaces
Because creating and managing kernel namespaces involves network stack configuration, root privileges are required.
To create a new network namespace named isolated-lab, open a terminal and execute:
sudo ip netns add isolated-lab
To verify all active network namespaces currently configured on the system, run:
ip netns list
The terminal outputs the namespace name alongside its unique ID:
isolated-lab (id: 0)
The kernel mounts the namespace handle under /var/run/netns/isolated-lab.
Executing Commands Inside the Namespace
To run commands within the isolated namespace, prefix them with ip netns exec <namespace-name>.
Inspect the initial interface inventory of the sandbox:
sudo ip netns exec isolated-lab ip link show
Notice that only the loopback interface (lo) exists, and it is in the DOWN state. Bring the loopback adapter up:
sudo ip netns exec isolated-lab ip link set dev lo up
Now verify that local inter-process communication works inside the sandbox:
sudo ip netns exec isolated-lab ping -c 2 127.0.0.1
The ping packets route through the namespace’s private loopback adapter independently of the host’s loopback interface.
Interconnecting Namespaces Using Virtual Ethernet (veth) Pairs
An isolated namespace cannot communicate with the host or external internet until a network interface is assigned to it. The standard mechanism to connect namespaces is a virtual ethernet pair (veth), which behaves like a physical patch cable connecting two network jacks.
To create a veth pair named veth-host and veth-ns:
sudo ip link add veth-host type veth peer name veth-ns
Both ends of the virtual cable initially reside in the host namespace. Move the veth-ns endpoint into your isolated namespace:
sudo ip link set veth-ns netns isolated-lab
Notice that veth-ns disappears from the host’s ip link output and appears inside isolated-lab.
Configuring IP Addresses and Testing Communication
Assign private IP addresses to both ends of the virtual patch cable. On the host side, assign 10.200.1.1/24:
sudo ip addr add 10.200.1.1/24 dev veth-host
sudo ip link set dev veth-host up
Inside the namespace, assign 10.200.1.2/24 to veth-ns and bring the interface up:
sudo ip netns exec isolated-lab ip addr add 10.200.1.2/24 dev veth-ns
sudo ip netns exec isolated-lab ip link set dev veth-ns up
Test bi-directional communication between the host and the sandbox:
sudo ip netns exec isolated-lab ping -c 3 10.200.1.1
The packets traverse the virtual cable directly between the two isolated network stacks.
Routing Namespace Traffic to the External Internet via NAT
To grant the isolated namespace internet connectivity through the host’s physical network adapter (e.g., enp3s0):
1. Add a default gateway inside the namespace pointing to the host’s veth IP:
sudo ip netns exec isolated-lab ip route add default via 10.200.1.1
2. Enable IPv4 packet forwarding in the Linux kernel on the host:
sudo sysctl -w net.ipv4.ip_forward=1
3. Add an iptables Masquerade rule to NAT outbound traffic from the namespace:
sudo iptables -t nat -A POSTROUTING -s 10.200.1.0/24 -o enp3s0 -j MASQUERADE
sudo iptables -A FORWARD -i enp3s0 -o veth-host -j ACCEPT
sudo iptables -A FORWARD -i veth-host -o enp3s0 -j ACCEPT
Verify external connectivity from within the namespace:
sudo ip netns exec isolated-lab ping -c 3 1.1.1.1
The isolated namespace now has outbound internet access while maintaining separate listening sockets and routing tables.
Spawning an Interactive Shell Inside the Namespace
Rather than prepending ip netns exec before every administrative command, you can launch an interactive Bash subshell directly within the namespace:
sudo ip netns exec isolated-lab bash
Any commands, servers (such as Python http.server), or network utilities launched inside this subshell execute in complete network isolation.
Deleting Network Namespaces Cleanly
When your testing session or lab environment is finished, tear down the namespace using the delete command:
sudo ip netns delete isolated-lab
The kernel terminates all processes bound to the namespace, unmounts the descriptor handle from /var/run/netns/, and tears down the attached veth peer automatically.
Mastering ip netns empowers Ubuntu administrators and DevOps engineers to troubleshoot microsegmentation, test VPN routing, and architect secure container environments with minimal overhead.