Linux Namespaces

Quick Reference

# List namespaces of a process
ls -la /proc/$$/ns/
lsns

# Create new namespace (unshare)
unshare --mount --uts --ipc --net --pid --fork bash

# Enter existing namespace
nsenter --target PID --mount --uts --ipc --net --pid

# View namespace hierarchy
lsns -t net
lsns -p PID

Understanding Namespaces

What are Namespaces?

Linux namespaces provide isolation of system resources. Each namespace type isolates a specific global resource:

  • Mount (mnt) - Filesystem mount points

  • UTS - Hostname and domain name

  • IPC - Inter-process communication

  • Network (net) - Network stack (interfaces, routing, firewall)

  • PID - Process IDs

  • User - User and group IDs

  • Cgroup - Cgroup root directory

  • Time - System clocks (Linux 5.6+)

Namespace Types

Namespace Flag What It Isolates

Mount

CLONE_NEWNS

Mount points, filesystem view

UTS

CLONE_NEWUTS

Hostname, domainname

IPC

CLONE_NEWIPC

System V IPC, POSIX message queues

Network

CLONE_NEWNET

Network devices, stacks, ports

PID

CLONE_NEWPID

Process IDs

User

CLONE_NEWUSER

User and group IDs

Cgroup

CLONE_NEWCGROUP

Cgroup root directory

Time

CLONE_NEWTIME

Boot and monotonic clocks

Viewing Namespaces

Process Namespaces

# View namespaces of current process
ls -la /proc/$$/ns/

# View namespaces of specific process
ls -la /proc/1234/ns/

# Compare namespaces (same inode = same namespace)
readlink /proc/1/ns/net
readlink /proc/$$/ns/net

List System Namespaces

# List all namespaces
lsns

# List specific type
lsns -t net
lsns -t mnt
lsns -t pid

# Show owner/creator
lsns -o NS,TYPE,NPROCS,PID,USER,COMMAND

# For specific process
lsns -p 1234

Creating Namespaces with unshare

Basic Usage

# Create new UTS namespace (isolated hostname)
unshare --uts bash
hostname isolated-host
hostname  # Shows "isolated-host"
exit
hostname  # Shows original hostname

# Create new mount namespace
unshare --mount bash
mount --bind /tmp /mnt
ls /mnt    # Shows /tmp contents
exit       # Mount is gone

Multiple Namespaces

# Create multiple namespaces at once
unshare --mount --uts --ipc --pid --fork bash

# Full container-like isolation
unshare --mount --uts --ipc --net --pid --fork \
    --mount-proc bash

# With user namespace (rootless)
unshare --user --map-root-user bash
id  # Shows uid=0(root)

Common Options

# --fork: Fork before exec (needed for PID namespace)
unshare --pid --fork bash

# --mount-proc: Mount new /proc (needed for PID namespace)
unshare --pid --fork --mount-proc bash
ps aux  # Only shows processes in namespace

# --map-root-user: Map current user to root in user namespace
unshare --user --map-root-user bash

# --propagation: Control mount propagation
unshare --mount --propagation private bash

Entering Namespaces with nsenter

Enter Process Namespaces

# Enter all namespaces of a process
nsenter --target 1234 --all

# Enter specific namespaces
nsenter --target 1234 --mount --uts --ipc --net --pid

# Enter with specific command
nsenter --target 1234 --net ip addr

# Enter container namespace
nsenter --target $(docker inspect -f '{{.State.Pid}}' container_name) \
    --mount --uts --ipc --net --pid bash

Enter by Namespace File

# Enter using namespace file path
nsenter --net=/proc/1234/ns/net ip addr

# For persistent namespace
nsenter --net=/var/run/netns/mynetns ip addr

Network Namespaces

Create and Manage

# Create named network namespace
ip netns add mynetns

# List network namespaces
ip netns list

# Execute in namespace
ip netns exec mynetns ip addr
ip netns exec mynetns bash

# Delete namespace
ip netns delete mynetns

Configure Network Namespace

# Create veth pair for communication
ip link add veth0 type veth peer name veth1

# Move one end to namespace
ip link set veth1 netns mynetns

# Configure host side
ip addr add 10.200.0.1/24 dev veth0
ip link set veth0 up

# Configure namespace side
ip netns exec mynetns ip addr add 10.200.0.2/24 dev veth1
ip netns exec mynetns ip link set veth1 up
ip netns exec mynetns ip link set lo up

# Add default route in namespace
ip netns exec mynetns ip route add default via 10.200.0.1

# Test connectivity
ip netns exec mynetns ping 10.200.0.1

Enable Internet Access

# Enable IP forwarding
echo 1 > /proc/sys/net/ipv4/ip_forward

# NAT for namespace traffic
iptables -t nat -A POSTROUTING -s 10.200.0.0/24 -j MASQUERADE

# Test from namespace
ip netns exec mynetns ping 8.8.8.8

