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