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