Mount Namespaces

Private Mounts

# Create mount namespace with private propagation
unshare --mount --propagation private bash

# Mounts in this namespace won't propagate to parent
mount -t tmpfs tmpfs /mnt
ls /mnt    # Visible here
# Not visible in parent namespace

Bind Mounts

# Create isolated filesystem view
unshare --mount bash

# Bind mount different directory
mount --bind /opt/app/etc /etc
cat /etc/passwd    # Shows /opt/app/etc/passwd

# Overlay mount
mount -t overlay overlay -o lowerdir=/lower,upperdir=/upper,workdir=/work /mnt

PID Namespaces

Create PID Namespace

# Must use --fork for PID namespace
unshare --pid --fork --mount-proc bash

# Process sees itself as PID 1
echo $$    # Shows 1

# Only processes in namespace visible
ps aux     # Only shows processes in this namespace

Nested PID Namespaces

# PIDs are hierarchical
# Parent can see all child namespace PIDs
# Child cannot see parent PIDs

# From parent
ps aux | grep sleep  # Sees process in child namespace

# From child namespace
ps aux               # Only sees own processes

User Namespaces

Unprivileged Containers

# Create user namespace (unprivileged)
unshare --user --map-root-user bash

# Now root (UID 0) inside namespace
id    # uid=0(root) gid=0(root)

# But maps to regular user outside
# Can't actually do privileged operations on host

UID/GID Mapping

# View mappings
cat /proc/$$/uid_map
cat /proc/$$/gid_map

# Manual mapping requires newuidmap/newgidmap
# Or configured in /etc/subuid and /etc/subgid

# Check subuid allocation
grep $USER /etc/subuid
# username:100000:65536

Cgroup Namespaces

Cgroup Isolation

# Create cgroup namespace
unshare --cgroup bash

# Process sees its cgroup as root
cat /proc/self/cgroup  # Shows / instead of full path

# Useful for containers to hide host cgroup structure

Practical Examples

Simple Container

#!/bin/bash
# Simple container using namespaces

# Create root filesystem
mkdir -p /tmp/container/rootfs
# ... populate with minimal rootfs

# Run container
unshare --mount --uts --ipc --pid --net --fork \
    --root=/tmp/container/rootfs \
    --mount-proc \
    /bin/sh

# Or with pivot_root for full isolation

Network Namespace for Testing

#!/bin/bash
# Create isolated network environment for testing

# Create namespace
ip netns add testnet

# Create veth pair
ip link add vtest0 type veth peer name vtest1
ip link set vtest1 netns testnet

# Configure
ip addr add 192.168.100.1/24 dev vtest0
ip link set vtest0 up

ip netns exec testnet ip addr add 192.168.100.2/24 dev vtest1
ip netns exec testnet ip link set vtest1 up
ip netns exec testnet ip link set lo up

# Run test server in isolated namespace
ip netns exec testnet python3 -m http.server 8080 &

# Access from host
curl http://192.168.100.2:8080

# Cleanup
ip netns delete testnet

Process Isolation

#!/bin/bash
# Run process with limited visibility

unshare --pid --fork --mount-proc \
    --mount --propagation private \
    -- sh -c '
        # Process can only see its own PIDs
        # Has isolated mount namespace
        echo "PID in namespace: $$"
        ps aux
        exec "$@"
    ' -- "$@"

Troubleshooting

Permission Denied

# Check if user namespaces are enabled
cat /proc/sys/kernel/unprivileged_userns_clone

# Enable if needed
echo 1 | sudo tee /proc/sys/kernel/unprivileged_userns_clone

# Check subuid/subgid
grep $USER /etc/subuid /etc/subgid

Namespace Not Persisting

# Namespaces are destroyed when last process exits
# Use bind mount to persist

# Create persistent network namespace
ip netns add persistent
# Creates /var/run/netns/persistent

# Or bind mount namespace file
touch /var/run/myns
unshare --net=/var/run/myns true

Cannot Enter Namespace

# Check namespace exists
ls -la /proc/PID/ns/

# Check permissions
ls -la /proc/PID/ns/net

# May need CAP_SYS_ADMIN or same user namespace
nsenter --user --preserve-credentials --target PID --net

Quick Command Reference

# View namespaces
ls -la /proc/$$/ns/                          # Current process
lsns                                          # All namespaces
lsns -t net                                   # Network namespaces

# Create namespaces
unshare --uts bash                            # UTS only
unshare --net bash                            # Network only
unshare --mount --uts --ipc --pid --fork bash # Multiple
unshare --user --map-root-user bash           # User (rootless)

# Enter namespaces
nsenter --target PID --all                    # All namespaces
nsenter --target PID --net                    # Network only
ip netns exec NAME command                    # Named netns

# Network namespaces
ip netns add NAME                             # Create
ip netns list                                 # List
ip netns exec NAME command                    # Execute
ip netns delete NAME                          # Delete