blob: 90d25cf4a6c6ba9ccfff9f103a3b1bf73eb7a6cb [file] [log] [blame]
Nathan Skrzypczak9ad39c02021-08-19 11:38:06 +02001VPP as a Home Gateway
2=====================
3
4Vpp running on a small system (with appropriate NICs) makes a fine home
5gateway. The resulting system performs far in excess of requirements: a
6debug image runs at a vector size of ~1.2 terminating a 150-mbit down /
710-mbit up cable modem connection.
8
9At a minimum, install sshd and the isc-dhcp-server. If you prefer, you
10can use dnsmasq.
11
12System configuration files
13--------------------------
14
15/etc/vpp/startup.conf:
16
17.. code-block:: c
18
19 unix {
20 nodaemon
21 log /var/log/vpp/vpp.log
22 full-coredump
23 cli-listen /run/vpp/cli.sock
24 startup-config /setup.gate
25 poll-sleep-usec 100
26 gid vpp
27 }
28 api-segment {
29 gid vpp
30 }
31 dpdk {
32 dev 0000:03:00.0
33 dev 0000:14:00.0
34 etc.
35 }
36
37 plugins {
38 ## Disable all plugins, selectively enable specific plugins
39 ## YMMV, you may wish to enable other plugins (acl, etc.)
40 plugin default { disable }
41 plugin dpdk_plugin.so { enable }
42 plugin nat_plugin.so { enable }
43 ## if you plan to use the time-based MAC filter
44 plugin mactime_plugin.so { enable }
45 }
46
47/etc/dhcp/dhcpd.conf:
48
49.. code-block:: c
50
51 subnet 192.168.1.0 netmask 255.255.255.0 {
52 range 192.168.1.10 192.168.1.99;
53 option routers 192.168.1.1;
54 option domain-name-servers 8.8.8.8;
55 }
56
57If you decide to enable the vpp dns name resolver, substitute
58192.168.1.2 for 8.8.8.8 in the dhcp server configuration.
59
60/etc/default/isc-dhcp-server:
61
62.. code-block:: c
63
64 # On which interfaces should the DHCP server (dhcpd) serve DHCP requests?
65 # Separate multiple interfaces with spaces, e.g. "eth0 eth1".
66 INTERFACESv4="lstack"
67 INTERFACESv6=""
68
69/etc/ssh/sshd_config:
70
71.. code-block:: c
72
73 # What ports, IPs and protocols we listen for
74 Port <REDACTED-high-number-port>
75 # Change to no to disable tunnelled clear text passwords
76 PasswordAuthentication no
77
78For your own comfort and safety, do NOT allow password authentication
79and do not answer ssh requests on port 22. Experience shows several hack
80attempts per hour on port 22, but none (ever) on random high-number
81ports.
82
83Systemd configuration
84---------------------
85
86In a typical home-gateway use-case, vpp owns the one-and-only WAN link
87with a prayer of reaching the public internet. Simple things like
88updating distro software requires use of the "lstack" interface created
89above, and configuring a plausible upstream DNS name resolver.
90
91Configure /etc/systemd/resolved.conf as follows.
92
93/etc/systemd/resolved.conf:
94
95.. code-block:: c
96
97 [Resolve]
98 DNS=8.8.8.8
99 #FallbackDNS=
100 #Domains=
101 #LLMNR=no
102 #MulticastDNS=no
103 #DNSSEC=no
104 #Cache=yes
105 #DNSStubListener=yes
106
107Netplan configuration
108---------------------
109
110If you want to configure a static IP address on one of your home-gateway
111Ethernet ports on Ubuntu 18.04, you'll need to configure netplan.
112Netplan is relatively new. It and the network manager GUI and can be
113cranky. In the configuration shown below, s/enp4s0/<your-interface>/...
114
115/etc/netplan-01-netcfg.yaml:
116
117.. code-block:: c
118
119 # This file describes the network interfaces available on your system
120 # For more information, see netplan(5).
121 network:
122 version: 2
123 renderer: networkd
124 ethernets:
125 enp4s0:
126 dhcp4: no
127 addresses: [192.168.2.254/24]
128 gateway4: 192.168.2.100
129 nameservers:
130 search: [my.local]
131 addresses: [8.8.8.8]
132
133/etc/systemd/network-10.enp4s0.network:
134
135.. code-block:: c
136
137 [Match]
138 Name=enp4s0
139
140 [Link]
141 RequiredForOnline=no
142
143 [Network]
144 ConfigureWithoutCarrier=true
145 Address=192.168.2.254/24
146
147Note that we've picked an IP address for the home gateway which is on an
148independent unrouteable subnet. This is handy for installing (and
149possibly reverting) new vpp software.
150
151VPP Configuration Files
152-----------------------
153
154Here we see a nice use-case for the vpp debug CLI macro expander:
155
156/setup.gate:
157
158.. code-block:: c
159
160 define HOSTNAME vpp1
161 define TRUNK GigabitEthernet3/0/0
162
163 comment { Specific MAC address yields a constant IP address }
164 define TRUNK_MACADDR 48:f8:b3:00:01:01
165 define BVI_MACADDR 48:f8:b3:01:01:02
166
167 comment { inside subnet 192.168.<inside_subnet>.0/24 }
168 define INSIDE_SUBNET 1
169
170 define INSIDE_PORT1 GigabitEthernet6/0/0
171 define INSIDE_PORT2 GigabitEthernet6/0/1
172 define INSIDE_PORT3 GigabitEthernet8/0/0
173 define INSIDE_PORT4 GigabitEthernet8/0/1
174
175 comment { feature selections }
176 define FEATURE_NAT44 comment
177 define FEATURE_CNAT uncomment
178 define FEATURE_DNS comment
179 define FEATURE_IP6 comment
180 define FEATURE_MACTIME uncomment
181
182 exec /setup.tmpl
183
184/setup.tmpl:
185
186.. code-block:: c
187
188 show macro
189
190 set int mac address $(TRUNK) $(TRUNK_MACADDR)
191 set dhcp client intfc $(TRUNK) hostname $(HOSTNAME)
192 set int state $(TRUNK) up
193
194 bvi create instance 0
195 set int mac address bvi0 $(BVI_MACADDR)
196 set int l2 bridge bvi0 1 bvi
197 set int ip address bvi0 192.168.$(INSIDE_SUBNET).1/24
198 set int state bvi0 up
199
200 set int l2 bridge $(INSIDE_PORT1) 1
201 set int state $(INSIDE_PORT1) up
202 set int l2 bridge $(INSIDE_PORT2) 1
203 set int state $(INSIDE_PORT2) up
204 set int l2 bridge $(INSIDE_PORT3) 1
205 set int state $(INSIDE_PORT3) up
206 set int l2 bridge $(INSIDE_PORT4) 1
207 set int state $(INSIDE_PORT4) up
208
209 comment { dhcp server and host-stack access }
210 create tap host-if-name lstack host-ip4-addr 192.168.$(INSIDE_SUBNET).2/24 host-ip4-gw 192.168.$(INSIDE_SUBNET).1
211 set int l2 bridge tap0 1
212 set int state tap0 up
213
214 service restart isc-dhcp-server
215
216 $(FEATURE_NAT44) { nat44 enable users 50 user-sessions 750 sessions 63000 }
217 $(FEATURE_NAT44) { nat44 add interface address $(TRUNK) }
218 $(FEATURE_NAT44) { set interface nat44 in bvi0 out $(TRUNK) }
219
220 $(FEATURE_NAT44) { nat44 add static mapping local 192.168.$(INSIDE_SUBNET).2 22432 external $(TRUNK) 22432 tcp }
221
222 $(FEATURE_CNAT) { cnat snat with $(TRUNK) }
223 $(FEATURE_CNAT) { set interface feature bvi0 ip4-cnat-snat arc ip4-unicast }
224 $(FEATURE_CNAT) { cnat translation add proto tcp real $(TRUNK) 22432 to -> 192.168.$(INSIDE_SUBNET).2 22432 }
225 $(FEATURE_CNAT) { $(FEATURE_DNS) { cnat translation add proto udp real $(TRUNK) 53053 to -> 192.168.$(INSIDE_SUBNET).1 53053 } }
226
227 $(FEATURE_DNS) { $(FEATURE_NAT44) { nat44 add identity mapping external $(TRUNK) udp 53053 } }
228 $(FEATURE_DNS) { bin dns_name_server_add_del 8.8.8.8 }
229 $(FEATURE_DNS) { bin dns_enable_disable }
230
231 comment { set ct6 inside $(TRUNK) }
232 comment { set ct6 outside $(TRUNK) }
233
234 $(FEATURE_IP6) { set int ip6 table $(TRUNK) 0 }
235 $(FEATURE_IP6) { ip6 nd address autoconfig $(TRUNK) default-route }
236 $(FEATURE_IP6) { dhcp6 client $(TRUNK) }
237 $(FEATURE_IP6) { dhcp6 pd client $(TRUNK) prefix group hgw }
238 $(FEATURE_IP6) { set ip6 address bvi0 prefix group hgw ::1/64 }
239 $(FEATURE_IP6) { ip6 nd address autoconfig bvi0 default-route }
240 comment { iPhones seem to need lots of RA messages... }
241 $(FEATURE_IP6) { ip6 nd bvi0 ra-managed-config-flag ra-other-config-flag ra-interval 5 3 ra-lifetime 180 }
242 comment { ip6 nd bvi0 prefix 0::0/0 ra-lifetime 100000 }
243
244
245 $(FEATURE_MACTIME) { bin mactime_add_del_range name cisco-vpn mac a8:b4:56:e1:b8:3e allow-static }
246 $(FEATURE_MACTIME) { bin mactime_add_del_range name old-mac mac <redacted> allow-static }
247 $(FEATURE_MACTIME) { bin mactime_add_del_range name roku mac <redacted> allow-static }
248 $(FEATURE_MACTIME) { bin mactime_enable_disable $(INSIDE_PORT1) }
249 $(FEATURE_MACTIME) { bin mactime_enable_disable $(INSIDE_PORT2) }
250 $(FEATURE_MACTIME) { bin mactime_enable_disable $(INSIDE_PORT3) }
251 $(FEATURE_MACTIME) { bin mactime_enable_disable $(INSIDE_PORT4) }
252
253Installing new vpp software
254---------------------------
255
256If you're **sure** that a given set of vpp Debian packages will install
257and work properly, you can install them while logged into the gateway
258via the lstack / nat path. This procedure is a bit like standing on a
259rug and yanking it. If all goes well, a perfect back-flip occurs. If
260not, you may wish that you'd configured a static IP address on a
261reserved Ethernet interface as described above.
262
263Installing a new vpp image via ssh to 192.168.1.2:
264
265.. code-block:: c
266
267 # nohup dpkg -i *.deb >/dev/null 2>&1 &
268
269Within a few seconds, the inbound ssh connection SHOULD begin to respond
270again. If it does not, you'll have to debug the issue(s).
271
272Reasonably Robust Remote Software Installation
273----------------------------------------------
274
275Here are a couple of scripts which yield a reasonably robust software
276installation scheme.
277
278Build-host script
279~~~~~~~~~~~~~~~~~
280
281.. code-block:: c
282
283 #!/bin/bash
284
285 buildroot=/scratch/vpp-workspace/build-root
286 if [ $1x = "testx" ] ; then
287 subdir="test"
288 ipaddr="192.168.2.48"
289 elif [ $1x = "foox" ] ; then
290 subdir="foo"
291 ipaddr="foo.some.net"
292 elif [ $1x = "barx" ] ; then
293 subdir="bar"
294 ipaddr="bar.some.net"
295 else
296 subdir="test"
297 ipaddr="192.168.2.48"
298 fi
299
300 echo Save current software...
301 ssh -p 22432 $ipaddr "rm -rf /gate_debians.prev"
302 ssh -p 22432 $ipaddr "mv /gate_debians /gate_debians.prev"
303 ssh -p 22432 $ipaddr "mkdir /gate_debians"
304 echo Copy new software to the gateway...
305 scp -P 22432 $buildroot/*.deb $ipaddr:/gate_debians
306 echo Install new software...
307 ssh -p 22432 $ipaddr "nohup /usr/local/bin/vpp-swupdate > /dev/null 2>&1 &"
308
309 for i in 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1
310 do
311 echo Wait for $i seconds...
312 sleep 1
313 done
314
315 echo Try to access the device...
316
317 ssh -p 22432 -o ConnectTimeout=10 $ipaddr "tail -20 /var/log/syslog | grep Ping"
318 if [ $? == 0 ] ; then
319 echo Access test OK...
320 else
321 echo Access failed, wait for configuration restoration...
322 for i in 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1
323 do
324 echo Wait for $i seconds...
325 sleep 1
326 done
327 echo Retry access test
328 ssh -p 22432 -o ConnectTimeout=10 $ipaddr "tail -20 /var/log/syslog | grep Ping"
329 if [ $? == 0 ] ; then
330 echo Access test OK, check syslog on the device
331 exit 1
332 else
333 echo Access test still fails, manual intervention required.
334 exit 2
335 fi
336 fi
337
338 exit 0
339
340Target script
341~~~~~~~~~~~~~
342
343.. code-block:: c
344
345 #!/bin/bash
346
347 logger "About to update vpp software..."
348 cd /gate_debians
349 service vpp stop
350 sudo dpkg -i *.deb >/dev/null 2>&1 &
351 sleep 20
352 logger "Ping connectivity test..."
353 for i in 1 2 3 4 5 6 7 8 9 10
354 do
355 ping -4 -c 1 yahoo.com
356 if [ $? == 0 ] ; then
357 logger "Ping test OK..."
358 exit 0
359 fi
360 done
361
362 logger "Ping test NOT OK, restore old software..."
363 rm -rf /gate_debians
364 mv /gate_debians.prev /gate_debians
365 cd /gate_debians
366 nohup sudo dpkg -i *.deb >/dev/null 2>&1 &
367 sleep 20
368 logger "Repeat connectivity test..."
369 for i in 1 2 3 4 5 6 7 8 9 10
370 do
371 ping -4 -c 1 yahoo.com
372 if [ $? == 0 ] ; then
373 logger "Ping test OK after restoring old software..."
374 exit 0
375 fi
376 done
377
378 logger "Ping test FAIL after restoring software, manual intervention required"
379 exit 2
380
381Note that the target script **requires** that the user id which invokes
382it will manage to “sudo dpkg …” without further authentication. If
383you’re uncomfortable with the security implications of that requirement,
384you’ll need to solve the problem a different way. Strongly suggest
385configuring sshd as described above to minimize risk.
386
387Testing new software
388--------------------
389
390If you frequently test new home gateway software, it may be handy to set
391up a test gateway behind your production gateway. This testing
392methodology reduces complaints from family members, to name one benefit.
393
394Change the inside network (dhcp) subnet from 192.168.1.0/24 to
395192.168.3.0/24, change the (dhcp) advertised router to 192.168.3.1,
396reconfigure the vpp tap interface addresses onto the 192.168.3.0/24
397subnet, and you should be all set.
398
399This scenario nats traffic twice: first, from the 192.168.3.0/24 network
400onto the 192.168.1.0/24 network. Next, from the 192.168.1.0/24 network
401onto the public internet.
402
403Patches
404-------
405
406You'll want this addition to src/vpp/vnet/main.c to add the "service
407restart isc-dhcp-server” and "service restart vpp" commands:
408
409.. code-block:: c
410
411 #include <sys/types.h>
412 #include <sys/wait.h>
413
414 static int
415 mysystem (char *cmd)
416 {
417 int rv = 0;
418
419 if (fork())
420 wait (&rv);
421 else
422 execl("/bin/sh", "sh", "-c", cmd);
423
424 if (rv != 0)
425 clib_unix_warning ("('%s') child process returned %d", cmd, rv);
426 return rv;
427 }
428
429 static clib_error_t *
430 restart_isc_dhcp_server_command_fn (vlib_main_t * vm,
431 unformat_input_t * input,
432 vlib_cli_command_t * cmd)
433 {
434 int rv;
435
436 /* Wait a while... */
437 vlib_process_suspend (vm, 2.0);
438
439 rv = mysystem("/usr/sbin/service isc-dhcp-server restart");
440
441 vlib_cli_output (vm, "Restarted the isc-dhcp-server, status %d...", rv);
442 return 0;
443 }
444
445 VLIB_CLI_COMMAND (restart_isc_dhcp_server_command, static) =
446 {
447 .path = "service restart isc-dhcp-server",
448 .short_help = "restarts the isc-dhcp-server",
449 .function = restart_isc_dhcp_server_command_fn,
450 };
451
452 static clib_error_t *
453 restart_dora_tunnels_command_fn (vlib_main_t * vm,
454 unformat_input_t * input,
455 vlib_cli_command_t * cmd)
456 {
457 int rv;
458
459 /* Wait three seconds... */
460 vlib_process_suspend (vm, 3.0);
461
462 rv = mysystem ("/usr/sbin/service dora restart");
463
464 vlib_cli_output (vm, "Restarted the dora tunnel service, status %d...", rv);
465 return 0;
466 }
467
468 VLIB_CLI_COMMAND (restart_dora_tunnels_command, static) =
469 {
470 .path = "service restart dora",
471 .short_help = "restarts the dora tunnel service",
472 .function = restart_dora_tunnels_command_fn,
473 };
474
475 static clib_error_t *
476 restart_vpp_service_command_fn (vlib_main_t * vm,
477 unformat_input_t * input,
478 vlib_cli_command_t * cmd)
479 {
480 (void) mysystem ("/usr/sbin/service vpp restart");
481 return 0;
482 }
483
484 VLIB_CLI_COMMAND (restart_vpp_service_command, static) =
485 {
486 .path = "service restart vpp",
487 .short_help = "restarts the vpp service, be careful what you wish for",
488 .function = restart_vpp_service_command_fn,
489 };
490
491Using the time-based mac filter plugin
492--------------------------------------
493
494If you need to restrict network access for certain devices to specific
495daily time ranges, configure the "mactime" plugin. Add it to the list of
496enabled plugins in /etc/vpp/startup.conf, then enable the feature on the
497NAT "inside" interfaces:
498
499.. code-block:: c
500
501 bin mactime_enable_disable GigabitEthernet0/14/0
502 bin mactime_enable_disable GigabitEthernet0/14/1
503 ...
504
505Create the required src-mac-address rule database. There are 4 rule
506entry types:
507
508- allow-static - pass traffic from this mac address
509- drop-static - drop traffic from this mac address
510- allow-range - pass traffic from this mac address at specific times
511- drop-range - drop traffic from this mac address at specific times
512
513Here are some examples:
514
515.. code-block:: c
516
517 bin mactime_add_del_range name alarm-system mac 00:de:ad:be:ef:00 allow-static
518 bin mactime_add_del_range name unwelcome mac 00:de:ad:be:ef:01 drop-static
519 bin mactime_add_del_range name not-during-business-hours mac <mac> drop-range Mon - Fri 7:59 - 18:01
520 bin mactime_add_del_range name monday-busines-hours mac <mac> allow-range Mon 7:59 - 18:01