Skip to content

Network Namespaces & VRF - Virtual Network Isolation for Raspberry Pi

Introduction

Network namespaces and VRF (Virtual Routing and Forwarding) are powerful Linux kernel features that enable complete network isolation on a single device. They allow you to run multiple independent network stacks, each with its own routing tables, firewall rules, and network interfaces - all on one Raspberry Pi.

This technology enables sophisticated networking scenarios that were previously impossible without multiple physical devices:

  • Multiple VPN Connections: Connect to different VPNs simultaneously without conflicts
  • Network Segmentation: Isolate IoT devices, guest networks, and production services
  • Testing Environments: Test network configurations without affecting your main network
  • Multi-Tenant Systems: Run separate network environments for different users or services
  • Container Networking: Foundation of Docker, Kubernetes, and LXC networking
  • Security Isolation: Prevent network-based attacks from spreading between services
  • Traffic Engineering: Route different applications through different network paths

This comprehensive guide covers:

  • Network Namespaces: Create isolated network environments with separate interfaces and routing
  • VRF (Virtual Routing and Forwarding): Multiple routing tables for traffic separation
  • Virtual Ethernet (veth) Pairs: Connect namespaces and create virtual networks
  • Network Bridges: Build complex virtual network topologies
  • VPN Segmentation: Route different traffic through different VPN tunnels
  • Container Integration: Understand Docker and Kubernetes networking fundamentals
  • Practical Applications: Multi-VPN gateway, isolated test networks, secure IoT segments
  • Performance Tuning: Optimize virtual networking for Raspberry Pi

Perfect for:

  • Network Engineers: Advanced routing and traffic engineering
  • Security Professionals: Network isolation and segmentation
  • DevOps Engineers: Container networking and multi-environment setups
  • VPN Users: Multiple simultaneous VPN connections with policy routing
  • IoT Developers: Isolate untrusted devices on separate networks
  • System Administrators: Complex network topology management
  • Homelab Enthusiasts: Professional networking features on consumer hardware

Understanding Network Namespaces

What is a Network Namespace?

A network namespace is a Linux kernel feature that provides complete isolation of network resources. Each namespace has:

  • Network interfaces: Separate set of physical and virtual interfaces
  • IP addresses: Independent IP address assignments
  • Routing tables: Isolated routing decisions
  • Firewall rules: Separate iptables/nftables configurations
  • Network statistics: Independent /proc/net entries
  • Port bindings: Same port can be used in different namespaces

Default Network Namespace

# Every Linux system starts with one default namespace
# All processes run in this namespace unless moved

# View current namespace
ip netns identify $$
# (empty output = default namespace)

# List all network namespaces
ip netns list
# (empty if no custom namespaces created)

# View interfaces in default namespace
ip link show

# View routing table
ip route show

# View firewall rules
sudo iptables -L -n

Network Namespace Architecture

┌─────────────────────────────────────────────────────────────┐
│                    Physical Raspberry Pi                     │
├─────────────────────────────────────────────────────────────┤
│                                                               │
│  ┌─────────────────────┐      ┌─────────────────────┐       │
│  │  Default Namespace  │      │   Namespace "red"   │       │
│  │                     │      │                     │       │
│  │  eth0: 192.168.1.10│      │  veth-red: 10.1.0.2│       │
│  │  wlan0: DHCP       │      │  Routing: custom   │       │
│  │  lo: 127.0.0.1     │      │  iptables: custom  │       │
│  │                     │      │                     │       │
│  │  Routing: main     │      │  ┌──────────────┐  │       │
│  │  iptables: main    │      │  │Process A     │  │       │
│  │                     │      │  │(runs in red) │  │       │
│  │  ┌──────────────┐  │      │  └──────────────┘  │       │
│  │  │Default       │  │      │                     │       │
│  │  │processes     │  │      └─────────────────────┘       │
│  │  └──────────────┘  │                                     │
│  └─────────────────────┘      ┌─────────────────────┐       │
│                                │  Namespace "blue"   │       │
│                                │                     │       │
│                                │  veth-blue: 10.2.0.2│       │
│                                │  Routing: custom   │       │
│                                │  iptables: custom  │       │
│                                │                     │       │
│                                │  ┌──────────────┐  │       │
│                                │  │Process B     │  │       │
│                                │  │(runs in blue)│  │       │
│                                │  └──────────────┘  │       │
│                                └─────────────────────┘       │
│                                                               │
└─────────────────────────────────────────────────────────────┘

Creating and Managing Network Namespaces

Basic Namespace Operations

# Create a network namespace
sudo ip netns add red

