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 -h, --help (since v0.2.0) show help and exit
130
131
132 -v, --version (since v0.2.0) show version and exit
133
134
135
137 Terminal 1: Create user/network/mount namespaces
138
139
140 (host)$ unshare --user --map-root-user --net --mount
141 (namespace)$ echo $$ > /tmp/pid
142
143
144
145 In this documentation, we use (host)$ as the prompt of the host shell,
146 (namespace)$ as the prompt of the shell running in the namespaces.
147
148
149 If unshare fails, try the following commands (known to be needed on De‐
150 bian, Arch, and old CentOS 7.X):
151
152
153 (host)$ sudo sh -c 'echo "user.max_user_namespaces=28633" >> /etc/sysctl.d/userns.conf'
154 (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
155 (host)$ sudo sysctl --system
156
157
158
159 Terminal 2: Start slirp4netns
160
161
162 (host)$ slirp4netns --configure --mtu=65520 $(cat /tmp/pid) tap0
163 starting slirp, MTU=65520
164
165
166
167 Terminal 1: Make sure tap0 is configured and connected to the Internet
168
169
170 (namespace)$ ip a
171 1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000
172 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
173 3: tap0: <BROADCAST,UP,LOWER_UP> mtu 65520 qdisc fq_codel state UNKNOWN group default qlen 1000
174 link/ether c2:28:0c:0e:29:06 brd ff:ff:ff:ff:ff:ff
175 inet 10.0.2.100/24 brd 10.0.2.255 scope global tap0
176 valid_lft forever preferred_lft forever
177 inet6 fe80::c028:cff:fe0e:2906/64 scope link
178 valid_lft forever preferred_lft forever
179 (namespace)$ echo "nameserver 10.0.2.3" > /tmp/resolv.conf
180 (namespace)$ mount --bind /tmp/resolv.conf /etc/resolv.conf
181 (namespace)$ curl https://example.com
182
183
184
185 Bind-mounting /etc/resolv.conf is only needed when /etc/resolv.conf on
186 the host refers to loopback addresses (127.0.0.X, typically dnsmasq(8)
187 or systemd-resolved.service(8)) that cannot be accessed from the name‐
188 space.
189
190
191 If your /etc/resolv.conf on the host is managed by networkmanager(8) or
192 systemd-resolved.service(8), you might need to mount a new filesystem
193 on /etc instead, so as to prevent the new /etc/resolv.conf from being
194 unmounted unexpectedly when /etc/resolv.conf on the host is regener‐
195 ated.
196
197
198 (namespace)$ mkdir /tmp/a /tmp/b
199 (namespace)$ mount --rbind /etc /tmp/a
200 (namespace)$ mount --rbind /tmp/b /etc
201 (namespace)$ mkdir /etc/.ro
202 (namespace)$ mount --move /tmp/a /etc/.ro
203 (namespace)$ cd /etc
204 (namespace)$ for f in .ro/*; do ln -s $f $(basename $f); done
205 (namespace)$ rm resolv.conf
206 (namespace)$ echo "nameserver 10.0.2.3" > resolv.conf
207 (namespace)$ curl https://example.com
208
209
210
211 These steps can be simplified with rootlesskit --copy-up=/etc if root‐
212 lesskit is installed:
213
214
215 (host)$ rootlesskit --net=slirp4netns --copy-up=/etc bash
216 (namespace)$ cat /etc/resolv.conf
217 nameserver 10.0.2.3
218
219
220
221
223 To route ping packets, you may need to set up net.ipv4.ping_group_range
224 properly as the root.
225
226
227 e.g.
228
229
230 (host)$ sudo sh -c 'echo "net.ipv4.ping_group_range=0 2147483647" > /etc/sysctl.d/ping_group_range.conf'
231 (host)$ sudo sysctl --system
232
233
234
235
237 By default, ports listening on INADDR_LOOPBACK (127.0.0.1) on the host
238 are accessible from the child namespace via the gateway (default:
239 10.0.2.2). --disable-host-loopback can be used to prohibit connecting
240 to INADDR_LOOPBACK on the host.
241
242
243 However, a host loopback address might be still accessible via the
244 built-in DNS (default: 10.0.2.3) if /etc/resolv.conf on the host refers
245 to a loopback address. You may want to set up iptables for limiting
246 access to the built-in DNS in such a case.
247
248
249 (host)$ nsenter -t $(cat /tmp/pid) -U --preserve-credentials -n
250 (namespace)$ iptables -A OUTPUT -d 10.0.2.3 -p udp --dport 53 -j ACCEPT
251 (namespace)$ iptables -A OUTPUT -d 10.0.2.3 -j DROP
252
253
254
255
257 slirp4netns can provide QMP-like API server over an UNIX socket file:
258
259
260 (host)$ slirp4netns --api-socket /tmp/slirp4netns.sock ...
261
262
263
264 add_hostfwd: Expose a port (IPv4 only)
265
266
267 (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}}'
268 (namespace)$ echo -n $json | nc -U /tmp/slirp4netns.sock
269 {"return": {"id": 42}}
270
271
272
273 If host_addr is not specified, then it defaults to "0.0.0.0".
274
275
276 If guest_addr is not specified, then it will be set to the default ad‐
277 dress that corresponds to --configure.
278
279
280 list_hostfwd: List exposed ports
281
282
283 (namespace)$ json='{"execute": "list_hostfwd"}'
284 (namespace)$ echo -n $json | nc -U /tmp/slirp4netns.sock
285 {"return": {"entries": [{"id": 42, "proto": "tcp", "host_addr": "0.0.0.0", "host_port": 8080, "guest_addr": "10.0.2.100", "guest_port": 80}]}}
286
287
288
289 remove_hostfwd: Remove an exposed port
290
291
292 (namespace)$ json='{"execute": "remove_hostfwd", "arguments": {"id": 42}}'
293 (namespace)$ echo -n $json | nc -U /tmp/slirp4netns.sock
294 {"return": {}}
295
296
297
298 Remarks:
299
300
301 • Client needs to shutdown(2) the socket with SHUT_WR after
302 sending every request. i.e. No support for keep-alive and
303 timeout.
304
305 • slirp4netns "stops the world" during processing API requests.
306
307 • A request must be less than 4096 bytes.
308
309 • JSON responses may contain error instead of return.
310
311
312
313
315 A user can define a network namespace path as opposed to the default
316 process ID:
317
318
319 (host)$ slirp4netns --netns-type=path ... /path/to/netns tap0
320
321
322
323 Currently, the netns-type=TYPE argument supports path or pid args with
324 the default being pid.
325
326
327 Additionally, a --userns-path=PATH argument can be included to override
328 any user namespace path defaults
329
330
331 (host)$ slirp4netns --netns-type=path --userns-path=/path/to/userns /path/to/netns tap0
332
333
334
335
337 A user can defined preferred outbound ipv4 and ipv6 address in multi IP
338 scenarios.
339
340
341 (host)$ slirp4netns --outbound-addr=10.2.2.10 --outbound-addr6=fe80::10 ...
342
343
344
345 Optionally you can use interface names instead of ip addresses.
346
347
348 (host)$ slirp4netns --outbound-addr=eth0 --outbound-addr6=eth0 ...
349
350
351
352
354 The easiest way to allow inter-namespace communication is to nest net‐
355 work namespaces inside the slirp4netns's network namespace.
356
357
358 (host)$ nsenter -t $(cat /tmp/pid) -U --preserve-credentials -n -m
359 (namespace)$ mount -t tmpfs none /run
360 (namespace)$ ip netns add foo
361 (namespace)$ ip netns add bar
362 (namespace)$ ip link add veth-foo type veth peer name veth-bar
363 (namespace)$ ip link set veth-foo netns foo
364 (namespace)$ ip link set veth-bar netns bar
365 (namespace)$ ip netns exec foo ip link set veth-foo name eth0
366 (namespace)$ ip netns exec bar ip link set veth-bar name eth0
367 (namespace)$ ip netns exec foo ip link set lo up
368 (namespace)$ ip netns exec bar ip link set lo up
369 (namespace)$ ip netns exec foo ip link set eth0 up
370 (namespace)$ ip netns exec bar ip link set eth0 up
371 (namespace)$ ip netns exec foo ip addr add 192.168.42.100/24 dev eth0
372 (namespace)$ ip netns exec bar ip addr add 192.168.42.101/24 dev eth0
373 (namespace)$ ip netns exec bar ping 192.168.42.100
374
375
376
377 However, this method does not work when you want to allow communication
378 across multiple slirp4netns instances. To allow communication across
379 multiple slirp4netns instances, you need to combine another network
380 stack such as vde_plug(1) with slirp4netns.
381
382
383 (host)$ vde_plug --daemon switch:///tmp/switch null://
384 (host)$ nsenter -t $(cat /tmp/pid-instance0) -U --preserve-credentials -n
385 (namespace-instance0)$ vde_plug --daemon vde:///tmp/switch tap://vde
386 (namespace-instance0)$ ip link set vde up
387 (namespace-instance0)$ ip addr add 192.168.42.100/24 dev vde
388 (namespace-instance0)$ exit
389 (host)$ nsenter -t $(cat /tmp/pid-instance1) -U --preserve-credentials -n
390 (namespace-instance1)$ vde_plug --daemon vde:///tmp/switch tap://vde
391 (namespace-instance1)$ ip link set vde up
392 (namespace-instance1)$ ip addr add 192.168.42.101/24 dev vde
393 (namespace-instance1)$ ping 192.168.42.100
394
395
396
397
399 VXLAN is known to work. See Usernetes project for the example of
400 multi-node rootless Kubernetes cluster with VXLAN:
401 https://github.com/rootless-containers/usernetes
402
403
404
406 Kernel 4.20 bumped up the default value of /proc/sys/net/ipv4/tcp_rmem
407 from 87380 to 131072. This is known to slow down slirp4netns port for‐
408 warding: https://github.com/rootless-containers/slirp4netns/issues/128.
409
410
411 As a workaround, you can adjust the value of
412 /proc/sys/net/ipv4/tcp_rmem inside the namespace. No real root privi‐
413 lege is needed to modify the file since kernel 4.15.
414
415
416 (host)$ nsenter -t $(cat /tmp/pid) -U --preserve-credentials -n -m
417 (namespace)$ c=$(cat /proc/sys/net/ipv4/tcp_rmem); echo $c | sed -e s/131072/87380/g > /proc/sys/net/ipv4/tcp_rmem
418
419
420
421
423 network_namespaces(7), user_namespaces(7), veth(4)
424
425
426
428 The slirp4netns command is available from https://github.com/root‐
429 less-containers/slirp4netns under GNU GENERAL PUBLIC LICENSE Version 2
430 (or later).
431
432
433
434Rootless Containers June 2021 SLIRP4NETNS(1)