Namespaces 08 - Connecting two network namespaces (ns1, ns2) - with two veth pairs and a standard Linux bridge
Linux Namespaces Learning · Previous: Connecting two network namespaces (ns1, ns2) - with a veth pair · Next: Connecting two network namespaces (ns1, ns2) - with two veth pairs and a distributed OVS switch (openvswitch)
The Slovak original of this document: Namespaces 08 - Prepojenie dvoch sieťových menných priestorov (ns1, ns2) - pomocou 2 párov veth adaptérov a štandardného Linux prepínača (bridge) (slovensky).
2016 - Linux NET Namespace - Connecting two network namespaces (ns1, ns2) - with two veth pairs and a standard Linux bridge
======================================================================================================================
[1] NET namespace - Connecting two network namespaces (ns1, ns2) - with two veth pairs and
a standard Linux bridge
======================================================================================================================
+------------------+ +-------------------------------+ +------------------+
| ns1 veth1 |======cable======| veth1-br bridge0 veth2-br |======cable======| veth2 ns2 |
+------------------+ +-------------------------------+ +------------------+
namespace "ns1" host system (bridge) namespace "ns2"
The first Ethernet cable (between namespace "ns1" and the Linux bridge "bridge0"): veth1====veth1-br
The second Ethernet cable (between namespace "ns2" and the Linux bridge "bridge0"): veth2====veth2-br
[1.1] - Remove the network namespaces "ns1" and "ns2" (if they exist).
[1.2] - Create two network (NET) namespaces, "ns1" and "ns2".
----------------------------------------------------------------------------------------------------------------
[1.1]# ip netns del ns1 &>/dev/null
[1.1]# ip netns del ns2 &>/dev/null
[1.2]# ip netns add ns1
[1.2]# ip netns add ns2
----------------------------------------------------------------------------------------------------------------
[1.3] - On the host system, create an Ethernet switch/bridge named "bridge0".
Note: the package "bridge-utils" has to be installed; it is what administers the Linux bridge.
[1.4] - Turn the Spanning Tree Protocol (STP) off on the Ethernet switch "bridge0".
[1.5] - On the host system, bring the Ethernet switch "bridge0" up.
----------------------------------------------------------------------------------------------------------------
[1.3]# brctl addbr bridge0
[1.4]# brctl stp bridge0 off
[1.5]# ip link set dev bridge0 up
----------------------------------------------------------------------------------------------------------------
[1.6]TERM1 - In network namespace "ns1", exec the command "bash".
[1.7]TERM2 - In network namespace "ns2", exec the command "bash".
----------------------------------------------------------------------------------------------------------------
[1.6]TERM1# ip netns exec ns1 bash
[1.7]TERM2# ip netns exec ns2 bash
----------------------------------------------------------------------------------------------------------------
[1.8] - Create a pair of virtual Ethernet devices, which stand for a network cable with two RJ45
plugs, then put one end (veth1) into namespace "ns1" and the other end
(veth1-br) into the Ethernet switch "bridge0".
[1.9] - Put the virtual Ethernet adapter "veth1" into network namespace "ns1".
[1.10] - Connect the virtual Ethernet adapter "veth1-br" to the Ethernet switch "bridge0".
[1.11] - Create a pair of virtual Ethernet devices, which stand for a network cable with two RJ45
plugs, then put one end (veth2) into namespace "ns2" and the other end
(veth2-br) into the Ethernet switch "bridge0".
[1.12] - Put the virtual Ethernet adapter "veth2" into network namespace "ns2".
[1.13] - Connect the virtual Ethernet adapter "veth2-br" to the Ethernet switch "bridge0".
----------------------------------------------------------------------------------------------------------------
[1.8] # ip link add veth1 type veth peer name veth1-br
[1.9] # ip link set veth1 netns ns1
[1.10]# brctl addif bridge0 veth1-br
[1.11]# ip link add veth2 type veth peer name veth2-br
[1.12]# ip link set veth2 netns ns2
[1.13]# brctl addif bridge0 veth2-br
----------------------------------------------------------------------------------------------------------------
[1.14] - Bring the network adapter "veth1" up in namespace "ns1" and give it the address "10.0.0.1".
[1.15] - Bring the network adapter/port "veth1-br" up on the standard Linux bridge "bridge0".
[1.16] - Bring the network adapter "veth2" up in namespace "ns2" and give it the address "10.0.0.2".
[1.17] - Bring the network adapter/port "veth2-br" up on the standard Linux bridge "bridge0".
[1.18] - From network namespace "ns1", test that namespace "ns2" answers.
[1.19] - From network namespace "ns2", test that namespace "ns1" answers.
----------------------------------------------------------------------------------------------------------------
[1.14]# ip netns exec ns1 ifconfig veth1 10.0.0.1/24 up
[1.15]# ip link set dev veth1-br up
[1.16]# ip netns exec ns2 ifconfig veth2 10.0.0.2/24 up
[1.17]# ip link set dev veth2-br up
[1.18]# ip netns exec ns1 ping 10.0.0.2
[1.19]# ip netns exec ns2 ping 10.0.0.1
----------------------------------------------------------------------------------------------------------------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.
brctland bridge-utils: the brctl man page itself says the tool is obsolete and points to thebridgecommand from iproute2. No extra package is needed:ip link add ... type bridgecreates the bridge,ip link set ... masterattaches a port,bridge link showlists the ports.ifconfig: steps [1.14] and [1.16] becomeip -n ns1 addr add 10.0.0.1/24 dev veth1andip -n ns1 link set veth1 up(the same forns2).- No shells needed in the namespaces: steps [1.6] and [1.7] can be left out; named namespaces persist on their own. The veth pairs can also be created with one end already in place:
ip link add veth1 netns ns1 type veth peer name veth1-br. - Without root: the lab works unchanged for an ordinary user inside
unshare --user --map-root-user --net --mount bashaftermount -t tmpfs tmpfs /run. The bridge then lives in that private network namespace instead of on the host, and everything disappears on exit. - Who builds this today: a bridge on the host with one veth pair per namespace is what a container engine sets up for containers started by root (podman's default
podmannetwork, managed by netavark). A container daemon that runs as root changes the network setup and the firewall rules of the host to do this. Rootless podman does not build it; it uses pasta, a user-space process, so no bridge, veth or firewall rule is created on the host.
Steps [1.3] to [1.5], [1.10] and [1.13] with iproute2 only:
$ # ip link add bridge0 type bridge stp_state 0 $ # ip link set bridge0 up $ # ip link set veth1-br master bridge0 $ # ip link set veth2-br master bridge0 $ # bridge link show
Sources: