1SLIRP4NETNS(1) User Commands SLIRP4NETNS(1)
2
3
4
6 slirp4netns - User-mode networking for unprivileged network namespaces
7
8
9
11 slirp4netns [OPTION]... PID|PATH [TAPNAME]
12
13
14
16 slirp4netns provides user-mode networking ("slirp") for network name‐
17 spaces.
18
19
20 Unlike veth(4), slirp4netns does not require the root privileges on the
21 host.
22
23
24 Default configuration:
25
26
27 • MTU: 1500
28
29 • CIDR: 10.0.2.0/24
30
31 • Gateway/Host: 10.0.2.2 (network address + 2)
32
33 • DNS: 10.0.2.3 (network address + 3)
34
35 • DHCP begin: 10.0.2.15 (network address + 15)
36
37 • DHCP end: 10.0.2.30 (network address + 30)
38
39 • IPv6 CIDR: fd00::/64
40
41 • IPv6 Gateway/Host: fd00::2
42
43 • IPv6 DNS: fd00::3
44
45
46
47
49 -c, --configure bring up the TAP interface. IP will be set to
50 10.0.2.100 (network address + 100) by default. IPv6 will be set to a
51 random address. Starting with v0.4.0, the loopback interface (lo) is
52 brought up as well.
53
54
55 -e, --exit-fd=FD specify the FD for terminating slirp4netns. When the
56 FD is specified, slirp4netns exits when a poll(2) event happens on the
57 FD.
58
59
60 -r, --ready-fd=FD specify the FD to write to when the initialization
61 steps are finished. When the FD is specified, slirp4netns writes "1"
62 to the FD and close the FD. Prior to v0.4.0, the FD was written after
63 the network configuration (-c) but before the API socket configuration
64 (-a).
65
66
67 -m, --mtu=MTU (since v0.2.0) specify MTU (max=65521).
68
69
70 -6, --enable-ipv6 (since v0.2.0, EXPERIMENTAL) enable IPv6
71
72
73 -a, --api-socket (since v0.3.0) API socket path
74
75
76 --cidr (since v0.3.0) specify CIDR, e.g. 10.0.2.0/24
77
78
79 --disable-host-loopback (since v0.3.0) prohibit connecting to
80 127.0.0.1:* on the host namespace
81
82
83 --netns-type=TYPE (since v0.4.0) specify network namespace type
84 ([path|pid], default=pid)
85
86
87 --userns-path=PATH (since v0.4.0) specify user namespace path
88
89
90 --enable-sandbox (since v0.4.0) enter the user namespace and create a
91 new mount namespace where only /etc and /run are mounted from the host.
92
93
94 Requires /etc/resolv.conf not to be a symlink to a file outside /etc
95 and /run.
96
97
98 When running as the root, the process does not enter the user namespace
99 but all the capabilities except CAP_NET_BIND_SERVICE are dropped.
100
101
102 --enable-seccomp (since v0.4.0, EXPERIMENTAL) enable seccomp(2) to
103 limit syscalls. Typically used in conjunction with --enable-sandbox.
104
105
106 --outbound-addr=IPv4 (since v1.1.0, EXPERIMENTAL) specify outbound ipv4
107 address slirp should bind to
108
109
110 --outbound-addr=INTERFACE (since v1.1.0, EXPERIMENTAL) specify outbound
111 interface slirp should bind to (ipv4 traffic only)
112
113
114 --outbound-addr=IPv6 (since v1.1.0, EXPERIMENTAL) specify outbound ipv6
115 address slirp should bind to
116
117
118 --outbound-addr6=INTERFACE (since v1.1.0, EXPERIMENTAL) specify out‐
119 bound interface slirp should bind to (ipv6 traffic only)
120
121
122 --disable-dns (since v1.1.0) disable built-in DNS (10.0.2.3 by default)
123
124
125 --macaddress (since v1.1.9) specify MAC address of the TAP interface
126 (only valid with -c)
127
128
129 --target-type=TYPE (since v1.2.0) specify the target type
130 ([netns|bess], default=netns).
131
132
133 The bess mode (since v1.2.0, EXPERIMENTAL) is expected to be used with
134 User Mode Linux. The bess mode conflicts with --configure, --netns-
135 type, and --userns-path.
136
137
138 -h, --help (since v0.2.0) show help and exit
139
140
141 -v, --version (since v0.2.0) show version and exit
142
143
144
146 Terminal 1: Create user/network/mount namespaces
147
148
149 (host)$ unshare --user --map-root-user --net --mount
150 (namespace)$ echo $$ > /tmp/pid
151
152
153
154 In this documentation, we use (host)$ as the prompt of the host shell,
155 (namespace)$ as the prompt of the shell running in the namespaces.
156
157
158 If unshare fails, try the following commands (known to be needed on De‐
159 bian, Arch, and old CentOS 7.X):
160
161
162 (host)$ sudo sh -c 'echo "user.max_user_namespaces=28633" >> /etc/sysctl.d/userns.conf'
163 (host)$ if [ -f /proc/sys/kernel/unprivileged_userns_clone ]; then sudo sh -c 'echo "kernel.unprivileged_userns_clone=1" >> /etc/sysctl.d/userns.conf'; fi
164 (host)$ sudo sysctl --system
165
166
167
168 Terminal 2: Start slirp4netns
169
170
171 (host)$ slirp4netns --configure --mtu=65520 $(cat /tmp/pid) tap0
172 starting slirp, MTU=65520
173
174
175
176 Terminal 1: Make sure tap0 is configured and connected to the Internet
177
178
179 (namespace)$ ip a
180 1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000
181 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
182 3: tap0: <BROADCAST,UP,LOWER_UP> mtu 65520 qdisc fq_codel state UNKNOWN group default qlen 1000
183 link/ether c2:28:0c:0e:29:06 brd ff:ff:ff:ff:ff:ff
184 inet 10.0.2.100/24 brd 10.0.2.255 scope global tap0
185 valid_lft forever preferred_lft forever
186 inet6 fe80::c028:cff:fe0e:2906/64 scope link
187 valid_lft forever preferred_lft forever
188 (namespace)$ echo "nameserver 10.0.2.3" > /tmp/resolv.conf
189 (namespace)$ mount --bind /tmp/resolv.conf /etc/resolv.conf
190 (namespace)$ curl https://example.com
191
192
193
194 Bind-mounting /etc/resolv.conf is only needed when /etc/resolv.conf on
195 the host refers to loopback addresses (127.0.0.X, typically dnsmasq(8)
196 or systemd-resolved.service(8)) that cannot be accessed from the name‐
197 space.
198
199
200 If your /etc/resolv.conf on the host is managed by networkmanager(8) or
201 systemd-resolved.service(8), you might need to mount a new filesystem
202 on /etc instead, so as to prevent the new /etc/resolv.conf from being
203 unmounted unexpectedly when /etc/resolv.conf on the host is regener‐
204 ated.
205
206
207 (namespace)$ mkdir /tmp/a /tmp/b
208 (namespace)$ mount --rbind /etc /tmp/a
209 (namespace)$ mount --rbind /tmp/b /etc
210 (namespace)$ mkdir /etc/.ro
211 (namespace)$ mount --move /tmp/a /etc/.ro
212 (namespace)$ cd /etc
213 (namespace)$ for f in .ro/*; do ln -s $f $(basename $f); done
214 (namespace)$ rm resolv.conf
215 (namespace)$ echo "nameserver 10.0.2.3" > resolv.conf
216 (namespace)$ curl https://example.com
217
218
219
220 These steps can be simplified with rootlesskit --copy-up=/etc if root‐
221 lesskit is installed:
222
223
224 (host)$ rootlesskit --net=slirp4netns --copy-up=/etc bash
225 (namespace)$ cat /etc/resolv.conf
226 nameserver 10.0.2.3
227
228
229
230
232 To route ping packets, you may need to set up net.ipv4.ping_group_range
233 properly as the root.
234
235
236 e.g.
237
238
239 (host)$ sudo sh -c 'echo "net.ipv4.ping_group_range=0 2147483647" > /etc/sysctl.d/ping_group_range.conf'
240 (host)$ sudo sysctl --system
241
242
243
244
246 By default, ports listening on INADDR_LOOPBACK (127.0.0.1) on the host
247 are accessible from the child namespace via the gateway (default:
248 10.0.2.2). --disable-host-loopback can be used to prohibit connecting
249 to INADDR_LOOPBACK on the host.
250
251
252 However, a host loopback address might be still accessible via the
253 built-in DNS (default: 10.0.2.3) if /etc/resolv.conf on the host refers
254 to a loopback address. You may want to set up iptables for limiting
255 access to the built-in DNS in such a case.
256
257
258 (host)$ nsenter -t $(cat /tmp/pid) -U --preserve-credentials -n
259 (namespace)$ iptables -A OUTPUT -d 10.0.2.3 -p udp --dport 53 -j ACCEPT
260 (namespace)$ iptables -A OUTPUT -d 10.0.2.3 -j DROP
261
262
263
264
266 slirp4netns can provide QMP-like API server over an UNIX socket file:
267
268
269 (host)$ slirp4netns --api-socket /tmp/slirp4netns.sock ...
270
271
272
273 add_hostfwd: Expose a port (IPv4 only)
274
275
276 (namespace)$ json='{"execute": "add_hostfwd", "arguments": {"proto": "tcp", "host_addr": "0.0.0.0", "host_port": 8080, "guest_addr": "10.0.2.100", "guest_port": 80}}'
277 (namespace)$ echo -n $json | nc -U /tmp/slirp4netns.sock
278 {"return": {"id": 42}}
279
280
281
282 If host_addr is not specified, then it defaults to "0.0.0.0".
283
284
285 If guest_addr is not specified, then it will be set to the default ad‐
286 dress that corresponds to --configure.
287
288
289 list_hostfwd: List exposed ports
290
291
292 (namespace)$ json='{"execute": "list_hostfwd"}'
293 (namespace)$ echo -n $json | nc -U /tmp/slirp4netns.sock
294 {"return": {"entries": [{"id": 42, "proto": "tcp", "host_addr": "0.0.0.0", "host_port": 8080, "guest_addr": "10.0.2.100", "guest_port": 80}]}}
295
296
297
298 remove_hostfwd: Remove an exposed port
299
300
301 (namespace)$ json='{"execute": "remove_hostfwd", "arguments": {"id": 42}}'
302 (namespace)$ echo -n $json | nc -U /tmp/slirp4netns.sock
303 {"return": {}}
304
305
306
307 Remarks:
308
309
310 • Client needs to shutdown(2) the socket with SHUT_WR after
311 sending every request. i.e. No support for keep-alive and
312 timeout.
313
314 • slirp4netns "stops the world" during processing API requests.
315
316 • A request must be less than 4096 bytes.
317
318 • JSON responses may contain error instead of return.
319
320
321
322
324 A user can define a network namespace path as opposed to the default
325 process ID:
326
327
328 (host)$ slirp4netns --netns-type=path ... /path/to/netns tap0
329
330
331
332 Currently, the netns-type=TYPE argument supports path or pid args with
333 the default being pid.
334
335
336 Additionally, a --userns-path=PATH argument can be included to override
337 any user namespace path defaults
338
339
340 (host)$ slirp4netns --netns-type=path --userns-path=/path/to/userns /path/to/netns tap0
341
342
343
344
346 A user can defined preferred outbound ipv4 and ipv6 address in multi IP
347 scenarios.
348
349
350 (host)$ slirp4netns --outbound-addr=10.2.2.10 --outbound-addr6=fe80::10 ...
351
352
353
354 Optionally you can use interface names instead of ip addresses.
355
356
357 (host)$ slirp4netns --outbound-addr=eth0 --outbound-addr6=eth0 ...
358
359
360
361
363 The easiest way to allow inter-namespace communication is to nest net‐
364 work namespaces inside the slirp4netns's network namespace.
365
366
367 (host)$ nsenter -t $(cat /tmp/pid) -U --preserve-credentials -n -m
368 (namespace)$ mount -t tmpfs none /run
369 (namespace)$ ip netns add foo
370 (namespace)$ ip netns add bar
371 (namespace)$ ip link add veth-foo type veth peer name veth-bar
372 (namespace)$ ip link set veth-foo netns foo
373 (namespace)$ ip link set veth-bar netns bar
374 (namespace)$ ip netns exec foo ip link set veth-foo name eth0
375 (namespace)$ ip netns exec bar ip link set veth-bar name eth0
376 (namespace)$ ip netns exec foo ip link set lo up
377 (namespace)$ ip netns exec bar ip link set lo up
378 (namespace)$ ip netns exec foo ip link set eth0 up
379 (namespace)$ ip netns exec bar ip link set eth0 up
380 (namespace)$ ip netns exec foo ip addr add 192.168.42.100/24 dev eth0
381 (namespace)$ ip netns exec bar ip addr add 192.168.42.101/24 dev eth0
382 (namespace)$ ip netns exec bar ping 192.168.42.100
383
384
385
386 However, this method does not work when you want to allow communication
387 across multiple slirp4netns instances. To allow communication across
388 multiple slirp4netns instances, you need to combine another network
389 stack such as vde_plug(1) with slirp4netns.
390
391
392 (host)$ vde_plug --daemon switch:///tmp/switch null://
393 (host)$ nsenter -t $(cat /tmp/pid-instance0) -U --preserve-credentials -n
394 (namespace-instance0)$ vde_plug --daemon vde:///tmp/switch tap://vde
395 (namespace-instance0)$ ip link set vde up
396 (namespace-instance0)$ ip addr add 192.168.42.100/24 dev vde
397 (namespace-instance0)$ exit
398 (host)$ nsenter -t $(cat /tmp/pid-instance1) -U --preserve-credentials -n
399 (namespace-instance1)$ vde_plug --daemon vde:///tmp/switch tap://vde
400 (namespace-instance1)$ ip link set vde up
401 (namespace-instance1)$ ip addr add 192.168.42.101/24 dev vde
402 (namespace-instance1)$ ping 192.168.42.100
403
404
405
406
408 VXLAN is known to work. See Usernetes project for the example of
409 multi-node rootless Kubernetes cluster with VXLAN:
410 https://github.com/rootless-containers/usernetes
411
412
413
415 slirp4netns (since v1.2.0) can be also used as a BESS-compatible server
416 to provide network connectivity to User Mode Linux.
417
418
419 Terminal 1: Start slirp4netns
420
421
422 (host)$ slirp4netns --target-type=bess /tmp/bess.sock
423
424
425
426 Terminal 2: Start User Mode Linux
427
428
429 (host)$ linux.uml vec0:transport=bess,dst=/tmp/bess.sock,depth=128,gro=1 root=/dev/root rootfstype=hostfs init=/bin/bash mem=2G
430 (UML)$ ip addr add 10.0.2.100/24 dev vec0
431 (UML)$ ip link set vec0 up
432 (UML)$ ip route add default via 10.0.2.2
433
434
435
436 Currently, only a single instance of User Mode Linux can be connected
437 to the slirp4netns BESS server.
438
439
440 See also User Mode Linux documentation: https://www.ker‐
441 nel.org/doc/html/latest/virt/uml/user_mode_linux_howto_v2.html#bess-
442 socket-transport
443
444
445
447 Kernel 4.20 bumped up the default value of /proc/sys/net/ipv4/tcp_rmem
448 from 87380 to 131072. This is known to slow down slirp4netns port for‐
449 warding: https://github.com/rootless-containers/slirp4netns/issues/128.
450
451
452 As a workaround, you can adjust the value of
453 /proc/sys/net/ipv4/tcp_rmem inside the namespace. No real root privi‐
454 lege is needed to modify the file since kernel 4.15.
455
456
457 (host)$ nsenter -t $(cat /tmp/pid) -U --preserve-credentials -n -m
458 (namespace)$ c=$(cat /proc/sys/net/ipv4/tcp_rmem); echo $c | sed -e s/131072/87380/g > /proc/sys/net/ipv4/tcp_rmem
459
460
461
462
464 network_namespaces(7), user_namespaces(7), veth(4)
465
466
467
469 The slirp4netns command is available from https://github.com/rootless-
470 containers/slirp4netns under GNU GENERAL PUBLIC LICENSE Version 2 (or
471 later).
472
473
474
475Rootless Containers January 2022 SLIRP4NETNS(1)