3 linux-network-namespace-labs (lnnl) is a small program to easily create
4 networking lab setups based on Linux network namespaces. It provides a quick
5 way to set up labs using a text file describing the architecture (networks,
6 nodes, links, commands). This is much simpler than running each node in a
7 separate virtual machine or manually allocating the IP addresses for each
8 node. It is licensed under GPLv3+.
15 - Go, no external dependencies
19 - Linux compiled with `CONFIG_NET_NS` (available on most modern systems)
21 - root (or unprivileged user namespaces, see below)
28 Then copy the binary `lnnl` to a directory in your `$PATH`.
33 The following configuration from `examples/readme/` sets up a lab with three
34 nodes (routers) and configures static routes.
37 # Network range for loopback addresses of the nodes
38 net loops 192.0.2.0/24 3fff::/20
39 # Network range for interfaces between nodes
40 net addrs 198.51.100.0/24 2001:db8::/32
42 # Set up three nodes (routers) and assign IPv4 and IPv6 loopback addresses
47 # Links between routers: /31 or /127 prefixes are used for each interface
51 # Commands to run on each node; $1 is the node name (= name of the network
52 # namespace). Here it's used to set up static routes but can also be used to
53 # start routing daemons like Bird.
57 Then set up the lab by running (as root):
63 Now you can enter the network namespace of each router and test a simple
68 lo UNKNOWN 127.0.0.1/8 ::1/128
69 lo2 UNKNOWN 192.0.2.0/32 3fff::/128 fe80::438:67ff:fe0a:4e58/64
70 r2@if287 UP 198.51.100.0/31 2001:db8::/127 fe80::a896:cdff:fe58:5c23/64
71 # traceroute 192.0.2.2
72 traceroute to 192.0.2.2 (192.0.2.2), 30 hops max, 60 byte packets
73 1 r2 (198.51.100.1) 0.937 ms 0.818 ms 0.768 ms
74 2 r3-loop (192.0.2.2) 0.722 ms 0.650 ms 0.603 ms
76 Use `exit` to leave the network namespace.
78 The `/etc/hosts` file of each node (via `/etc/netns/<ns>/hosts`) is
79 automatically filled with all known addresses so you can use hostnames as
83 PING r3-loop(r3-loop (3fff::2)) 56 data bytes
84 64 bytes from r3-loop (3fff::2): icmp_seq=1 ttl=63 time=0.266 ms
85 --- r3-loop ping statistics ---
86 1 packets transmitted, 1 received, 0% packet loss, time 0ms
87 rtt min/avg/max/mdev = 0.266/0.266/0.266/0.000 ms
89 When you change the configuration you can simply rerun "up" and it will remove
90 the lab (and kill all processes inside it) before restarting it:
95 When you're done you can remove the lab with:
100 To get an overview of the network you can create a
101 https://en.wikipedia.org/wiki/DOT_(graph_description_language)[DOT] file:
103 $ lnnl dot lab.conf lab.dot
104 $ dot -Tpng lab.dot > lab.png
106 image::examples/readme/lab.png[DOT style diagram of network nodes and links]
109 === Running without root using unprivileged user namespaces
111 Creating a named network namespace within a user namespace requires a few
112 extra steps. Use the following commands:
114 $ unshare --user --net --mount --map-auto --map-root-user
115 # mount -t tmpfs tmpfs /run
116 # mount -t tmpfs tmpfs /etc/netns
117 # export PATH=$PATH:/usr/sbin
119 The tmpfs mounts make the directories writable within the user namespace. The
120 PATH is updated to ensure `sysctl` is found.
122 To run the bird-ospf example:
125 # lnnl up examples/bird-ospf/lab.conf
127 # ip netns exec r1 ip -br a
129 # birdc -s /run/bird/r1.ctl
132 To enter the namespace from another terminal (get the PID with `echo $$`):
134 $ nsenter --user --net --mount --target $pid
139 Have a look at `examples/`, which also includes running
140 https://bird.network.cz/[Bird] on each node and spawning a Podman container
141 inside the created nodes with https://frrouting.org/[FRR].
144 == Syntax of configuration file
146 One option per line, empty lines are permitted as well as comments starting
149 The config file is parsed from top to bottom and the options "net", "node",
150 "link" must be given in this order. "cmd" can be put anywhere (but is only
151 executed at the end).
155 "net" <name> <prefix>...
157 "net" creates a new prefix which is used to allocate addresses for loopback
158 and link interfaces. Multiple IPv4 and IPv6 prefixes can be specified. When
159 the network is used, one address from each prefix is assigned to the
160 interface. "net"s used for loopback interfaces must be separate from "net"s
161 used for link interfaces.
165 "node" <name> [<loopback-net-name>...]
167 "node" creates a new node (router) and (if specified) assigns loopback
168 addresses from the given networks. The loopback addresses are assigned to a
173 "link" <node> <node> <net-name>|"-" ["l3"]
175 "link" creates links between nodes. The IP addresses are taken from the given
176 network. /31 is used for IPv4- and /127 for IPv6-prefixes. If "-" is used as
177 the net-name then no addresses are assigned (useful for unnumbered links). The
178 MAC address is dynamically allocated by the kernel. The link is named after
179 the node "on the other side". Multiple links can be created between two nodes.
180 In this case, suffixes like "_2", "_3", etc. are appended to the interface
181 name. By default, veth interfaces are used. Adding "l3" changes this to
182 netkit, which provides a layer-3 connection without needing ARP (requires
183 kernel 6.7, iproute2 6.8).
187 "cmd" <string-passed-to-sh-c>
189 "cmd" runs the given command (by passing it as is to `sh -c`) on each node.
190 The first argument is the name of the node (which is also the name of the
191 network namespace). This can be used to run setup commands or routing daemons
194 If "cmd" is not flexible enough you can simply use `ip netns exec` to manually
195 run commands on specific nodes.
200 Written by Simon Ruderich <simon@ruderich.org>.
202 Please report bugs, feature requests and patches via email.
207 This program is licensed under GPL version 3 or later.
209 Copyright (C) 2024 Simon Ruderich
211 This program is free software: you can redistribute it and/or modify
212 it under the terms of the GNU General Public License as published by
213 the Free Software Foundation, either version 3 of the License, or
214 (at your option) any later version.
216 This program is distributed in the hope that it will be useful,
217 but WITHOUT ANY WARRANTY; without even the implied warranty of
218 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
219 GNU General Public License for more details.
221 You should have received a copy of the GNU General Public License
222 along with this program. If not, see <https://www.gnu.org/licenses/>.