Linux network namespaces are a fundamental kernel feature that enables network isolation, forming the backbone of modern containerization technologies like Docker and Kubernetes. Understanding network namespaces is essential for anyone working with containers, networking, or system administration. This guide provides comprehensive coverage of network namespaces, from basic concepts to advanced implementation patterns.
Introduction to Linux Namespaces
Namespaces are a Linux kernel feature that partitions kernel resources so that one set of processes sees one set of resources while another set of processes sees a different set. Linux provides several types of namespaces:
- PID: Process ID isolation
- NET: Network stack isolation
- MNT: Mount point isolation
- UTS: Hostname and domain name isolation
- IPC: Inter-process communication isolation
- USER: User and group ID isolation
- CGROUP: Control group isolation
Network namespaces specifically isolate network resources, providing each namespace with its own network stack, including network interfaces, routing tables, firewall rules, and sockets.
Network Namespace Fundamentals
What Gets Isolated in Network Namespaces
Each network namespace contains:
- Network interfaces: Physical or virtual NICs
- IPv4 and IPv6 protocol stacks: Independent IP addressing
- Routing tables: Separate routing decisions
- Firewall rules: Independent iptables/nftables rules
- Port numbers: Same port can be used in different namespaces
- UNIX domain sockets: Network-type sockets
/proc/netdirectory: Per-namespace network information/sys/class/netdirectory: Per-namespace network device info
Default Network Namespace
The root (default) network namespace contains all network resources when the system boots. All processes inherit this namespace unless explicitly moved to another.
Creating and Managing Network Namespaces
Basic Commands with ip netns
The ip command from the iproute2 package manages network namespaces.
Create a network namespace:
sudo ip netns add myns
List network namespaces:
sudo ip netns list
Delete a network namespace:
sudo ip netns delete myns
Execute command in namespace:
sudo ip netns exec myns <command>
For example:
# Run bash shell in namespace
sudo ip netns exec myns bash
## Check interfaces in namespace
sudo ip netns exec myns ip link show
## Check routing table
sudo ip netns exec myns ip route show
Understanding Namespace Persistence
Network namespaces created with ip netns are persisted as bind mounts in /var/run/netns/:
ls -l /var/run/netns/
This persistence allows namespaces to exist even when no processes are running in them.
Exploring a New Namespace
When you create a new network namespace, it starts empty:
## Create namespace
sudo ip netns add test
## Check interfaces (only loopback exists, and it's down)
sudo ip netns exec test ip link show
## Check routing
sudo ip netns exec test ip route show
## Check IP addresses
sudo ip netns exec test ip addr show
Output shows only the loopback interface in DOWN state:
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
Enable the loopback interface:
sudo ip netns exec test ip link set lo up
sudo ip netns exec test ip addr show lo
Connecting Network Namespaces
Namespaces start isolated. To enable communication, we need to create connections.
Virtual Ethernet (veth) Pairs
veth pairs are virtual ethernet devices that act like a network cable—packets sent into one end come out the other. They’re the primary mechanism for connecting namespaces.
Create veth pair:
## Create pair named veth0 and veth1
sudo ip link add veth0 type veth peer name veth1
View the pair:
ip link show type veth
Move one end to namespace:
## Create namespace
sudo ip netns add ns1
## Move veth1 to ns1
sudo ip link set veth1 netns ns1
Now veth1 doesn’t appear in the default namespace:
ip link show veth1 # Not found
sudo ip netns exec ns1 ip link show veth1 # Found in ns1
Configure IP addresses and bring up:
## Configure veth0 in default namespace
sudo ip addr add 10.0.0.1/24 dev veth0
sudo ip link set veth0 up
## Configure veth1 in ns1
sudo ip netns exec ns1 ip addr add 10.0.0.2/24 dev veth1
sudo ip netns exec ns1 ip link set veth1 up
Test connectivity:
ping -c 3 10.0.0.2
sudo ip netns exec ns1 ping -c 3 10.0.0.1
Connecting Two Namespaces
Create two isolated namespaces and connect them:
## Create namespaces
sudo ip netns add red
sudo ip netns add blue
## Create veth pair
sudo ip link add veth-red type veth peer name veth-blue
## Move interfaces to namespaces
sudo ip link set veth-red netns red
sudo ip link set veth-blue netns blue
## Configure red namespace
sudo ip netns exec red ip addr add 192.168.1.1/24 dev veth-red
sudo ip netns exec red ip link set veth-red up
sudo ip netns exec red ip link set lo up
## Configure blue namespace
sudo ip netns exec blue ip addr add 192.168.1.2/24 dev veth-blue
sudo ip netns exec blue ip link set veth-blue up
sudo ip netns exec blue ip link set lo up
## Test connectivity
sudo ip netns exec red ping -c 3 192.168.1.2
sudo ip netns exec blue ping -c 3 192.168.1.1
Bridge Networks and Namespaces
For connecting multiple namespaces, bridges are more scalable than point-to-point veth pairs.
Creating a Bridge
## Create bridge
sudo ip link add br0 type bridge
sudo ip link set br0 up
sudo ip addr add 10.0.0.1/24 dev br0
Connecting Multiple Namespaces to Bridge
## Create three namespaces
for i in 1 2 3; do
sudo ip netns add ns$i
done
## Create veth pairs and connect to bridge
for i in 1 2 3; do
# Create veth pair
sudo ip link add veth$i type veth peer name veth-br$i
# Connect one end to bridge
sudo ip link set veth-br$i master br0
sudo ip link set veth-br$i up
# Move other end to namespace
sudo ip link set veth$i netns ns$i
# Configure in namespace
sudo ip netns exec ns$i ip addr add 10.0.0.$((i+1))/24 dev veth$i
sudo ip netns exec ns$i ip link set veth$i up
sudo ip netns exec ns$i ip link set lo up
done
Test connectivity between namespaces:
sudo ip netns exec ns1 ping -c 2 10.0.0.2
sudo ip netns exec ns1 ping -c 2 10.0.0.3
sudo ip netns exec ns2 ping -c 2 10.0.0.3
All namespaces can now communicate through the bridge.
Providing Internet Access to Namespaces
Namespaces isolated from the host need routing and NAT to access the internet.
Setup Internet Gateway
Assuming eth0 is your internet-connected interface:
## Enable IP forwarding
sudo sysctl -w net.ipv4.ip_forward=1
## Make permanent
echo "net.ipv4.ip_forward=1" | sudo tee -a /etc/sysctl.conf
## Configure NAT (iptables)
sudo iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -o eth0 -j MASQUERADE
sudo iptables -A FORWARD -i br0 -o eth0 -j ACCEPT
sudo iptables -A FORWARD -i eth0 -o br0 -m state --state RELATED,ESTABLISHED -j ACCEPT
Configure Default Route in Namespace
## Add default route via bridge
sudo ip netns exec ns1 ip route add default via 10.0.0.1
## Configure DNS
sudo mkdir -p /etc/netns/ns1
echo "nameserver 8.8.8.8" | sudo tee /etc/netns/ns1/resolv.conf
## Test internet connectivity
sudo ip netns exec ns1 ping -c 3 8.8.8.8
sudo ip netns exec ns1 ping -c 3 google.com
Advanced Namespace Operations
Running Services in Namespaces
Start a web server in an isolated namespace:
## Create and configure namespace
sudo ip netns add webserver
sudo ip link add veth-web type veth peer name veth-web-br
sudo ip link set veth-web-br master br0 up
sudo ip link set veth-web netns webserver
sudo ip netns exec webserver ip addr add 10.0.0.10/24 dev veth-web
sudo ip netns exec webserver ip link set veth-web up
sudo ip netns exec webserver ip link set lo up
sudo ip netns exec webserver ip route add default via 10.0.0.1
## Run Python HTTP server in namespace
sudo ip netns exec webserver python3 -m http.server 8080 &
## Access from another namespace
sudo ip netns exec ns1 curl http://10.0.0.10:8080
Port Forwarding to Namespaces
Forward traffic from host port to namespace service:
## Forward host port 8080 to namespace port 8080
sudo iptables -t nat -A PREROUTING -p tcp --dport 8080 -j DNAT --to-destination 10.0.0.10:8080
sudo iptables -A FORWARD -p tcp -d 10.0.0.10 --dport 8080 -j ACCEPT
## Now accessible from external network
curl http://<host-ip>:8080
Network Namespace with VLAN
Create namespace connected to VLAN:
## Create VLAN interface
sudo ip link add link eth0 name eth0.100 type vlan id 100
sudo ip link set eth0.100 up
## Create namespace
sudo ip netns add vlan-ns
## Create and configure veth pair
sudo ip link add veth-vlan type veth peer name veth-vlan-br
sudo ip link set veth-vlan netns vlan-ns
sudo ip link set veth-vlan-br master br0 up
## Configure in namespace
sudo ip netns exec vlan-ns ip addr add 10.100.0.2/24 dev veth-vlan
sudo ip netns exec vlan-ns ip link set veth-vlan up
sudo ip netns exec vlan-ns ip link set lo up
Container Networking Patterns
Docker-Style Container Networking
Docker creates network namespaces for containers and connects them via bridges.
Simulate Docker network model:
## Create docker-like bridge
sudo ip link add docker0 type bridge
sudo ip addr add 172.17.0.1/16 dev docker0
sudo ip link set docker0 up
## Create container namespace
sudo ip netns add container1
## Connect to bridge
sudo ip link add veth0 type veth peer name veth0-br
sudo ip link set veth0-br master docker0 up
sudo ip link set veth0 netns container1
## Configure container
sudo ip netns exec container1 ip addr add 172.17.0.2/16 dev veth0
sudo ip netns exec container1 ip link set veth0 up
sudo ip netns exec container1 ip link set lo up
sudo ip netns exec container1 ip route add default via 172.17.0.1
## Enable NAT
sudo iptables -t nat -A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
Multiple Isolated Networks
Create multiple isolated networks, each with its own bridge:
## Network 1: Frontend
sudo ip link add br-frontend type bridge
sudo ip addr add 10.1.0.1/24 dev br-frontend
sudo ip link set br-frontend up
## Network 2: Backend
sudo ip link add br-backend type bridge
sudo ip addr add 10.2.0.1/24 dev br-backend
sudo ip link set br-backend up
## Create container connected to both networks
sudo ip netns add app-container
## Connect to frontend
sudo ip link add veth-front type veth peer name veth-front-br
sudo ip link set veth-front-br master br-frontend up
sudo ip link set veth-front netns app-container
sudo ip netns exec app-container ip addr add 10.1.0.2/24 dev veth-front
sudo ip netns exec app-container ip link set veth-front up
## Connect to backend
sudo ip link add veth-back type veth peer name veth-back-br
sudo ip link set veth-back-br master br-backend up
sudo ip link set veth-back netns app-container
sudo ip netns exec app-container ip addr add 10.2.0.2/24 dev veth-back
sudo ip netns exec app-container ip link set veth-back up
## Now app-container has interfaces on both networks
sudo ip netns exec app-container ip addr show
Debugging Network Namespaces
Inspecting Namespace Configuration
List all interfaces:
sudo ip netns exec myns ip link show
Show IP addresses:
sudo ip netns exec myns ip addr show
Show routing table:
sudo ip netns exec myns ip route show
Show ARP cache:
sudo ip netns exec myns ip neigh show
Show firewall rules:
sudo ip netns exec myns iptables -L -n -v
sudo ip netns exec myns iptables -t nat -L -n -v
Testing Connectivity
Ping test:
sudo ip netns exec myns ping -c 3 10.0.0.1
Trace route:
sudo ip netns exec myns traceroute 8.8.8.8
Check listening ports:
sudo ip netns exec myns netstat -tulpn
## or
sudo ip netns exec myns ss -tulpn
sudo ip netns exec myns nslookup google.com
sudo ip netns exec myns dig google.com
TCP connectivity:
## Test with netcat
sudo ip netns exec myns nc -zv 10.0.0.1 80
Traffic Capture
Capture packets in namespace:
## Install tcpdump in namespace
sudo ip netns exec myns tcpdump -i veth0 -n
## Save to file
sudo ip netns exec myns tcpdump -i veth0 -w capture.pcap
## Analyze with wireshark
wireshark capture.pcap
Security Considerations
Namespace Isolation Limits
Network namespaces provide network-level isolation but:
- Share kernel: All namespaces share the same kernel
- Resource limits: No automatic resource limits (use cgroups)
- Root privileges: Root in namespace can affect host
- Side-channel attacks: Possible through shared kernel resources
Best Practices
- Combine with other namespaces: Use PID, mount, and user namespaces together
- Use user namespaces: Map root in namespace to non-root on host
- Apply resource limits: Use cgroups to limit CPU, memory, network bandwidth
- Firewall rules: Apply strict iptables rules per namespace
- Limit capabilities: Drop unnecessary Linux capabilities
- SELinux/AppArmor: Additional MAC layer protection
- Network policies: Implement network segmentation and policies
- Monitor activity: Log and monitor namespace network activity
Practical Automation Scripts
Script to Create Isolated Container
#!/bin/bash
NAMESPACE=$1
IP_ADDR=$2
if [ -z "$NAMESPACE" ] || [ -z "$IP_ADDR" ]; then
echo "Usage: $0 <namespace> <ip_address>"
exit 1
fi
## Create namespace
ip netns add "$NAMESPACE"
## Create veth pair
VETH="${NAMESPACE}-veth"
VETH_BR="${NAMESPACE}-veth-br"
ip link add "$VETH" type veth peer name "$VETH_BR"
## Attach to bridge (assume br0 exists)
ip link set "$VETH_BR" master br0
ip link set "$VETH_BR" up
## Move to namespace
ip link set "$VETH" netns "$NAMESPACE"
## Configure in namespace
ip netns exec "$NAMESPACE" ip addr add "$IP_ADDR/24" dev "$VETH"
ip netns exec "$NAMESPACE" ip link set "$VETH" up
ip netns exec "$NAMESPACE" ip link set lo up
ip netns exec "$NAMESPACE" ip route add default via 10.0.0.1
echo "Namespace $NAMESPACE created with IP $IP_ADDR"
Script to Clean Up Namespace
#!/bin/bash
NAMESPACE=$1
if [ -z "$NAMESPACE" ]; then
echo "Usage: $0 <namespace>"
exit 1
fi
## Delete namespace (automatically removes interfaces in it)
ip netns delete "$NAMESPACE"
## Clean up bridge interface if exists
VETH_BR="${NAMESPACE}-veth-br"
if ip link show "$VETH_BR" &>/dev/null; then
ip link delete "$VETH_BR"
fi
echo "Namespace $NAMESPACE deleted"
Performance Considerations
Network Namespace Overhead
Network namespaces have minimal performance impact:
- Context switching: Slight overhead when switching between namespaces
- veth throughput: Nearly native performance (90-95% of physical interface)
- Bridge overhead: Minimal impact for most workloads
- Memory usage: ~1MB per namespace for network stack
Optimization Tips
- Use veth offloading:
ethtool -K veth0 tx off rx off
- Increase queue length:
ip link set veth0 txqueuelen 10000
- Enable bridge fast path:
sysctl -w net.bridge.bridge-nf-call-iptables=0
sysctl -w net.bridge.bridge-nf-call-ip6tables=0
- Use jumbo frames if network supports:
ip link set veth0 mtu 9000
- Tune TCP settings per namespace:
ip netns exec myns sysctl -w net.ipv4.tcp_congestion_control=bbr
ip netns exec myns sysctl -w net.core.rmem_max=134217728
ip netns exec myns sysctl -w net.core.wmem_max=134217728
Integration with Container Runtimes
How Docker Uses Network Namespaces
Docker automatically:
- Creates network namespace per container
- Creates veth pair
- Connects one end to docker0 bridge
- Moves other end into container namespace
- Configures IP address and routing
- Sets up NAT for outbound traffic
- Configures DNS
View Docker network namespaces:
## Find container PID
docker inspect -f '{{.State.Pid}}' <container>
## Access its network namespace
sudo nsenter -t <PID> -n ip addr
How Kubernetes Uses Network Namespaces
Kubernetes CNI (Container Network Interface) plugins:
- Create network namespace for pod
- Configure networking per CNI plugin (Calico, Flannel, etc.)
- Assign IP from pod CIDR
- Set up routes for pod-to-pod communication
- Implement network policies
List pod network namespaces:
## On Kubernetes node
sudo ip netns list | grep cni
Related Articles
- Penetration Testing Reconnaissance
- Cloudflare Workers: Serverless Web Application
- Kubernetes and Container Orchestration
- What is Cyber Essentials, Cyber Essentials Plus and how do
Conclusion
Linux network namespaces provide powerful network isolation capabilities that form the foundation of modern container technologies. Understanding how to create, connect, and manage network namespaces is essential for working with containers, debugging networking issues, and implementing custom network topologies.
From simple point-to-point connections using veth pairs to complex multi-network architectures with bridges and NAT, network namespaces offer flexibility and isolation without significant performance overhead. Combined with other namespace types, cgroups, and security features, they enable secure, isolated environments for running applications.
Whether you’re troubleshooting Docker networking, implementing custom container solutions, or simply exploring Linux networking capabilities, mastering network namespaces opens up new possibilities for network architecture and isolation strategies.
References
- Linux Network Namespaces: https://man7.org/linux/man-pages/man7/network_namespaces.7.html
- iproute2 Documentation: https://wiki.linuxfoundation.org/networking/iproute2
- Container Networking: https://www.kernel.org/doc/Documentation/networking/
- Docker Networking: https://docs.docker.com/network/
- Kubernetes Networking: https://kubernetes.io/docs/concepts/cluster-administration/networking/