Linux Namespaces
Linux namespace isolation — PID, network, mount, user, and UTS namespaces with unshare and nsenter.
Namespace Types
Seven namespace types — the building blocks of containers
# Mount (mnt) — isolated filesystem mounts
# PID — isolated process IDs (PID 1 per namespace)
# Network (net) — isolated network stack (interfaces, routes, iptables)
# UTS — isolated hostname and domain name
# IPC — isolated System V IPC and POSIX message queues
# User — isolated UID/GID mappings (unprivileged containers)
# Cgroup — isolated cgroup root view
Listing Namespaces
List all namespaces on the system — type, PID, command
lsns
List only network namespaces
lsns -t net
List namespaces for a specific process
lsns -p $(pgrep -x sshd | head -1)
Show namespace inodes for a process — raw /proc view
ls -la /proc/$(pgrep -x sshd | head -1)/ns/
Compare namespaces of two processes — same inode = same namespace
readlink /proc/1/ns/net ; readlink /proc/$$/ns/net
Unshare — Create New Namespaces
Create an isolated mount namespace — mounts are private
sudo unshare --mount /bin/bash
Create an isolated PID namespace — new PID 1 inside
sudo unshare --pid --fork --mount-proc /bin/bash
--fork is required with --pid because PID namespaces take effect on child processes, not the calling process.
|
Create an isolated UTS namespace — change hostname without affecting host
sudo unshare --uts /bin/bash
# Inside: hostname isolated-host
Create an isolated network namespace — no interfaces except lo
sudo unshare --net /bin/bash
# Inside: ip link show — only lo exists
Create a user namespace — root inside, unprivileged outside
unshare --user --map-root-user /bin/bash
# Inside: whoami → root (but no real privileges on host)
Combine multiple namespaces — poor man’s container
sudo unshare --mount --pid --net --uts --ipc --fork --mount-proc /bin/bash
Nsenter — Enter Existing Namespaces
Enter all namespaces of a running container/process
sudo nsenter -t $(pgrep -x nginx | head -1) -m -u -i -n -p /bin/bash
Enter only the network namespace of a process — debug networking
sudo nsenter -t $(pgrep -x nginx | head -1) -n /bin/bash
Enter a namespace by path — useful for named network namespaces
sudo nsenter --net=/var/run/netns/lab01 /bin/bash
Run a single command in another namespace — no interactive shell
sudo nsenter -t $(pgrep -x nginx | head -1) -n ip addr show
Network Namespaces (ip netns)
Create a named network namespace — persists in /var/run/netns/
sudo ip netns add lab01
List named network namespaces
sudo ip netns list
Run a command inside a network namespace
sudo ip netns exec lab01 ip link show
Create a veth pair connecting host to namespace
sudo ip link add veth-host type veth peer name veth-ns
sudo ip link set veth-ns netns lab01
sudo ip addr add 192.168.100.1/24 dev veth-host
sudo ip link set veth-host up
sudo ip netns exec lab01 ip addr add 192.168.100.2/24 dev veth-ns
sudo ip netns exec lab01 ip link set veth-ns up
sudo ip netns exec lab01 ip link set lo up
Verify connectivity between host and namespace
ping -c 2 192.168.100.2
sudo ip netns exec lab01 ping -c 2 192.168.100.1
Delete a named network namespace — cleans up interfaces
sudo ip netns delete lab01
Mount Namespaces and Chroot
chroot vs mount namespace — chroot changes root, mount ns isolates mounts
# chroot: changes apparent root directory, trivially escapable by root
sudo chroot /mnt/sysroot /bin/bash
# mount namespace: full mount table isolation, proper containment
sudo unshare --mount /bin/bash
chroot is not a security boundary — any process with CAP_SYS_CHROOT can escape. Mount namespaces with pivot_root provide actual isolation.
|
Bind mount inside a mount namespace — visible only inside
sudo unshare --mount /bin/bash
# Inside:
mount --bind /tmp/overlay /var/www/html
# Host's /var/www/html is unchanged
PID Namespaces
Create a PID namespace — process sees itself as PID 1
sudo unshare --pid --fork --mount-proc /bin/bash
# Inside: ps aux shows only processes in this namespace
Inspect PID namespace membership from outside
awk '{print $1}' /proc/$(pgrep -x nginx | head -1)/status | head -10
PID namespace nesting — child sees parent’s PID 1 as its own
cat /proc/1/status | awk '/NSpid/'
NSpid shows the PID in each nested namespace. A process might be PID 4523 on the host but PID 1 inside its namespace.
|
Container Relationship
See namespaces used by a container — podman or docker
sudo lsns | awk '/conmon|containerd-shim/'
Enter a running container’s namespaces directly — bypass container CLI
PID=$(sudo podman inspect --format '{{.State.Pid}}' mycontainer)
sudo nsenter -t $PID -m -u -i -n -p /bin/bash
Compare host and container namespace inodes
readlink /proc/1/ns/net
readlink /proc/$(sudo podman inspect -f '{{.State.Pid}}' mycontainer)/ns/net
Inspection and Debugging
Show all namespace types for PID 1 (init) — the host root namespaces
ls -la /proc/1/ns/
Find all processes in a specific namespace — by inode number
INODE=$(readlink /proc/$(pgrep -x nginx | head -1)/ns/net)
awk -v inode="$INODE" '{cmd="readlink /proc/"$1"/ns/net"; cmd|getline ns; close(cmd); if(ns==inode) print $1}' <(ls /proc/ | awk '/^[0-9]+$/')
Count processes per network namespace — detect namespace sprawl
lsns -t net --output=NPROCS,PID,COMMAND --no-headings
RHCSA Patterns
Create an isolated environment — mount + PID + network namespaces
sudo unshare --mount --pid --net --fork --mount-proc /bin/bash
# Verify isolation:
hostname # same as host (no --uts)
ip link show # only lo
ps aux # only bash and ps
mount | wc -l # independent mount table
Network namespace lab — create, connect, test, tear down
sudo ip netns add test01
sudo ip link add veth0 type veth peer name veth1
sudo ip link set veth1 netns test01
sudo ip addr add 10.0.0.1/24 dev veth0 && sudo ip link set veth0 up
sudo ip netns exec test01 ip addr add 10.0.0.2/24 dev veth1
sudo ip netns exec test01 ip link set veth1 up
sudo ip netns exec test01 ip link set lo up
ping -c 1 10.0.0.2
sudo ip netns delete test01