# List all namespaces
ip netns list
# Output: red

# Create multiple namespaces
sudo ip netns add blue
sudo ip netns add green

# View all namespaces
ip netns list
# Output:
# green
# blue
# red

# Delete a namespace
sudo ip netns delete green

# Execute command in namespace
sudo ip netns exec red ip addr show
# Shows only lo interface (loopback), down by default

# Start bash shell in namespace
sudo ip netns exec red bash
# Now you're inside the "red" namespace
# Exit with 'exit' command

Namespace Isolation Demonstration

# Create test namespace
sudo ip netns add isolated

# Compare interface lists
echo "=== Default Namespace ==="
ip link show

echo "=== Isolated Namespace ==="
sudo ip netns exec isolated ip link show
# Only shows 'lo' (loopback), nothing else

# Try to ping from isolated namespace (will fail - no connectivity)
sudo ip netns exec isolated ping 8.8.8.8
# Error: Network is unreachable

# Bring up loopback in namespace
sudo ip netns exec isolated ip link set lo up

# Now can ping localhost
sudo ip netns exec isolated ping -c 3 127.0.0.1
# Works!

# But still no external connectivity
sudo ip netns exec isolated ping -c 1 8.8.8.8
# Error: Network is unreachable

Virtual Ethernet (veth) Pairs

veth pairs are virtual network cables - what goes in one end comes out the other.

Creating veth Pairs

# Create a veth pair
sudo ip link add veth0 type veth peer name veth1

# Both ends are in default namespace initially
ip link show | grep veth
# veth0@veth1: ...
# veth1@veth0: ...

# Move one end to a namespace
sudo ip link set veth1 netns red

# Now veth1 only visible in 'red' namespace
ip link show | grep veth
# Only shows veth0

sudo ip netns exec red ip link show
# Shows both lo and veth1

Connecting Namespace to Default Network

# Create namespace
sudo ip netns add red

# Create veth pair
sudo ip link add veth-red type veth peer name veth-red-br

# Move one end to namespace
sudo ip link set veth-red netns red

# Configure namespace side
sudo ip netns exec red ip addr add 10.1.0.2/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 default namespace side
sudo ip addr add 10.1.0.1/24 dev veth-red-br
sudo ip link set veth-red-br up

# Test connectivity
ping -c 3 10.1.0.2
# Success!

# From namespace to default
sudo ip netns exec red ping -c 3 10.1.0.1
# Success!

Adding Internet Access to Namespace

# Add default route in namespace
sudo ip netns exec red ip route add default via 10.1.0.1

# Enable IP forwarding on host
sudo sysctl -w net.ipv4.ip_forward=1

# Add NAT (masquerade) for namespace traffic
sudo iptables -t nat -A POSTROUTING -s 10.1.0.0/24 -o eth0 -j MASQUERADE

# Allow forwarding
sudo iptables -A FORWARD -i veth-red-br -o eth0 -j ACCEPT
sudo iptables -A FORWARD -i eth0 -o veth-red-br -m state --state RELATED,ESTABLISHED -j ACCEPT

# Test internet from namespace
sudo ip netns exec red ping -c 3 8.8.8.8
# Success!

sudo ip netns exec red curl -s https://ifconfig.me
# Shows public IP

Network Bridges for Complex Topologies

Creating a Bridge

1
2
3
4
5
6
7
8
# Create a bridge
sudo ip link add br0 type bridge

# Bring it up
sudo ip link set br0 up

# Assign IP to bridge
sudo ip addr add 10.10.0.1/24 dev br0

Connecting Multiple Namespaces via Bridge

#!/bin/bash
# multi-namespace-bridge.sh

# Create bridge
sudo ip link add br-ns type bridge
sudo ip link set br-ns up
sudo ip addr add 10.100.0.1/24 dev br-ns

# Function to create and connect namespace
create_namespace() {
    local NAME=$1
    local IP=$2

    # Create namespace
    sudo ip netns add $NAME

    # Create veth pair
    sudo ip link add veth-$NAME type veth peer name veth-$NAME-br

    # Move one end to namespace
    sudo ip link set veth-$NAME netns $NAME

    # Configure namespace side
    sudo ip netns exec $NAME ip addr add $IP/24 dev veth-$NAME
    sudo ip netns exec $NAME ip link set veth-$NAME up
    sudo ip netns exec $NAME ip link set lo up
    sudo ip netns exec $NAME ip route add default via 10.100.0.1

    # Attach bridge side to bridge
    sudo ip link set veth-$NAME-br master br-ns
    sudo ip link set veth-$NAME-br up

    echo "Created namespace: $NAME with IP $IP"
}

