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.