Network Namespaces: Multiple Networks on One Linux Host
Network namespaces are one of the most powerful features in the Linux kernel. They allow a single Linux system to host multiple independent network stacks, making one machine behave like many separate computers. Every container runtime relies on this feature.
Learning Objectives
By the end of this chapter, you will be able to:
- Understand what a network namespace is
- Explain why network namespaces exist
- Create and delete network namespaces
- Execute commands inside namespaces
- Move interfaces between namespaces
- Understand what resources are isolated
- Observe how namespaces change the kernel's view of networking
- Troubleshoot namespaces using standard Linux tools
The Problem
Consider a normal Linux system.
+--------------------------------+
| Linux Kernel |
| |
| Interfaces |
| lo |
| eth0 |
| |
| Routing Table |
| Neighbor Table |
| Firewall Rules |
| Listening Sockets |
+--------------------------------+
Every process on the system shares the same network stack.
If one process adds a route:
ip route add 10.100.0.0/24 via 192.168.1.1
every process immediately sees that route.
If one process starts listening on port 80:
python3 -m http.server 80
no other process can also listen on TCP port 80 using the same IP address.
Everything shares the same networking environment.
For traditional servers, this is exactly what we want.
For containers and virtual environments, it is not.
Why Containers Need Isolation
Imagine running three web applications.
Host
Application A
Application B
Application C
Each application expects to listen on:
TCP port 80
Without isolation:
Application A → Port 80 ✓
Application B → Port 80 ✗
Address already in use
Application C → Port 80 ✗
Address already in use
Only one application can own the port.
Now imagine each application has its own network stack.
Namespace A
------------
eth0
lo
Port 80
Namespace B
------------
eth0
lo
Port 80
Namespace C
------------
eth0
lo
Port 80
Now every application can use port 80 simultaneously because they are listening inside different network namespaces.
This is exactly how containers work.
What Is a Network Namespace?
A network namespace is an isolated networking environment managed by the Linux kernel.
Each namespace has its own:
- network interfaces
- routing table
- neighbor (ARP/NDP) table
- firewall rules
- connection tracking table
- sockets
/proc/net- network-related sysctls (many are namespace-specific)
A process inside one namespace cannot directly see the networking resources of another namespace.
Think of a network namespace as giving a process its own private networking world.
One Kernel, Multiple Network Stacks
The important thing to understand is that namespaces do not create multiple kernels.
There is still only one Linux kernel.
Linux Kernel
+-------------------------------+
| |
| Namespace A |
| Namespace B |
| Namespace C |
| Namespace D |
| |
+-------------------------------+
The kernel simply maintains multiple independent networking contexts.
Every packet is processed by the same kernel, but inside the correct namespace.
The Default Namespace
When Linux boots, it automatically creates one network namespace.
This is called the initial namespace (sometimes informally called the root namespace).
Unless you explicitly create another namespace, every process runs here.
+--------------------------------+
| Initial Namespace |
| |
| Interfaces |
| lo |
| eth0 |
| |
| Routing Table |
| Neighbor Table |
| Firewall Rules |
| Listening Sockets |
+--------------------------------+
Everything you've learned so far in this book has taken place inside this initial namespace.
Listing Network Namespaces
Most Linux systems use the ip command to manage namespaces.
List all named namespaces:
ip netns list
A new installation usually returns nothing:
<no output>
That does not mean no namespace exists.
It simply means no additional named namespaces have been created.
The initial namespace is always present but is not shown by ip netns list.
Creating a Namespace
Create a namespace called web:
sudo ip netns add web
Now list namespaces:
ip netns list
Output:
web
Create another:
sudo ip netns add database
Now:
web
database
Each namespace has its own completely independent networking stack.
Where Are Namespaces Stored?
After creating a namespace:
ip netns add web
look inside:
ls -l /var/run/netns
Example:
web
database
These are bind mounts that allow the namespace to be referenced by name.
The actual namespace object exists inside the Linux kernel.
Running Commands Inside a Namespace
To execute a command inside a namespace:
sudo ip netns exec web ip addr
Output:
1: lo: <LOOPBACK>
Notice something surprising.
There is no eth0.
Only the loopback interface exists.
Every new namespace starts almost empty.
Looking at Interfaces
Compare the host:
ip addr
Example:
lo
eth0
Now compare the namespace:
ip netns exec web ip addr
Example:
lo
The namespace cannot see the host's interfaces.
This is the first demonstration that namespaces isolate networking resources.
Looking at Routes
Host:
ip route
Example:
default via 192.168.1.1
192.168.1.0/24 dev eth0
Namespace:
ip netns exec web ip route
Output:
<no output>
No interfaces means no routes.
Every namespace owns its own routing table.
Looking at Neighbor Entries
Host:
ip neigh
Example:
192.168.1.1 dev eth0 lladdr 00:11:22:33:44:55
Namespace:
ip netns exec web ip neigh
Output:
<no output>
Neighbor tables are isolated as well.
Looking at Listening Sockets
Host:
ss -lnt
Namespace:
ip netns exec web ss -lnt
Initially:
State Recv-Q Send-Q Local Address:Port
No listening sockets exist because no applications are running inside that namespace.
The Loopback Interface
Every namespace contains its own loopback interface.
Initially it is down.
Verify:
ip netns exec web ip addr
Example:
lo: <LOOPBACK>
Bring it up:
sudo ip netns exec web ip link set lo up
Verify:
ip netns exec web ip addr
Now:
lo: <LOOPBACK,UP,LOWER_UP>
Most container runtimes automatically enable loopback.
When working manually, you must remember to do it yourself.
Creating a Process Inside a Namespace
Start a shell:
sudo ip netns exec web bash
Your shell is now running inside the namespace.
Everything executed from this shell stays inside the namespace.
Check:
ip addr
Output:
lo
Exit normally:
exit
Demonstration: Independent Routing Tables
Create another namespace.
sudo ip netns add test
Bring up loopback:
sudo ip netns exec test ip link set lo up
Add a route:
sudo ip netns exec test ip route add blackhole 10.10.10.0/24
Check routes:
ip netns exec test ip route
Output:
blackhole 10.10.10.0/24
Now check the host:
ip route
The route does not exist.
The routing table is completely independent.
Namespace Isolation in Practice
Suppose we have two namespaces.
Linux Kernel
+---------------------------------------------+
Namespace A Namespace B
eth0 eth0
10.0.0.2 192.168.10.2
Route A Route B
Sockets A Sockets B
Firewall A Firewall B
+---------------------------------------------+
Although both namespaces run inside the same kernel, they behave like two independent Linux machines.
Neither knows the other's interfaces exist.
What Is Shared?
Namespaces isolate networking, not the entire operating system.
Processes still share:
- the Linux kernel
- CPU
- physical memory
- filesystem (unless other namespaces are used)
- kernel modules
- scheduler
Only networking resources are separated.
What Is Not Shared?
Each namespace has its own:
- interfaces
- IP addresses
- routing table
- neighbor table
- ARP cache
- sockets
- firewall rules
- connection tracking
- multicast memberships
/proc/net
This isolation is what makes containers practical.
Cleaning Up
Delete namespaces:
sudo ip netns delete web
sudo ip netns delete database
sudo ip netns delete test
Verify:
ip netns list
Output:
<no output>
Common Mistakes
Forgetting to Enable Loopback
Many commands fail because lo is still down.
Always run:
ip netns exec <namespace> ip link set lo up
Expecting eth0 to Exist
A newly created namespace contains no physical interfaces.
Interfaces must either be:
- moved into the namespace, or
- created inside it.
We'll learn both approaches in the next chapters.
Expecting Internet Access
A namespace has no connectivity by default.
Creating a namespace does not connect it to anything.
It is simply an isolated networking environment.
Key Takeaways
- A network namespace provides an isolated network stack inside the Linux kernel.
- The initial namespace is created automatically during boot and contains the host's normal networking configuration.
- Every namespace has its own interfaces, routing table, neighbor table, sockets, firewall rules, and connection tracking state.
- Newly created namespaces contain only a disabled loopback interface.
- Processes running in different namespaces can safely use the same IP addresses and port numbers because they belong to different networking contexts.
- Creating a namespace does not provide connectivity. Interfaces and links must be added explicitly.
Coming Next
A network namespace is an isolated networking environment, but by itself it cannot communicate with anything—not even another namespace.
In the next chapter, we'll introduce the Virtual Ethernet (veth) pair, one of the most fundamental Linux networking primitives. A veth pair acts like an Ethernet cable inside the kernel, allowing two namespaces to exchange packets as if they were connected by a physical wire. Nearly every container platform relies on this mechanism to connect isolated network namespaces to the outside world.