# Create multiple namespaces
create_namespace ns1 10.100.0.10
create_namespace ns2 10.100.0.20
create_namespace ns3 10.100.0.30

# Enable forwarding
sudo sysctl -w net.ipv4.ip_forward=1

# Add NAT for internet access
sudo iptables -t nat -A POSTROUTING -s 10.100.0.0/24 -o eth0 -j MASQUERADE
sudo iptables -A FORWARD -i br-ns -o eth0 -j ACCEPT
sudo iptables -A FORWARD -i eth0 -o br-ns -m state --state RELATED,ESTABLISHED -j ACCEPT

echo "=== Testing connectivity ==="

# Test namespace to namespace
echo "ns1 -> ns2:"
sudo ip netns exec ns1 ping -c 2 10.100.0.20

echo "ns2 -> ns3:"
sudo ip netns exec ns2 ping -c 2 10.100.0.30

# Test internet access
echo "ns1 -> Internet:"
sudo ip netns exec ns1 ping -c 2 8.8.8.8

echo "Done! All namespaces connected via bridge."

VRF (Virtual Routing and Forwarding)

VRF provides multiple routing tables on a single interface, without full namespace isolation.

Understanding VRF vs Network Namespaces

Feature Network Namespace VRF
Routing Tables Separate Separate
Network Interfaces Can be separate Shared
Firewall Rules Separate Shared
Process Isolation Full Partial
Performance Slight overhead Minimal overhead
Use Case Complete isolation Traffic separation
Complexity Higher Lower

Creating VRF Devices

# Load VRF kernel module (if not already loaded)
sudo modprobe vrf

# Create VRF device
sudo ip link add vrf-red type vrf table 10
sudo ip link set vrf-red up

# Create another VRF
sudo ip link add vrf-blue type vrf table 20
sudo ip link set vrf-blue up

# List VRF devices
ip link show type vrf

Assigning Interfaces to VRF

# Create virtual interfaces for testing
sudo ip link add dummy-red type dummy
sudo ip link add dummy-blue type dummy

# Assign to VRF
sudo ip link set dummy-red master vrf-red
sudo ip link set dummy-blue master vrf-blue

# Configure IPs
sudo ip addr add 10.1.1.1/24 dev dummy-red
sudo ip addr add 10.2.2.1/24 dev dummy-blue

# Bring up
sudo ip link set dummy-red up
sudo ip link set dummy-blue up

# View routing tables
ip route show vrf vrf-red
ip route show vrf vrf-blue
ip route show table 10
ip route show table 20

Running Processes in VRF Context

# Start process in specific VRF
sudo ip vrf exec vrf-red ping 8.8.8.8

# Run server in specific VRF
sudo ip vrf exec vrf-red python3 -m http.server 8080

# Run shell in VRF context
sudo ip vrf exec vrf-blue bash
# All commands now use vrf-blue routing
ping 8.8.8.8
curl https://ifconfig.me
exit

Practical Application: Multi-VPN Setup

Scenario: Route Different Traffic Through Different VPNs

#!/bin/bash
# multi-vpn-setup.sh - Route work and personal traffic through separate VPNs

set -e

echo "=== Setting up Multi-VPN with Network Namespaces ==="

# Create namespaces
sudo ip netns add vpn-work
sudo ip netns add vpn-personal

# Create veth pairs
sudo ip link add veth-work type veth peer name veth-work-br
sudo ip link add veth-pers type veth peer name veth-pers-br

# Move to namespaces
sudo ip link set veth-work netns vpn-work
sudo ip link set veth-pers netns vpn-personal

# Configure work namespace
sudo ip netns exec vpn-work ip addr add 10.200.1.2/24 dev veth-work
sudo ip netns exec vpn-work ip link set veth-work up
sudo ip netns exec vpn-work ip link set lo up
sudo ip netns exec vpn-work ip route add default via 10.200.1.1

# Configure personal namespace
sudo ip netns exec vpn-personal ip addr add 10.200.2.2/24 dev veth-pers
sudo ip netns exec vpn-personal ip link set veth-pers up
sudo ip netns exec vpn-personal ip link set lo up
sudo ip netns exec vpn-personal ip route add default via 10.200.2.1

# Configure host side
sudo ip addr add 10.200.1.1/24 dev veth-work-br
sudo ip addr add 10.200.2.1/24 dev veth-pers-br
sudo ip link set veth-work-br up
sudo ip link set veth-pers-br up

