blob: 9fd4bc0c5db63b0817b15edc3028a7e89a54d78c [file] [log] [blame]
Nathan Skrzypczak9ad39c02021-08-19 11:38:06 +02001Simulating networks with VPP
2============================
3
4The make test framework provides a good way to test individual
5features. However, when testing several features at once - or validating
6nontrivial configurations - it may prove difficult or impossible to use
7the unit-test framework.
8
9This note explains how to set up lxc/lxd, and a 5-container testbed to
10test a split-tunnel nat + ikev2 + ipsec + ipv6 prefix-delegation
11scenario.
12
13OS / Distro test results
14------------------------
15
Dave Barachb7e66f42023-12-29 11:15:34 -050016This setup has been tested on Ubuntu 18.04 - 22.04 LTS systems. Other
17distros may work fine, or not at all.
Nathan Skrzypczak9ad39c02021-08-19 11:38:06 +020018
19Proxy Server
20------------
21
22If you need to use a proxy server e.gfrom a lab system, youll
23probably need to set HTTP_PROXY, HTTPS_PROXY, http_proxy and https_proxy
24in /etc/environment. Directly setting variables in the environment
25doesnt work. The lxd snap *daemon* needs the proxy settings, not the
26user interface.
27
28Something like so:
29
30::
31
32 HTTP_PROXY=http://my.proxy.server:8080
33 HTTPS_PROXY=http://my.proxy.server:4333
34 http_proxy=http://my.proxy.server:8080
35 https_proxy=http://my.proxy.server:4333
36
37Install and configure lxd
38-------------------------
39
40Install the lxd snap. The lxd snap is up to date, as opposed to the
41results of sudo apt-get install lxd”.
42
43::
44
45 # snap install lxd
46 # lxd init
47
48lxd init asks several questions. With the exception of the storage
49pool, take the defaults. To match the configs shown below, create a
50storage pool named vpp.” Storage pools of type zfs and files have
51been tested successfully.
52
53zfs is more space-efficient. lxc copy is infinitely faster with zfs.
54The path for the zfs storage pool is under /var. Do not replace it with
55a symbolic link, unless you want to rebuild all of your containers from
56scratch. Ask me how I know that.
57
58Create three network segments
59-----------------------------
60
61Aka, linux bridges.
62
63::
64
65 # lxc network create respond
66 # lxc network create internet
67 # lxc network create initiate
68
69Well explain the test topology in a bit. Stay tuned.
70
71Set up the default container profile
72------------------------------------
73
74Execute lxc profile edit default”, and install the following
75configuration. Note that the shared directory should mount your vpp
76workspaces. With that trick, you can edit code from any of the
77containers, run vpp without installing it, etc.
78
79::
80
81 config: {}
82 description: Default LXD profile
83 devices:
84 eth0:
85 name: eth0
86 network: lxdbr0
87 type: nic
88 eth1:
89 name: eth1
90 nictype: bridged
91 parent: internet
92 type: nic
93 eth2:
94 name: eth2
95 nictype: bridged
96 parent: respond
97 type: nic
98 eth3:
99 name: eth3
100 nictype: bridged
101 parent: initiate
102 type: nic
103 root:
104 path: /
105 pool: vpp
106 type: disk
107 shared:
108 path: /scratch
109 source: /scratch
110 type: disk
111 name: default
112
Dave Barachb7e66f42023-12-29 11:15:34 -0500113
Nathan Skrzypczak9ad39c02021-08-19 11:38:06 +0200114Set up the network configurations
115---------------------------------
116
117Edit the fake internet backbone:
118
119::
120
121 # lxc network edit internet
122
123Install the ip addresses shown below, to avoid having to rebuild the vpp
124and host configuration:
125
126::
127
Dave Barachb7e66f42023-12-29 11:15:34 -0500128 config:
129 ipv4.address: 10.26.68.1/24
130 ipv4.dhcp.ranges: 10.26.68.10-10.26.68.50
131 ipv4.nat: "true"
132 ipv6.address: none
133 ipv6.nat: "false"
134 description: ""
135 name: internet
136 type: bridge
137 used_by:
138 managed: true
139 status: Created
140 locations:
141 - none
Nathan Skrzypczak9ad39c02021-08-19 11:38:06 +0200142
143Repeat the process with the respond and initiate networks, using
144these configurations:
145
146respond network configuration
147~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
148
149::
150
151 config:
152 ipv4.address: 10.166.14.1/24
153 ipv4.dhcp.ranges: 10.166.14.10-10.166.14.50
154 ipv4.nat: "true"
155 ipv6.address: none
156 ipv6.nat: "false"
157 description: ""
158 name: respond
159 type: bridge
160 used_by:
161 managed: true
162 status: Created
163 locations:
164 - none
165
166initiate network configuration
167~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
168
169::
170
171 config:
172 ipv4.address: 10.219.188.1/24
173 ipv4.dhcp.ranges: 10.219.188.10-10.219.188.50
174 ipv4.nat: "true"
175 ipv6.address: none
176 ipv6.nat: "false"
177 description: ""
178 name: initiate
179 type: bridge
180 used_by:
181 managed: true
182 status: Created
183 locations:
Nathan Skrzypczak9ad39c02021-08-19 11:38:06 +0200184
185Create a master container image
186---------------------------------
187
188The master container image should be set up so that you can build vpp,
189ssh into the container, edit source code, run gdb, etc.
190
191Make sure that e.gpublic key auth ssh works.
192
193::
194
Dave Barachb7e66f42023-12-29 11:15:34 -0500195 # lxd launch ubuntu:22.04 respond
Nathan Skrzypczak9ad39c02021-08-19 11:38:06 +0200196 <spew>
197 # lxc exec respond bash
198 respond# cd /scratch/my-vpp-workspace
199 respond# apt-get install make ssh
200 respond# make install-dep
201 respond# exit
202 # lxc stop respond
203
204Mark the container image privileged. If you forget this step, youll
205trip over a netlink error (-11) aka EAGAIN when you try to roll in the
206vpp configurations.
207
208::
209
210 # lxc config set respond security.privileged "true"
211
212Duplicate the master container image
213--------------------------------------
214
215To avoid having to configure N containers, be sure that the master
216container image is fully set up before you help it have children:
217
218::
219
220 # lxc copy respond respondhost
221 # lxc copy respond initiate
222 # lxc copy respond initiatehost
223 # lxc copy respond dhcpserver # optional, to test ipv6 prefix delegation
224
225Install handy script
226--------------------
227
Dave Barachb7e66f42023-12-29 11:15:34 -0500228See below for a handy host script which executes lxc commands across
229the current set of running containers. I call it lxc-foreach,” feel
230free to call the script Ishmael if you like.
Nathan Skrzypczak9ad39c02021-08-19 11:38:06 +0200231
232Examples:
233
234::
235
236 $ lxc-foreach start
237 <issues "lxc start" for each container in the list>
238
239After a few seconds, use this one to open an ssh connection to each
240container. The ssh command parses the output of lxc info,” which
241displays container ip addresses.
242
243::
244
245 $ lxc-foreach ssh
246
247Heres the script:
248
249::
250
Dave Barachb7e66f42023-12-29 11:15:34 -0500251 #!/bin/bash
Nathan Skrzypczak9ad39c02021-08-19 11:38:06 +0200252
Dave Barachb7e66f42023-12-29 11:15:34 -0500253 set -u
254 export containers="respond initiate initiatehost respondhost"
Nathan Skrzypczak9ad39c02021-08-19 11:38:06 +0200255
Dave Barachb7e66f42023-12-29 11:15:34 -0500256 if [ x$1 = "x" ] ; then
257 echo missing command
258 exit 1
259 fi
Nathan Skrzypczak9ad39c02021-08-19 11:38:06 +0200260
Dave Barachb7e66f42023-12-29 11:15:34 -0500261 if [ $1 = "ssh" ] ; then
262 for c in $containers
263 do
Nathan Skrzypczak9ad39c02021-08-19 11:38:06 +0200264
Dave Barachb7e66f42023-12-29 11:15:34 -0500265 inet=`lxc info $c | grep 10.38.33 | sed "s/.*inet://" | sed "s/\/24.*//" | tr -d " "`
266 if [ x$inet != "x" ] ; then
267 gnome-terminal --title "$c(ssh)" --command "/usr/bin/ssh -Y root@$inet"
268 fi
269 done
270 exit 0
271 fi
Nathan Skrzypczak9ad39c02021-08-19 11:38:06 +0200272
Dave Barachb7e66f42023-12-29 11:15:34 -0500273 for c in $containers
274 do
275 inet=`lxc info $c | grep 10.38.33 | sed "s/.*inet://" | sed "s/\/24.*//" | tr -d " "`
276 if [ x$1 = "xstart" ] ; then
277 echo Starting $c
278 lxc start $c
279 elif [ x$1 = "xstop" ] ; then
280 echo Stopping $c
281 lxc stop $c
282 elif [ x$inet != "x" ] ; then
283 echo lxc $1 $c
284 lxc $1 $c
285 fi
286 done
287
288 exit 0
Nathan Skrzypczak9ad39c02021-08-19 11:38:06 +0200289
290Test topology
291-------------
292
293Finally, were ready to describe a test topology. First, a picture:
294
295::
296
Dave Barachb7e66f42023-12-29 11:15:34 -0500297 ===+======== management lan/bridge lxdbr0 (dhcp) ==============+===
298 | | |
299 | | |
300 | | |
301 v | v
302 eth0 | eth0
303 +---------+ eth1 eth1 +----------+
Nathan Skrzypczak9ad39c02021-08-19 11:38:06 +0200304 | respond | 10.26.88.100 <= internet bridge => 10.26.88.101 | initiate |
Dave Barachb7e66f42023-12-29 11:15:34 -0500305 +---------+ +----------+
Nathan Skrzypczak9ad39c02021-08-19 11:38:06 +0200306 eth2 / bvi0 10.166.14.2 | 10.219.188.2 eth3 / bvi0
Dave Barachb7e66f42023-12-29 11:15:34 -0500307 | | |
308 | ("respond" bridge) | ("initiate" bridge) |
309 | | |
310 v | v
311 eth2 10.166.14.3 | eth3 10.219.188.3
312 +-------------+ | +-------------+
313 | respondhost | | | respondhost |
314 +-------------+ | +-------------+
315 v
Nathan Skrzypczak9ad39c02021-08-19 11:38:06 +0200316 eth0 (management lan) <========+========> eth0 (management lan)
317
318Test topology discussion
319~~~~~~~~~~~~~~~~~~~~~~~~
320
321This topology is suitable for testing almost any tunnel encap/decap
322scenario. The two containers respondhost and initiatehost are
323end-stations connected to two vpp instances running on respond and
324initiate”.
325
326We leverage the Linux end-station network stacks to generate traffic of
327all sorts.
328
329The so-called internet bridge models the public internet. The
330respond and initiate bridges connect vpp instances to local hosts
331
332End station configs
333-------------------
334
335The end-station Linux configurations set up the eth2 and eth3 ip
336addresses shown above, and add tunnel routes to the opposite end-station
337networks.
338
339respondhost configuration
340~~~~~~~~~~~~~~~~~~~~~~~~~
341
342::
343
344 ifconfig eth2 10.166.14.3/24 up
345 route add -net 10.219.188.0/24 gw 10.166.14.2
346
347initiatehost configuration
348~~~~~~~~~~~~~~~~~~~~~~~~~~
349
350::
351
352 sudo ifconfig eth3 10.219.188.3/24 up
353 sudo route add -net 10.166.14.0/24 gw 10.219.188.2
354
355VPP configs
356-----------
357
358Split nat44 / ikev2 + ipsec tunneling, with ipv6 prefix delegation in
359the respond config.
360
361respond configuration
362~~~~~~~~~~~~~~~~~~~~~
363
364::
365
366 set term pag off
367
368 comment { "internet" }
369 create host-interface name eth1
370 set int ip address host-eth1 10.26.68.100/24
371 set int ip6 table host-eth1 0
372 set int state host-eth1 up
373
374 comment { default route via initiate }
375 ip route add 0.0.0.0/0 via 10.26.68.101
376
377 comment { "respond-private-net" }
378 create host-interface name eth2
379 bvi create instance 0
380 set int l2 bridge bvi0 1 bvi
381 set int ip address bvi0 10.166.14.2/24
382 set int state bvi0 up
383 set int l2 bridge host-eth2 1
384 set int state host-eth2 up
385
386
387 nat44 add interface address host-eth1
388 set interface nat44 in host-eth2 out host-eth1
389 nat44 add identity mapping external host-eth1 udp 500
390 nat44 add identity mapping external host-eth1 udp 4500
391 comment { nat44 untranslated subnet 10.219.188.0/24 }
392
393 comment { responder profile }
394 ikev2 profile add initiate
395 ikev2 profile set initiate udp-encap
396 ikev2 profile set initiate auth rsa-sig cert-file /scratch/setups/respondcert.pem
397 set ikev2 local key /scratch/setups/initiatekey.pem
398 ikev2 profile set initiate id local fqdn initiator.my.net
399 ikev2 profile set initiate id remote fqdn responder.my.net
400 ikev2 profile set initiate traffic-selector remote ip-range 10.219.188.0 - 10.219.188.255 port-range 0 - 65535 protocol 0
401 ikev2 profile set initiate traffic-selector local ip-range 10.166.14.0 - 10.166.14.255 port-range 0 - 65535 protocol 0
402 create ipip tunnel src 10.26.68.100 dst 10.26.68.101
403 ikev2 profile set initiate tunnel ipip0
404
405 comment { ipv6 prefix delegation }
406 ip6 nd address autoconfig host-eth1 default-route
407 dhcp6 client host-eth1
408 dhcp6 pd client host-eth1 prefix group hgw
409 set ip6 address bvi0 prefix group hgw ::2/56
410 ip6 nd address autoconfig bvi0 default-route
411 ip6 nd bvi0 ra-interval 5 3 ra-lifetime 180
412
413 set int mtu packet 1390 ipip0
414 set int unnum ipip0 use host-eth1
415 ip route add 10.219.188.0/24 via ipip0
416
417initiate configuration
418~~~~~~~~~~~~~~~~~~~~~~
419
420::
421
422 set term pag off
423
424 comment { "internet" }
425 create host-interface name eth1
426 comment { set dhcp client intfc host-eth1 hostname initiate }
427 set int ip address host-eth1 10.26.68.101/24
428 set int state host-eth1 up
429
430 comment { default route via "internet gateway" }
431 comment { ip route add 0.0.0.0/0 via 10.26.68.1 }
432
433 comment { "initiate-private-net" }
434 create host-interface name eth3
435 bvi create instance 0
436 set int l2 bridge bvi0 1 bvi
437 set int ip address bvi0 10.219.188.2/24
438 set int state bvi0 up
439 set int l2 bridge host-eth3 1
440 set int state host-eth3 up
441
442 nat44 add interface address host-eth1
443 set interface nat44 in bvi0 out host-eth1
444 nat44 add identity mapping external host-eth1 udp 500
445 nat44 add identity mapping external host-eth1 udp 4500
446 comment { nat44 untranslated subnet 10.166.14.0/24 }
447
448 comment { initiator profile }
449 ikev2 profile add respond
450 ikev2 profile set respond udp-encap
451 ikev2 profile set respond auth rsa-sig cert-file /scratch/setups/initiatecert.pem
452 set ikev2 local key /scratch/setups/respondkey.pem
453 ikev2 profile set respond id local fqdn responder.my.net
454 ikev2 profile set respond id remote fqdn initiator.my.net
455
456 ikev2 profile set respond traffic-selector remote ip-range 10.166.14.0 - 10.166.14.255 port-range 0 - 65535 protocol 0
457 ikev2 profile set respond traffic-selector local ip-range 10.219.188.0 - 10.219.188.255 port-range 0 - 65535 protocol 0
458
459 ikev2 profile set respond responder host-eth1 10.26.68.100
460 ikev2 profile set respond ike-crypto-alg aes-cbc 256 ike-integ-alg sha1-96 ike-dh modp-2048
461 ikev2 profile set respond esp-crypto-alg aes-cbc 256 esp-integ-alg sha1-96 esp-dh ecp-256
462 ikev2 profile set respond sa-lifetime 3600 10 5 0
463
464 create ipip tunnel src 10.26.68.101 dst 10.26.68.100
465 ikev2 profile set respond tunnel ipip0
466 ikev2 initiate sa-init respond
467
468 set int mtu packet 1390 ipip0
469 set int unnum ipip0 use host-eth1
470 ip route add 10.166.14.0/24 via ipip0
471
472IKEv2 certificate setup
473-----------------------
474
475In both of the vpp configurations, youll see “/scratch/setups/xxx.pem
476mentioned. These certificates are used in the ikev2 key exchange.
477
478Heres how to generate the certificates:
479
480::
481
482 openssl req -x509 -nodes -newkey rsa:4096 -keyout respondkey.pem -out respondcert.pem -days 3560
483 openssl x509 -text -noout -in respondcert.pem
484 openssl req -x509 -nodes -newkey rsa:4096 -keyout initiatekey.pem -out initiatecert.pem -days 3560
485 openssl x509 -text -noout -in initiatecert.pem
486
487Make sure that the respond and initiate configurations point to the
488certificates.
489
490DHCPv6 server setup
491-------------------
492
493If you need an ipv6 dhcp server to test ipv6 prefix delegation, create
494the dhcpserver container as shown above.
495
496Install the isc-dhcp-server Debian package:
497
498::
499
500 sudo apt-get install isc-dhcp-server
501
502/etc/dhcp/dhcpd6.conf
503~~~~~~~~~~~~~~~~~~~~~
504
505Edit the dhcpv6 configuration and add an ipv6 subnet with prefix
506delegation. For example:
507
508::
509
510 subnet6 2001:db01:0:1::/64 {
511 range6 2001:db01:0:1::1 2001:db01:0:1::9;
512 prefix6 2001:db01:0:100:: 2001:db01:0:200::/56;
513 }
514
515Add an ipv6 address on eth1, which is connected to the internet
516bridge, and start the dhcp server. I use the following trivial bash
517script, which runs the dhcp6 server in the foreground and produces dhcp
518traffic spew:
519
520::
521
522 #!/bin/bash
523 ifconfig eth1 inet6 add 2001:db01:0:1::10/64 || true
524 dhcpd -6 -d -cf /etc/dhcp/dhcpd6.conf
525
526The \|\| true bit keeps going if eth1 already has the indicated ipv6
527address.
528
529Container / Host Interoperation
530-------------------------------
531
532Host / container interoperation is highly desirable. If the host and a
533set of containers dont run the same distro *and distro version*, its
534reasonably likely that the glibc versions wont match. That, in turn,
535makes vpp binaries built in one environment fail in the other.
536
537Trying to install multiple versions of glibc - especially at the host
538level - often ends very badly and is *not recommended*. Its not just
539glibc, either. The dynamic loader ld-linux-xxx-so.2 is glibc version
540specific.
541
542Fortunately, its reasonable easy to build lxd container images based on
543specific Ubuntu or Debian versions.
544
545Create a custom root filesystem image
546~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
547
548First, install the debootstrap tool:
549
550::
551
552 sudo apt-get install debootstrap
553
554Make a temp directory, and use debootstrap to populate it. In this
555example, we create an Ubuntu 20.04 (focal fossa) base image:
556
557::
558
559 # mkdir /tmp/myroot
560 # debootstrap focal /tmp/myroot http://archive.ubuntu.com/ubuntu
561
562To tinker with the base image (if desired):
563
564::
565
566 # chroot /tmp/myroot
567 <add packages, etc.>
568 # exit
569
570Make a compressed tarball of the base image:
571
572::
573
574 # tar zcf /tmp/rootfs.tar.gz -C /tmp/myroot .
575
576Create a metadata.yaml file which describes the base image:
577
578::
579
580 architecture: "x86_64"
581 # To get current date in Unix time, use `date +%s` command
582 creation_date: 1458040200
583 properties:
584 architecture: "x86_64"
585 description: "My custom Focal Fossa image"
586 os: "Ubuntu"
587 release: "focal"
588
589Make a compressed tarball of metadata.yaml:
590
591::
592
593 # tar zcf metadata.tar.gz metadata.yaml
594
595Import the image into lxc / lxd:
596
597::
598
599 $ lxc image import metadata.tar.gz rootfd.tar.gz --alias focal-base
600
601Create a container which uses the customized base image:
602~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
603
604::
605
606 $ lxc launch focal-base focaltest
607 $ lxc exec focaltest bash
608
609The next several steps should be executed in the container, in the bash
610shell spun up by lxc exec…”
611
612Configure container networking
613~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
614
615In the container, create /etc/netplan/50-cloud-init.yaml:
616
617::
618
619 network:
620 version: 2
621 ethernets:
622 eth0:
623 dhcp4: true
624
625Use cat > /etc/netplan/50-cloud-init.yaml”, and cut-’n-paste if your
626favorite text editor is AWOL.
627
628Apply the configuration:
629
630::
631
632 # netplan apply
633
634At this point, eth0 should have an ip address, and you should see a
635default route with route -n”.
636
637Configure apt
638~~~~~~~~~~~~~
639
640Again, in the container, set up /etc/apt/sources.list via cut-’n-paste
641from a recently update focal fossa host. Something like so:
642
643::
644
645 deb http://us.archive.ubuntu.com/ubuntu/ focal main restricted
646 deb http://us.archive.ubuntu.com/ubuntu/ focal-updates main restricted
647 deb http://us.archive.ubuntu.com/ubuntu/ focal universe
648 deb http://us.archive.ubuntu.com/ubuntu/ focal-updates universe
649 deb http://us.archive.ubuntu.com/ubuntu/ focal multiverse
650 deb http://us.archive.ubuntu.com/ubuntu/ focal-updates multiverse
651 deb http://us.archive.ubuntu.com/ubuntu/ focal-backports main restricted universe multiverse
652 deb http://security.ubuntu.com/ubuntu focal-security main restricted
653 deb http://security.ubuntu.com/ubuntu focal-security universe
654 deb http://security.ubuntu.com/ubuntu focal-security multiverse
655
656apt-get update and apt-install should produce reasonable results.
657Suggest apt-get install make git”.
658
659At this point, you can use the “/scratch sharepoint (or similar) to
660execute make install-dep install-ext-deps to set up the container with
661the vpp toolchain; proceed as desired.