Network Namespaces: Isolating VM Networking

Published: (November 29, 2025 at 05:31 PM EST)
3 min read
Source: Dev.to

Source: Dev.to

Introduction

In previous articles I discussed various networking approaches for Linux virtualization and introduced qcontroller, a tool that manages the full lifecycle of QEMU VM instances.
qcontroller also configures firewall settings with nftables. The original scheme used bridges, TAP devices, and host‑wide nftables rules, which polluted the host networking stack and required careful manual cleanup when removing VMs.

Linux network namespaces provide a way to isolate all networking components so that deleting a single namespace automatically removes everything created inside it.

What are Network Namespaces?

Network namespaces are a Linux kernel feature that gives each namespace its own:

  • Network devices
  • IPv4/IPv6 protocol stacks
  • Routing tables
  • Firewall rules
  • /proc/net, /sys/class/net, and related /proc/sys/net files
  • Port numbers (sockets)
  • UNIX‑domain abstract socket namespace

When a namespace is deleted, all devices (including veth pairs) that belong to it are destroyed automatically.

A veth device pair acts like a virtual Ethernet cable that can connect two namespaces (or a namespace and the host). This is the building block for providing internet connectivity to an isolated namespace.

Creating and Configuring a Network Namespace

# Create a new network namespace called 'example'
sudo ip netns add example

# Create a veth pair (virtual Ethernet cable)
sudo ip link add host-veth type veth peer name example-veth

# Move one end of the veth pair into the new namespace
sudo ip link set example-veth netns example

# Assign IP addresses
sudo ip addr add 192.168.26.1/24 dev host-veth               # Host side
sudo ip netns exec example ip addr add 192.168.26.2/24 dev example-veth  # Namespace side

# Bring both interfaces up
sudo ip link set dev host-veth up
sudo ip netns exec example ip link set dev example-veth up

Test connectivity:

sudo ip netns exec example ping -c 3 192.168.26.1

You should see replies from 192.168.26.1, confirming that the two namespaces can talk to each other while remaining isolated.

Enabling Internet Access

  1. Set a default route inside the namespace so that traffic is sent to the host side of the veth pair.

    sudo ip netns exec example ip route add default via 192.168.26.1
  2. Configure the host for forwarding and NAT (replace enp0s1 with your actual external interface).

    # Enable IP forwarding
    sudo sysctl -w net.ipv4.ip_forward=1
    
    # Allow established/related traffic back from the internet
    sudo iptables -A FORWARD -i enp0s1 -o host-veth -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
    
    # Allow new outgoing connections from the namespace
    sudo iptables -A FORWARD -i host-veth -o enp0s1 -j ACCEPT
    
    # Masquerade (NAT) the namespace subnet
    sudo iptables -t nat -A POSTROUTING -s 192.168.26.0/24 -o enp0s1 -j MASQUERADE

Test internet connectivity from the namespace:

sudo ip netns exec example ping -c 3 8.8.8.8

Successful replies indicate that the namespace now has internet access.

Adding a Bridge and TAP Devices for VMs

To run VMs inside the isolated namespace, create a bridge, move the IP address to the bridge, and attach VM TAP devices to it.

# 1. Create a bridge inside the namespace
sudo ip netns exec example ip link add name br0 type bridge

# 2. Move the IP address from the veth interface to the bridge
sudo ip netns exec example ip addr del 192.168.26.2/24 dev example-veth
sudo ip netns exec example ip addr add 192.168.26.2/24 dev br0

# 3. Attach the veth interface to the bridge
sudo ip netns exec example ip link set example-veth master br0

# 4. Bring the bridge up
sudo ip netns exec example ip link set br0 up

Now any VM TAP device that is attached to br0 will be part of the isolated network. When the example namespace is deleted, the bridge, veth pair, and all attached TAP devices disappear automatically, leaving the host networking clean.

Back to Blog

Related posts

Read more »