# Enable forwarding
sudo sysctl -w net.ipv4.ip_forward=1

# Setup NAT for each namespace
sudo iptables -t nat -A POSTROUTING -s 10.200.1.0/24 -o eth0 -j MASQUERADE
sudo iptables -t nat -A POSTROUTING -s 10.200.2.0/24 -o eth0 -j MASQUERADE

echo "=== Namespaces created. Now connect VPNs ==="

# Connect VPN in work namespace
echo "Starting work VPN in vpn-work namespace..."
sudo ip netns exec vpn-work openvpn --config /etc/openvpn/work.ovpn --daemon

# Connect VPN in personal namespace
echo "Starting personal VPN in vpn-personal namespace..."
sudo ip netns exec vpn-personal openvpn --config /etc/openvpn/personal.ovpn --daemon

# Wait for VPNs to connect
sleep 10

echo "=== Testing VPN connections ==="

# Check work VPN IP
WORK_IP=$(sudo ip netns exec vpn-work curl -s https://ifconfig.me)
echo "Work VPN IP: $WORK_IP"

# Check personal VPN IP
PERSONAL_IP=$(sudo ip netns exec vpn-personal curl -s https://ifconfig.me)
echo "Personal VPN IP: $PERSONAL_IP"

echo "=== Setup complete! ==="
echo ""
echo "To use work VPN:"
echo "  sudo ip netns exec vpn-work <command>"
echo ""
echo "To use personal VPN:"
echo "  sudo ip netns exec vpn-personal <command>"
echo ""
echo "Examples:"
echo "  sudo ip netns exec vpn-work firefox"
echo "  sudo ip netns exec vpn-personal transmission-gtk"

DNS Configuration for Separate VPNs

# Configure separate DNS for each namespace

# Work namespace - use work DNS servers
sudo mkdir -p /etc/netns/vpn-work
sudo tee /etc/netns/vpn-work/resolv.conf <<EOF
nameserver 10.0.0.1    # Work DNS server
nameserver 10.0.0.2
search company.local
EOF

# Personal namespace - use public DNS
sudo mkdir -p /etc/netns/vpn-personal
sudo tee /etc/netns/vpn-personal/resolv.conf <<EOF
nameserver 1.1.1.1
nameserver 8.8.8.8
EOF

# Test DNS resolution
sudo ip netns exec vpn-work nslookup internal.company.local
sudo ip netns exec vpn-personal nslookup google.com

Application Launcher for Specific Namespace

#!/bin/bash
# run-in-vpn.sh - Launch app in specific VPN namespace

NAMESPACE=$1
shift
COMMAND=$@

if [ -z "$NAMESPACE" ] || [ -z "$COMMAND" ]; then
    echo "Usage: $0 <namespace> <command>"
    echo "Example: $0 vpn-work firefox"
    exit 1
fi

# Preserve display for GUI apps
export DISPLAY=:0
export XAUTHORITY=$HOME/.Xauthority

# Run in namespace
sudo -E ip netns exec $NAMESPACE sudo -u $USER -E $COMMAND

Usage:

1
2
3
4
5
6
7
8
# Launch Firefox through work VPN
./run-in-vpn.sh vpn-work firefox

# Download file through personal VPN
./run-in-vpn.sh vpn-personal wget https://example.com/file.zip

# Start torrent client in personal VPN
./run-in-vpn.sh vpn-personal transmission-gtk

IoT Network Segmentation

Isolated IoT Network with Restricted Access

#!/bin/bash
# iot-segmentation.sh - Create isolated network for IoT devices

# Create IoT namespace
sudo ip netns add iot-devices

# Create veth pair
sudo ip link add veth-iot type veth peer name veth-iot-br

# Move to namespace
sudo ip link set veth-iot netns iot-devices

# Configure namespace (no default route initially - isolated)
sudo ip netns exec iot-devices ip addr add 192.168.100.2/24 dev veth-iot
sudo ip netns exec iot-devices ip link set veth-iot up
sudo ip netns exec iot-devices ip link set lo up

# Configure host side
sudo ip addr add 192.168.100.1/24 dev veth-iot-br
sudo ip link set veth-iot-br up

# Create bridge for IoT devices
sudo ip link add br-iot type bridge
sudo ip link set br-iot up
sudo ip addr add 192.168.100.254/24 dev br-iot

# Attach veth to bridge
sudo ip link set veth-iot-br master br-iot

echo "=== IoT Network Created ==="

# Setup DHCP server for IoT devices (dnsmasq)
sudo tee /etc/dnsmasq.d/iot-network.conf <<EOF
interface=br-iot
dhcp-range=192.168.100.10,192.168.100.200,12h
dhcp-option=option:router,192.168.100.254
dhcp-option=option:dns-server,192.168.100.254
EOF

sudo systemctl restart dnsmasq

# Firewall rules: IoT devices can only access specific services
# Block IoT -> Internal network
sudo iptables -A FORWARD -i br-iot -d 192.168.1.0/24 -j DROP

# Allow IoT -> Internet (HTTP/HTTPS only)
sudo iptables -A FORWARD -i br-iot -p tcp --dport 80 -j ACCEPT
sudo iptables -A FORWARD -i br-iot -p tcp --dport 443 -j ACCEPT
sudo iptables -A FORWARD -i br-iot -p udp --dport 53 -j ACCEPT

# Allow specific internal service (e.g., Home Assistant)
sudo iptables -A FORWARD -i br-iot -d 192.168.1.100 -p tcp --dport 8123 -j ACCEPT

# NAT for internet access
sudo iptables -t nat -A POSTROUTING -s 192.168.100.0/24 -o eth0 -j MASQUERADE

# Log dropped IoT traffic for monitoring
sudo iptables -A FORWARD -i br-iot -j LOG --log-prefix "IoT-DROP: "

echo "=== IoT Segmentation Complete ==="
echo "IoT devices on br-iot (192.168.100.0/24)"
echo "Restricted to HTTP/HTTPS and specific internal services only"

Monitoring IoT Network Traffic

# Watch IoT network traffic in real-time
sudo tcpdump -i br-iot -n

# Monitor blocked access attempts
sudo tail -f /var/log/kern.log | grep "IoT-DROP"

# View active connections from IoT network
sudo conntrack -L -s 192.168.100.0/24

# Statistics
sudo iptables -L FORWARD -v -n | grep br-iot

Container Network Simulation

Understanding Docker Networking with Namespaces

#!/bin/bash
# docker-like-networking.sh - Simulate Docker bridge networking

# Create bridge (like docker0)
sudo ip link add docker0 type bridge
sudo ip link set docker0 up
sudo ip addr add 172.17.0.1/16 dev docker0

# Function to create "container"
create_container() {
    local NAME=$1
    local IP=$2

    # Create namespace (container)
    sudo ip netns add $NAME

    # Create veth pair
    sudo ip link add veth-$NAME type veth peer name veth-$NAME-br

    # Move one end to namespace
    sudo ip link set veth-$NAME netns $NAME

    # Configure namespace
    sudo ip netns exec $NAME ip addr add $IP/16 dev veth-$NAME
    sudo ip netns exec $NAME ip link set veth-$NAME up
    sudo ip netns exec $NAME ip link set lo up
    sudo ip netns exec $NAME ip route add default via 172.17.0.1

    # Attach to bridge
    sudo ip link set veth-$NAME-br master docker0
    sudo ip link set veth-$NAME-br up

    echo "Container $NAME created with IP $IP"
}

# Create multiple containers
create_container container1 172.17.0.10
create_container container2 172.17.0.20
create_container container3 172.17.0.30

# Enable forwarding and NAT
sudo sysctl -w net.ipv4.ip_forward=1
sudo iptables -t nat -A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE

# Port forwarding (like docker -p 8080:80)
# Forward host port 8080 to container1 port 80
sudo iptables -t nat -A PREROUTING -p tcp --dport 8080 -j DNAT --to-destination 172.17.0.10:80
sudo iptables -A FORWARD -p tcp -d 172.17.0.10 --dport 80 -j ACCEPT

echo "=== Docker-like network created ==="
echo "Test container networking:"
echo "  sudo ip netns exec container1 ping 172.17.0.20"
echo "  sudo ip netns exec container2 curl http://172.17.0.10"

Advanced Routing with VRF

Policy-Based Routing with VRF

#!/bin/bash
# vrf-policy-routing.sh - Route traffic based on source IP using VRF

# Create VRFs
sudo ip link add vrf-isp1 type vrf table 100
sudo ip link add vrf-isp2 type vrf table 200
sudo ip link set vrf-isp1 up
sudo ip link set vrf-isp2 up

# Assume two internet connections: eth0 (ISP1) and eth1 (ISP2)

# Create dummy interfaces for VRF
sudo ip link add dum-isp1 type dummy
sudo ip link add dum-isp2 type dummy

# Assign to VRFs
sudo ip link set dum-isp1 master vrf-isp1
sudo ip link set dum-isp2 master vrf-isp2

sudo ip link set dum-isp1 up
sudo ip link set dum-isp2 up

# Add routes in VRF tables
sudo ip route add default via 192.168.1.1 dev eth0 table 100  # ISP1
sudo ip route add default via 192.168.2.1 dev eth1 table 200  # ISP2

# Policy routing: Route based on source IP
sudo ip rule add from 10.0.1.0/24 table 100  # Subnet A -> ISP1
sudo ip rule add from 10.0.2.0/24 table 200  # Subnet B -> ISP2

# Mark packets and route based on marks
sudo iptables -t mangle -A PREROUTING -s 10.0.1.0/24 -j MARK --set-mark 1
sudo iptables -t mangle -A PREROUTING -s 10.0.2.0/24 -j MARK --set-mark 2

sudo ip rule add fwmark 1 table 100
sudo ip rule add fwmark 2 table 200

echo "Policy routing configured:"
echo "  10.0.1.0/24 -> ISP1 (eth0)"
echo "  10.0.2.0/24 -> ISP2 (eth1)"

Load Balancing Across Multiple Connections

1
2
3
4
5
6
7
8
# Create weighted multipath route
sudo ip route add default \
    nexthop via 192.168.1.1 dev eth0 weight 1 \
    nexthop via 192.168.2.1 dev eth1 weight 1

# This distributes traffic across both connections
# For per-connection (not per-packet) balancing
sudo sysctl -w net.ipv4.fib_multipath_hash_policy=1

Testing and Debugging

Comprehensive Network Namespace Test

#!/bin/bash
# test-namespace-connectivity.sh

test_namespace() {
    local NS=$1
    local DESC=$2

    echo "=== Testing $DESC ($NS) ==="

    # Check interfaces
    echo "Interfaces:"
    sudo ip netns exec $NS ip link show | grep -E '^[0-9]'

    # Check IP addresses
    echo "IP Addresses:"
    sudo ip netns exec $NS ip addr show | grep "inet "

    # Check routing
    echo "Routes:"
    sudo ip netns exec $NS ip route show

    # Test connectivity
    echo "Connectivity tests:"

    # Gateway
    GW=$(sudo ip netns exec $NS ip route show default | awk '{print $3}')
    if [ ! -z "$GW" ]; then
        sudo ip netns exec $NS ping -c 1 -W 2 $GW > /dev/null 2>&1
        if [ $? -eq 0 ]; then
            echo "  ✓ Gateway ($GW) reachable"
        else
            echo "  ✗ Gateway ($GW) unreachable"
        fi
    fi

    # Internet
    sudo ip netns exec $NS ping -c 1 -W 2 8.8.8.8 > /dev/null 2>&1
    if [ $? -eq 0 ]; then
        echo "  ✓ Internet (8.8.8.8) reachable"
    else
        echo "  ✗ Internet unreachable"
    fi

    # DNS
    sudo ip netns exec $NS nslookup google.com > /dev/null 2>&1
    if [ $? -eq 0 ]; then
        echo "  ✓ DNS resolution working"
    else
        echo "  ✗ DNS resolution failed"
    fi

    echo ""
}

# Test all namespaces
for ns in $(ip netns list | awk '{print $1}'); do
    test_namespace $ns "$ns"
done

Network Tracing

# Trace packets through namespaces

# In default namespace
sudo tcpdump -i veth-red-br -n

# In namespace
sudo ip netns exec red tcpdump -i veth-red -n

# Trace all bridges
sudo tcpdump -i br-ns -n

# Monitor iptables hits
sudo watch -n 1 'iptables -L -v -n | head -20'

Performance Testing

#!/bin/bash
# namespace-performance-test.sh

# Create test namespace
sudo ip netns add perf-test
sudo ip link add veth-perf type veth peer name veth-perf-br
sudo ip link set veth-perf netns perf-test
sudo ip netns exec perf-test ip addr add 10.99.0.2/24 dev veth-perf
sudo ip netns exec perf-test ip link set veth-perf up
sudo ip netns exec perf-test ip link set lo up
sudo ip addr add 10.99.0.1/24 dev veth-perf-br
sudo ip link set veth-perf-br up

echo "=== Performance Tests ==="

# Latency test
echo "Latency (ping):"
sudo ip netns exec perf-test ping -c 100 -i 0.01 10.99.0.1 | tail -3

# Bandwidth test (iperf3)
echo "Starting iperf3 server in namespace..."
sudo ip netns exec perf-test iperf3 -s -D

sleep 2

echo "Bandwidth test:"
iperf3 -c 10.99.0.2 -t 10

# Cleanup
sudo pkill iperf3
sudo ip netns delete perf-test

Systemd Integration

Persistent Namespace Setup

# /etc/systemd/system/netns-vpn-work.service

[Unit]
Description=Network Namespace for Work VPN
After=network.target

[Service]
Type=oneshot
RemainAfterExit=yes

ExecStart=/usr/local/bin/setup-vpn-work-namespace.sh
ExecStop=/usr/local/bin/teardown-vpn-work-namespace.sh

[Install]
WantedBy=multi-user.target

Setup script:

#!/bin/bash
# /usr/local/bin/setup-vpn-work-namespace.sh

set -e

# Create namespace
ip netns add vpn-work

# Create veth pair
ip link add veth-work type veth peer name veth-work-br

# Configure namespace
ip link set veth-work netns vpn-work
ip netns exec vpn-work ip addr add 10.200.1.2/24 dev veth-work
ip netns exec vpn-work ip link set veth-work up
ip netns exec vpn-work ip link set lo up
ip netns exec vpn-work ip route add default via 10.200.1.1

# Configure host
ip addr add 10.200.1.1/24 dev veth-work-br
ip link set veth-work-br up

# Enable forwarding
sysctl -w net.ipv4.ip_forward=1

# NAT
iptables -t nat -A POSTROUTING -s 10.200.1.0/24 -o eth0 -j MASQUERADE

# Start VPN
ip netns exec vpn-work openvpn --config /etc/openvpn/work.ovpn --daemon

echo "Work VPN namespace ready"

Teardown script:

#!/bin/bash
# /usr/local/bin/teardown-vpn-work-namespace.sh

# Kill VPN
ip netns exec vpn-work pkill openvpn || true

# Remove iptables rules
iptables -t nat -D POSTROUTING -s 10.200.1.0/24 -o eth0 -j MASQUERADE || true

# Delete namespace (automatically deletes veth pair)
ip netns delete vpn-work || true

# Remove host veth
ip link delete veth-work-br || true

echo "Work VPN namespace removed"

Enable service:

1
2
3
sudo systemctl enable netns-vpn-work
sudo systemctl start netns-vpn-work
sudo systemctl status netns-vpn-work

Troubleshooting

Common Issues

1. Namespace has no connectivity

# Check if interfaces are up
sudo ip netns exec <namespace> ip link show

# Bring up if needed
sudo ip netns exec <namespace> ip link set <interface> up

# Check routing
sudo ip netns exec <namespace> ip route show

# Add default route if missing
sudo ip netns exec <namespace> ip route add default via <gateway>

# Check IP forwarding on host
sysctl net.ipv4.ip_forward
# Should be 1

2. DNS not working in namespace

# Check resolv.conf
sudo ip netns exec <namespace> cat /etc/resolv.conf

# Create namespace-specific DNS config
sudo mkdir -p /etc/netns/<namespace>
sudo tee /etc/netns/<namespace>/resolv.conf <<EOF
nameserver 8.8.8.8
nameserver 1.1.1.1
EOF

# Test
sudo ip netns exec <namespace> nslookup google.com

3. Cannot delete namespace - "Device or resource busy"

# Find processes using namespace
sudo ip netns identify <pid>
sudo lsns -t net

# Kill processes in namespace
sudo ip netns pids <namespace> | xargs sudo kill

# Force delete
sudo ip netns delete <namespace>

# If still fails, check for mounted resources
sudo umount /var/run/netns/<namespace> || true
sudo rm -f /var/run/netns/<namespace>

4. Performance issues

# Check for packet drops
ip -s link show

# Monitor interface statistics
watch -n 1 'ip -s link show veth-red'

# Check for MTU issues
ip netns exec <namespace> ip link show | grep mtu

# Set MTU if needed
sudo ip netns exec <namespace> ip link set <interface> mtu 1500

5. GUI applications won't start in namespace

1
2
3
4
5
# Need to preserve display and X authority
export DISPLAY=:0
export XAUTHORITY=$HOME/.Xauthority

sudo -E ip netns exec <namespace> sudo -u $USER -E firefox

Security Considerations

Hardening Namespace Isolation

# Prevent namespace from accessing host services
sudo iptables -A INPUT -i veth-red-br -d 192.168.1.10 -j DROP

# Allow only specific ports
sudo iptables -A INPUT -i veth-red-br -p tcp --dport 22 -j ACCEPT
sudo iptables -A INPUT -i veth-red-br -p tcp --dport 53 -j ACCEPT
sudo iptables -A INPUT -i veth-red-br -p udp --dport 53 -j ACCEPT

# Rate limiting
sudo iptables -A INPUT -i veth-red-br -m limit --limit 10/minute -j ACCEPT
sudo iptables -A INPUT -i veth-red-br -j DROP

# Log suspicious activity
sudo iptables -A INPUT -i veth-red-br -j LOG --log-prefix "NS-RED: "

AppArmor/SELinux Integration

# AppArmor profile for namespace processes
sudo tee /etc/apparmor.d/namespace-restricted <<'EOF'
#include <tunables/global>

/usr/bin/* {
  #include <abstractions/base>
  #include <abstractions/nameservice>

  network inet stream,
  network inet6 stream,

  deny /etc/shadow r,
  deny /root/** rw,
  deny /home/** rw,

  /tmp/** rw,
  /var/tmp/** rw,
}
EOF

sudo apparmor_parser -r /etc/apparmor.d/namespace-restricted

Performance Optimization

Raspberry Pi Specific Tuning

# Increase network buffers
sudo sysctl -w net.core.rmem_max=16777216
sudo sysctl -w net.core.wmem_max=16777216
sudo sysctl -w net.ipv4.tcp_rmem='4096 87380 16777216'
sudo sysctl -w net.ipv4.tcp_wmem='4096 65536 16777216'

# Enable TCP optimizations
sudo sysctl -w net.ipv4.tcp_window_scaling=1
sudo sysctl -w net.ipv4.tcp_timestamps=1
sudo sysctl -w net.ipv4.tcp_sack=1

# Reduce conntrack timeout for limited memory
sudo sysctl -w net.netfilter.nf_conntrack_tcp_timeout_established=600

# Make permanent
sudo tee -a /etc/sysctl.conf <<EOF
net.core.rmem_max=16777216
net.core.wmem_max=16777216
net.ipv4.tcp_rmem=4096 87380 16777216
net.ipv4.tcp_wmem=4096 65536 16777216
net.ipv4.tcp_window_scaling=1
net.ipv4.tcp_timestamps=1
net.ipv4.tcp_sack=1
net.netfilter.nf_conntrack_tcp_timeout_established=600
EOF

Monitoring Resource Usage

#!/bin/bash
# monitor-namespaces.sh

echo "=== Network Namespace Resource Usage ==="
echo ""

for ns in $(ip netns list | awk '{print $1}'); do
    echo "Namespace: $ns"

    # Process count
    PROCS=$(sudo ip netns pids $ns | wc -l)
    echo "  Processes: $PROCS"

    # Network statistics
    sudo ip netns exec $ns ip -s link show | grep -A 1 "RX:" | tail -1
    sudo ip netns exec $ns ip -s link show | grep -A 1 "TX:" | tail -1

    # Connection count
    CONNS=$(sudo ip netns exec $ns ss -tan | grep ESTAB | wc -l)
    echo "  Active connections: $CONNS"

    echo ""
done

Summary

This comprehensive guide covered network namespaces and VRF on Raspberry Pi:

✅ Core Concepts

  • Network namespace isolation and architecture
  • VRF for routing table separation
  • veth pairs for virtual connectivity
  • Network bridges for complex topologies

✅ Practical Applications

  • Multi-VPN setup: Simultaneous VPN connections with traffic routing
  • IoT segmentation: Isolated networks for untrusted devices
  • Container networking: Docker-like network simulation
  • Policy routing: VRF-based traffic engineering

✅ Advanced Features

  • DNS configuration per namespace
  • GUI application support in namespaces
  • Port forwarding and NAT
  • Load balancing across multiple connections

✅ Production Deployment

  • Systemd service integration
  • Persistent namespace configuration
  • Monitoring and debugging tools
  • Performance optimization

✅ Security

  • Network isolation enforcement
  • Firewall rules per namespace
  • AppArmor/SELinux integration
  • Rate limiting and logging

✅ Troubleshooting

  • Connectivity debugging
  • DNS resolution issues
  • Performance analysis
  • Resource cleanup

✅ Performance

  • Raspberry Pi specific tuning
  • Buffer optimization
  • Connection tracking limits
  • Resource monitoring

Next Steps

Advanced Topics:

  1. SR-IOV and Hardware Offload - Network card virtualization
  2. VXLAN Overlays - Layer 2 networks over Layer 3
  3. MPLS with VRF - Label switching for advanced routing
  4. eBPF-based Networking - Programmable network datapaths
  5. Kubernetes CNI Development - Custom container networking plugins

Related Guides:

With network namespaces and VRF, your Raspberry Pi can handle enterprise-grade network segmentation, multi-VPN routing, and container networking - all on a single device!