Namespaces 06 - Connecting a network namespace to the host system - with a veth pair
Linux Namespaces Learning · Previous: NET namespace · Next: Connecting two network namespaces (ns1, ns2) - with a veth pair
The Slovak original of this document: Namespaces 06 - Prepojenie sieťového menného priestoru a hostiteľského systému - pomocou páru veth adaptérov (slovensky).
2016 - Linux NET Namespace - Connecting a network namespace to the host system - with a veth pair
======================================================================================================================
[1] NET namespace - Connecting a network namespace to the host system - with a veth pair
======================================================================================================================
+--------------------+ +--------------------+
| hostOS veth1.1 |=========cable=========| veth1.2 ns1 | (PID = 2429)
+--------------------+ +--------------------+
host system namespace "ns1"
[1.1] - Create one network (NET) namespace, "ns1".
----------------------------------------------------------------------------------------------------------------
# ip netns add ns1
----------------------------------------------------------------------------------------------------------------
[1.2]TERM2 - In network namespace "ns1", exec the command "bash". PID = 2429
[1.3]TERM2 - Find the PID of the BASH process.
----------------------------------------------------------------------------------------------------------------
[1.2]TERM2# ip netns exec ns1 bash
[1.3]TERM2# echo $$
----------------------------------------------------------------------------------------------------------------
2429
----------------------------------------------------------------------------------------------------------------
[1.4] - Create a pair of virtual Ethernet devices, which stand for a network cable with two RJ45
plugs, putting one end (veth1.2) into namespace "ns1" (by the identifier of the
process [2429]) and the other end (veth1.1) into the host system.
----------------------------------------------------------------------------------------------------------------
# ip link add veth1.1 type veth peer name veth1.2 netns 2429
----------------------------------------------------------------------------------------------------------------
[1.5] - Check that the pairs of virtual devices from step [1.4] were created.
----------------------------------------------------------------------------------------------------------------
# ip link show
----------------------------------------------------------------------------------------------------------------
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP mode DEFAULT qlen 1000
link/ether 00:0c:29:9b:30:f4 brd ff:ff:ff:ff:ff:ff
3: veth1.1@if2: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT qlen 1000
link/ether 22:74:36:08:a3:e0 brd ff:ff:ff:ff:ff:ff link-netnsid 0
----------------------------------------------------------------------------------------------------------------
[1.6] - Bring the network adapter "veth1.2" up in namespace "ns1" and give it the address "10.0.0.1".
[1.7] - Bring the network adapter "veth1.1" up on the host system as the other end of the "cable/plug" "veth1.2" and
give it the address "10.0.0.2".
[1.8] - Test that the host OS and network namespace "ns1" can reach each other.
----------------------------------------------------------------------------------------------------------------
[1.6]# ip netns exec ns1 ifconfig veth1.2 10.0.0.1/24 up
[1.7]# ifconfig veth1.1 10.0.0.2/24 up
[1.8]# ping 10.0.0.1
----------------------------------------------------------------------------------------------------------------
64 bytes from 10.0.0.1: icmp_seq=1 ttl=64 time=0.075 ms
64 bytes from 10.0.0.1: icmp_seq=2 ttl=64 time=0.093 ms
...
----------------------------------------------------------------------------------------------------------------
[1.9] - Print the routing table of network namespace "ns1".
[1.10] - List the network adapters/links of network namespace "ns1".
----------------------------------------------------------------------------------------------------------------
[1.9] # ip netns exec ns1 route
----------------------------------------------------------------------------------------------------------------
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
10.0.0.0 0.0.0.0 255.255.255.0 U 0 0 0 veth1.2
----------------------------------------------------------------------------------------------------------------
[1.10]# ip netns exec ns1 ip link
----------------------------------------------------------------------------------------------------------------
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: veth1.2@if13: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT qlen 1000
link/ether 7e:d3:d9:0a:56:b4 brd ff:ff:ff:ff:ff:ff link-netnsid 0
----------------------------------------------------------------------------------------------------------------Current practice (checked 2026-10)
noteThe article above is kept as it was written in 2016. This section lists what has changed since and what to do instead today.
ifconfigandroute: both come from net-tools, whose man pages call them obsolete. The whole lab is done withipalone;ip -n ns1 ...is short forip netns exec ns1 ip ....- No shell needed to hold the namespace: steps [1.2] and [1.3] start
bashonly to get a PID fornetns 2429. A named namespace stays alive through its file in/run/netns, andip linkaccepts the name:peer name veth1.2 netns ns1. - Loopback is down: step [1.10] shows
loin state DOWN. Programs that talk to 127.0.0.1 inside the namespace needip -n ns1 link set lo up. - Without root: pasta: connecting a namespace to the host network no longer needs root-built plumbing.
pasta(from the passt project) runs as an ordinary user, creates the user and network namespace itself and puts a tap interface into it; a user-space process translates between that tap and normal sockets on the host. It needs no veth, bridge or NAT rules. By default the namespace gets a copy of the host's address and routes. It is the default network for rootless podman. - pasta does not isolate: with pasta's own defaults, ports that listen on the host, including services bound only to 127.0.0.1, are reachable from inside the namespace. In a test on this machine
--map-host-loopback nonealone did not close that;-T noneclosed 127.0.0.1, and only-T none --map-host-loopback nonetogether also closed the gateway address, which pasta maps to the host. Rootless podman starts pasta with-T none -U none --no-map-gw. Test the result whenever it matters.
The lab with current commands:
$ # ip netns add ns1 $ # ip link add veth1.1 type veth peer name veth1.2 netns ns1 $ # ip -n ns1 addr add 10.0.0.1/24 dev veth1.2 $ # ip -n ns1 link set veth1.2 up $ # ip addr add 10.0.0.2/24 dev veth1.1 $ # ip link set veth1.1 up $ # ip -n ns1 route
The unprivileged way to give a new network namespace a working connection:
$ pasta --config-net -- ip -br addrSources: