Příprava experimentálního prostředí

Stránky: CZ.NIC Moodle
Kurz: Síťování v Linuxu
Kniha: Příprava experimentálního prostředí
Vytiskl(a): Nepřihlášený host
Datum: sobota, 27. dubna 2024, 09.05

Spuštění virtuálního stroje

VirtualBox

V první řadě je třeba nainstalovat hypervisor - virtualizační prostředí pro operační systém, který používáte na své pracovní stanici. VirtualBox je dostupný zdarma pro osobní užití a výukové účely. Pro detaily si dovolujeme odkázat na aktuální licenci, která je dostupná společně s balíčky ke stažení na stránkách projektu: https://www.virtualbox.org/.

Pro instalaci VirtualBoxu vyberte na stránkách https://www.virtualbox.org/ poslední doporučenou verzi pro operační systém, který máte na vaší pracovní stanici. Stáhněte příslušný balíček se softwarem a nainstalujte jej dle návodu (v závislosti na vašem operačním systému, respektive prostředí).

Image Ubuntu 20.04 LTS

V našich experimentech vyjdeme z distribuce operačního systému GNU/Linux - Ubuntu Linux 20.04 LTS. Image jsou připravené ke stažení zdarma od projektu osboxes.org. Na stránce https://www.osboxes.org/ubuntu-server/ vyberte verzi 20.04, stáhněte archiv s image souborem (Ubnt-Svr-20.04-VB-64bit.7z), soubor rozbalte a získáte image pro VirtualBox (Ubuntu Server 20.04 (64bit).vdi).

Vytvoření VM (virtuálního stroje)

Spusťte VirtualBox. V menu Machine vytvořte nový VM (virtuální stroj) a zvolte Linux a distribuci Ubuntu (64-bit), jako na následujícím screenshotu.

VirtualBox - Nový VM

Než budete pokračovat, doporučujeme udělat si kopii staženého image Ubuntu Server 20.04 (64bit).vdi do adresáře, který vytvořil VirtualBox pro nově vzniklou VM (Sitovani). Následně můžeme image vybrat (nápovědou je následující screenshot - je třeba image přidat přes tlačítko Add, vybrat soubor ve file systému a pak zvolit v dialogu na screenshotu):

VirtualBox - VM image

Po potvrzení vznikne VM. Před prvním spuštěním VM je dalším krokem editace nastavení sítě. Umožňuje-li to Váš systém a nastavení vaší sítě, nastavte Attached to na Bridged adapter a vyberte na který interface se bude bridgovat a povolte Promiscuous Mode odevšud (Allow All). V našem případě jsme zvolili interface enx28f10e4d92d5, což je USB Ethernet adaptér, kterým jsme připojeni do LAN a přes NAT do Internetu.

Je třeba ověřit pravidla a nastavení lokální sítě, zda je na Vaší pracovní stanici dovolen provoz VM přímo připojených do sítě. Především jde o to, aby bylo povolenéopoužívat různé MAC adresy a IP adresy na tom samém portu switche. To ve většině domácích sítí a v malých firmách není problém. Centrálně spravované sítě ve větších firmách mají často provoz VM na klientských stanicích formálně zakázán a prakticky je vynucováno na switchích omezením počtu současné aktivních MAC adres na jednom portu. V tomto případě může spuštění další VM vést k odpojení portu a nutnosti vyčkat na timeout a nebo kontaktovat správce.

Následující screenshot ukazuje nastavení v našem případě.

Pokud vaše síť neumožňuje používat více MAC adres na jednom počítači respektive portu, eventuálně je nějaký jiný důvod, obejdeme se i s nastavením Attached to: NAT.

Pokud chcete používat WiFi, tak i v tomto případě nemusí bridge fungovat - WiFi adaptéry totiž většinou nesmí měnit svojí MAC adresu a tedy ani nemohou používat dvě najednou. VirtualBox to v některých případech dovede vyřešit, ale ne vždy.

Tím by mělo být nastavení hotovo a VM lze spustit (tlačítkem Start nebo přes kontextové menu VM). Pokud je vše v pořádku, měl by se po pár okamžicích spustit VM s operačním systémem Linux, podobně jako na následujícím screenshotu.

VirtualBox - new VM

Pokud je použit doporučený image z https://www.osboxes.org/ubuntu-server/ , pak je uživatelské jméno osboxes a heslo osboxes.org. Pro přepnutí do root účtu lze použít sudo su - a na výzvu opět zadat heslo uživatele osboxes.

Úvod do použitého virtuálního prostředí

Nainstalovaný VM s Ubuntu Linuxem je obdobný čistě nainstalovanému virtuálnímu serveru. Obdobného výsledku dosáhnete stažením oficiálního instalačního ISO image Ubuntu Server 20.04 LTS a standardní instalací. Tento postup je však mírně zdlouhavější a proto doporučujeme použít image projektu OS Boxes. Pokud by však image od OS Boxes nevyhovoval, je zde manuální instalace nebo případně použítí jiných image souborů, například od konkurenčního projektu VirtualBoxes - https://virtualboxes.org/images/ubuntu-server/.

Přihlášení

První přihlášení je zapotřebí udělat přes konzoli - ta je ukázana na posledním screenshotu v minulé kapitole. Jméno a heslo pochopitelně závisí na použitém image respektive na volbě při instalaci.

Pro další práci lze buď používat dále konzoli nebo v mnoha případech o něco pohodlnější SSH klient (na Linuxu ssh v terminálu, na Windows například PuTTY - https://www.putty.org/ ). Na to, aby se k VM bylo možné připojit SSH klientem je třeba splnit podmínky:

  • Mít nainstalovaný SSH server - příkazem sudo apt install ssh,
  • mít nastavenou IP adresu na bridged síťovém rozhraní VM,
  • znát tuto IP adresu na VM - příkazem ip address a hledáme IPv4 adresu na síťovém rozhraní enp0s3 resp. eth0.

Následující screenshot ukazuje náš příklad, kdy VM dostalo na brdiged síťové rozhraní IP adresu od DHCP serveru.

VM IP address

Z výpisu tedy vidíme, že IP adresa na rozhraní enp0s3 je 192.168.0.100.

Zkusíme se tedy připojit (poté, co se přesvědčíme, že máme nainstalovaný SSH server na VM) SSH klientem z pracovní stanice na VM. Pokud vše vyjde, uvidíte obdobný výstup jako když jsme na naší (linuxové) pracovní stanici použil příkaz ssh osboxes@192.168.0.100:

th@tapir:~$ ssh osboxes@192.168.0.100
The authenticity of host '192.168.0.100 (192.168.0.100)' can't be established.
ECDSA key fingerprint is SHA256:gTCDYqbsUNGHwrFRV1XuiFa+PpQ+nE2uoD0QqMGm5WE.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '192.168.0.100' (ECDSA) to the list of known hosts.
osboxes@192.168.0.100's password: 
Welcome to Ubuntu 20.04 LTS (GNU/Linux 5.4.0-28-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  System information as of Wed 30 Dec 2020 02:01:45 AM UTC

  System load:    0.0                Processes:               110
  Usage of /home: 0.0% of 249.01GB   Users logged in:         1
  Memory usage:   23%                IPv4 address for enp0s3: 192.168.0.100
  Swap usage:     0%

 * Introducing self-healing high availability clusters in MicroK8s.
   Simple, hardened, Kubernetes for production, from RaspberryPi to DC.

     https://microk8s.io/high-availability

182 updates can be installed immediately.
97 of these updates are security updates.
To see these additional updates run: apt list --upgradable


Last login: Tue Dec 29 04:16:27 2020
/usr/bin/xauth:  file /home/osboxes/.Xauthority does not exist
osboxes@osboxes:~$

U vás se bude pochopitelně lišit IP adresa, ev. použijete jiný SSH klient, pokud máte na pracovní stanici jiný OS, než Linux.

Kontejnery

Mohli bychom si sice vystačit s tím, že vytvoříme několik VM ve VirtualBoxu a mohli bychom mezi nimi nastavovat síťování, ale my půjdeme v prvních několika cvičeních cestou kontejnerů uvnitř naší VM.

Co jsou kontejnery a k čemu nám budou

  • Kontejnery jsou virtualizací userspacu, který ale běží s použitím jádra (kernelu), který používá "hypervisor" nebo lépe hostitel kontejnerů.
  • Kontejnery jsou méně náročné na prostředky (CPU, operační paměť a diskový prostor)
  • Kontejnery sice přinesou trochu složitosti navíc, ale hned na začátku si tak předvedeme použití zvlášť mocného nástroje - Linux network namespaces (nebo jen namespaces).
  • Každý kontejner má oddělené vlastní prostředí - namespace pro procesy, operační paměť, oddělený filesystém (to funguje podobně, jako chroot) a hlavně vlastní namespace pro síťový stack.
  • V neposlední řadě má praktický smysl toto znát - namespaces se běžně používají na serverech jako "lehká" virtualizace LXC resp. LXD a také jako spodní vrstva Dockeru.

Protože mají kontejnery oddělené síťové stacky, je nutné mít možnost kontejnery spojit mezi sebou - například pokud je v jednom kontejneru databázový server a v druhém aplikace, která DB servery používá. A pak je také potřeba umět kontejnery propojit s vnějším světem. To jde udělat několika způsoby.

Odkazy:

Nastavení sítě pro kontejnery

Zatím nebudeme zabíhat do detailů. Rozebrání funkce ethernetových switchů, softwarová emulace switche v Linuxu - bridge a routing v Linuxu bude obsahem následující kapitoly a ještě se k tomu několikát vrátíme v dalších kapitolách. Zatím tedy jen popíšeme, s čím začneme. Následující schéma ukazuje experimentální VM s kontejnery uvnitř, jak budou vypadat po instalaci LXC a vytvoření prvního kontejneru resp. prvních několika kontejnerů:

VM a LXC

V tomto případě jsou kontejnery propojeny bridgem lxcbr0, ale do internetu přistupují jen nepřímo přes NAT. IP adresy kontejnerům přiděluje minimalistický DHCP server dnsmasq.

Instalace LXC

Na Ubuntu je instalace LXC jednoduchá. V první řadě doporučujeme udělat update systému ve VM pro případ, že od vytvoření image došlo k vydání nějakých bezpečnostních updatů. Budeme pracovat jako root, takže pro zjednodušení, abychom nemuseli před všechny příkazy psát sudo, si ulehčíme situaci přepnutím do root shellu pomocí sudo su - .

Update provedeme pomocí dvojice příkazů apt update a apt dist-upgrade. V mém případě byl systém již aktualizován, takže výstup vypadá takto:

root@osboxes:/home/osboxes# apt update
Hit:1 http://de.archive.ubuntu.com/ubuntu focal InRelease
Hit:2 http://de.archive.ubuntu.com/ubuntu focal-updates InRelease
Hit:3 http://de.archive.ubuntu.com/ubuntu focal-backports InRelease
Hit:4 http://de.archive.ubuntu.com/ubuntu focal-security InRelease
Reading package lists... Done
Building dependency tree       
Reading state information... Done
All packages are up to date.

root@osboxes:/home/osboxes# apt dist-upgrade
Reading package lists... Done
Building dependency tree       
Reading state information... Done
Calculating upgrade... Done
0 upgraded, 0 newly installed, 0 to remove and 0 not upgraded.

Instalaci LXC pak provedeme pomocí příkazu apt install lxc . Příklad výstupu:

root@osboxes:/home/osboxes# apt install lxc
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following additional packages will be installed:
  bridge-utils dns-root-data dnsmasq-base libidn11 liblxc-common liblxc1 libpam-cgfs lxc-utils
  lxcfs uidmap
Suggested packages:
  ifupdown btrfs-tools lxc-templates lxctl
The following NEW packages will be installed:
  bridge-utils dns-root-data dnsmasq-base libidn11 liblxc-common liblxc1 libpam-cgfs lxc lxc-utils
  lxcfs uidmap
0 upgraded, 11 newly installed, 0 to remove and 0 not upgraded.
Need to get 1,641 kB of archives.
After this operation, 5,647 kB of additional disk space will be used.
Do you want to continue? [Y/n] 
Get:1 http://de.archive.ubuntu.com/ubuntu focal/universe amd64 lxcfs amd64 4.0.3-0ubuntu1 [65.3 kB]
Get:2 http://de.archive.ubuntu.com/ubuntu focal/main amd64 bridge-utils amd64 1.6-2ubuntu1 [30.5 kB]
Get:3 http://de.archive.ubuntu.com/ubuntu focal/main amd64 dns-root-data all 2019052802 [5,300 B]
Get:4 http://de.archive.ubuntu.com/ubuntu focal/main amd64 libidn11 amd64 1.33-2.2ubuntu2 [46.2 kB]
Get:5 http://de.archive.ubuntu.com/ubuntu focal/main amd64 dnsmasq-base amd64 2.80-1.1ubuntu1 [314 kB]
Get:6 http://de.archive.ubuntu.com/ubuntu focal/universe amd64 liblxc1 amd64 1:4.0.2-0ubuntu1 [292 kB]
Get:7 http://de.archive.ubuntu.com/ubuntu focal/universe amd64 liblxc-common amd64 1:4.0.2-0ubuntu1 [461 kB]
Get:8 http://de.archive.ubuntu.com/ubuntu focal/universe amd64 libpam-cgfs amd64 1:4.0.2-0ubuntu1 [35.5 kB]
Get:9 http://de.archive.ubuntu.com/ubuntu focal/universe amd64 lxc-utils amd64 1:4.0.2-0ubuntu1 [362 kB]
Get:10 http://de.archive.ubuntu.com/ubuntu focal/universe amd64 lxc all 1:4.0.2-0ubuntu1 [2,968 B]
Get:11 http://de.archive.ubuntu.com/ubuntu focal-updates/universe amd64 uidmap amd64 1:4.8.1-1ubuntu5.20.04 [26.3 kB]
Fetched 1,641 kB in 1s (2,522 kB/s)
Selecting previously unselected package lxcfs.
(Reading database ... 107569 files and directories currently installed.)
Preparing to unpack .../00-lxcfs_4.0.3-0ubuntu1_amd64.deb ...
Unpacking lxcfs (4.0.3-0ubuntu1) ...
Selecting previously unselected package bridge-utils.
Preparing to unpack .../01-bridge-utils_1.6-2ubuntu1_amd64.deb ...
Unpacking bridge-utils (1.6-2ubuntu1) ...
Selecting previously unselected package dns-root-data.
Preparing to unpack .../02-dns-root-data_2019052802_all.deb ...
Unpacking dns-root-data (2019052802) ...
Selecting previously unselected package libidn11:amd64.
Preparing to unpack .../03-libidn11_1.33-2.2ubuntu2_amd64.deb ...
Unpacking libidn11:amd64 (1.33-2.2ubuntu2) ...
Selecting previously unselected package dnsmasq-base.
Preparing to unpack .../04-dnsmasq-base_2.80-1.1ubuntu1_amd64.deb ...
Unpacking dnsmasq-base (2.80-1.1ubuntu1) ...
Selecting previously unselected package liblxc1.
Preparing to unpack .../05-liblxc1_1%3a4.0.2-0ubuntu1_amd64.deb ...
Unpacking liblxc1 (1:4.0.2-0ubuntu1) ...
Selecting previously unselected package liblxc-common.
Preparing to unpack .../06-liblxc-common_1%3a4.0.2-0ubuntu1_amd64.deb ...
Unpacking liblxc-common (1:4.0.2-0ubuntu1) ...
Selecting previously unselected package libpam-cgfs.
Preparing to unpack .../07-libpam-cgfs_1%3a4.0.2-0ubuntu1_amd64.deb ...
Unpacking libpam-cgfs (1:4.0.2-0ubuntu1) ...
Selecting previously unselected package lxc-utils.
Preparing to unpack .../08-lxc-utils_1%3a4.0.2-0ubuntu1_amd64.deb ...
Unpacking lxc-utils (1:4.0.2-0ubuntu1) ...
Selecting previously unselected package lxc.
Preparing to unpack .../09-lxc_1%3a4.0.2-0ubuntu1_all.deb ...
Unpacking lxc (1:4.0.2-0ubuntu1) ...
Selecting previously unselected package uidmap.
Preparing to unpack .../10-uidmap_1%3a4.8.1-1ubuntu5.20.04_amd64.deb ...
Unpacking uidmap (1:4.8.1-1ubuntu5.20.04) ...
Setting up libpam-cgfs (1:4.0.2-0ubuntu1) ...
Setting up lxcfs (4.0.3-0ubuntu1) ...
Created symlink /etc/systemd/system/multi-user.target.wants/lxcfs.service → /lib/systemd/system/lxcfs
.service.
Setting up uidmap (1:4.8.1-1ubuntu5.20.04) ...
Setting up dns-root-data (2019052802) ...
Setting up libidn11:amd64 (1.33-2.2ubuntu2) ...
Setting up bridge-utils (1.6-2ubuntu1) ...
Setting up dnsmasq-base (2.80-1.1ubuntu1) ...
Setting up liblxc1 (1:4.0.2-0ubuntu1) ...
Setting up lxc-utils (1:4.0.2-0ubuntu1) ...
Created symlink /etc/systemd/system/multi-user.target.wants/lxc-net.service → /lib/systemd/system/lxc
-net.service.
Created symlink /etc/systemd/system/multi-user.target.wants/lxc.service → /lib/systemd/system/lxc.ser
vice.
Setting up lxc dnsmasq configuration.
Setting up lxc (1:4.0.2-0ubuntu1) ...
Setting up liblxc-common (1:4.0.2-0ubuntu1) ...
Processing triggers for systemd (245.4-4ubuntu3.3) ...
Processing triggers for man-db (2.9.1-1) ...
Processing triggers for dbus (1.12.16-2ubuntu2.1) ...
Processing triggers for libc-bin (2.31-0ubuntu9.1) ...

Vytvoření kontejneru

Dejme tomu, že budeme chtít pro jednoduchost a relativní úspornost používat kontejnery s userpacem distribuce Debian 10 (buster). Opět půjdeme cestou použití předpřipraveného image, který lze automaticky stáhnout a nainstalovat do nově vytvořeného kontejneru pomocí template download . Prakticky stačí jediný příkaz lxc-create -t download -n c1 -- -d debian -r buster -a amd64, který kontejner založí a spustí template download, který stáhne distribuci debian, verzi buster pro architekturu amd64. Příklad výstupu je:

root@osboxes:/home/osboxes# lxc-create -t download -n c1 -- -d debian -r buster -a amd64
Setting up the GPG keyring
Downloading the image index
Downloading the rootfs
Downloading the metadata
The image cache is now ready
Unpacking the rootfs

---
You just created a Debian buster amd64 (20201229_05:24) container.

To enable SSH, run: apt install openssh-server
No default root or user password are set by LXC.

Existenci kontejneru ověříme příkazem lxc-ls. Následně jej nastartujeme příkazem lxc-start c1 . Dále ověříme, že kontejner běží pomocí lxc-info c1 a vstoupíme do terminálu kontejneru lxc-attaach c1 a porozhlédneme se uvnitř kontejneru:

root@osboxes:/home/osboxes# lxc-ls
c1   
root@osboxes:/home/osboxes# lxc-info c1
Name:           c1
State:          STOPPED
root@osboxes:/home/osboxes# lxc-start c1
root@osboxes:/home/osboxes# lxc-info c1
Name:           c1
State:          RUNNING
PID:            65910
IP:             10.0.3.9
CPU use:        0.31 seconds
BlkIO use:      120.00 KiB
Memory use:     16.24 MiB
KMem use:       3.99 MiB
Link:           vethwfg1Dt
 TX bytes:      1.51 KiB
 RX bytes:      2.26 KiB
 Total bytes:   3.76 KiB
root@osboxes:/home/osboxes# lxc-attach c1
root@c1:/# hostname
c1
root@c1:/# ps ax
    PID TTY      STAT   TIME COMMAND
      1 ?        Ss     0:00 /sbin/init
     47 ?        Ss     0:00 /lib/systemd/systemd-journald
     56 ?        Ss     0:00 /usr/bin/dbus-daemon --system --address=systemd: --nofork --nopidfile --
     58 ?        Ss     0:00 /lib/systemd/systemd-logind
     72 ?        Ss     0:00 /sbin/dhclient -4 -v -i -pf /run/dhclient.eth0.pid -lf /var/lib/dhcp/dhc
     93 pts/3    Ss+    0:00 /sbin/agetty -o -p -- \u --noclear --keep-baud pts/3 115200,38400,9600 v
     94 pts/1    Ss+    0:00 /sbin/agetty -o -p -- \u --noclear --keep-baud pts/1 115200,38400,9600 v
     95 pts/2    Ss+    0:00 /sbin/agetty -o -p -- \u --noclear --keep-baud pts/2 115200,38400,9600 v
     96 pts/1    Ss+    0:00 /sbin/agetty -o -p -- \u --noclear --keep-baud console 115200,38400,9600
     97 pts/0    Ss+    0:00 /sbin/agetty -o -p -- \u --noclear --keep-baud pts/0 115200,38400,9600 v
     99 pts/2    Ss     0:00 /bin/bash
    110 pts/2    R+     0:00 ps ax

Z terminálu kontejneru lze vystoupit - vrátit se zpět do VM stiskem Ctrl-D nebo příkazem exit.

Síť v kontejneru

Pokud jde o síťovou konektivitu, tak ta v našem případě funguje následovně:

root@c1:/# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0@if4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 00:16:3e:73:04:49 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 10.0.3.9/24 brd 10.0.3.255 scope global dynamic eth0
       valid_lft 3583sec preferred_lft 3583sec
    inet6 fe80::216:3eff:fe73:449/64 scope link 
       valid_lft forever preferred_lft forever

root@c1:/# ping 8.8.8.8
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=116 time=14.0 ms
64 bytes from 8.8.8.8: icmp_seq=2 ttl=116 time=10.5 ms
^C
--- 8.8.8.8 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 3ms
rtt min/avg/max/mdev = 10.479/12.254/14.030/1.778 ms

root@c1:/# ip route
default via 10.0.3.1 dev eth0 
10.0.3.0/24 dev eth0 proto kernel scope link src 10.0.3.9

Vidíme, že kontejner používá úplně jiný adresní rozsah, než máme na síťovém rozhraní VM. Vystoupíme tedy nyní z kontejneru do VM a prozkoumáme situaci tam. Ještě předtím si je dobré všimnout, že ve výpisu lxc-info c1 byl řádek

root@osboxes:/home/osboxes# lxc-info c1
...
Link:           vethwfg1Dt

Jméno interfacu vethwfg1Dt je náhodně zvolené jméno virtuálního ethernetového páru (https://man7.org/linux/man-pages/man4/veth.4.html), který je spojkou mezi systémem hostitele (VM), kde figuruje pod jménem vethwfg1Dt. Druhou stranou veth rozhraní je uvnitř kontejneru rozhraní eth0@if4 nebo zkráceně eth0.

Síť ve VM (hostiteli kontejneru)

Ve VM vypadá nastavení sítě v našem případě takto:

root@osboxes:/home/osboxes# ip addr
1: lo: <loopback,up,lower_up> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: enp0s3: <broadcast,multicast,up,lower_up> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 08:00:27:19:77:53 brd ff:ff:ff:ff:ff:ff
    inet 192.168.0.100/24 brd 192.168.0.255 scope global dynamic enp0s3
       valid_lft 2512sec preferred_lft 2512sec
    inet6 fe80::a00:27ff:fe19:7753/64 scope link 
       valid_lft forever preferred_lft forever
3: lxcbr0: <broadcast,multicast,up,lower_up> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 00:16:3e:00:00:00 brd ff:ff:ff:ff:ff:ff
    inet 10.0.3.1/24 scope global lxcbr0
       valid_lft forever preferred_lft forever
    inet6 fe80::216:3eff:fe00:0/64 scope link 
       valid_lft forever preferred_lft forever
4: vethwfg1Dt@if2: <broadcast,multicast,up,lower_up> mtu 1500 qdisc noqueue master lxcbr0 state UP group default qlen 1000
    link/ether fe:08:30:5a:d7:82 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::fc08:30ff:fe5a:d782/64 scope link 
       valid_lft forever preferred_lft forever
root@osboxes:/home/osboxes# bridge link
4: vethwfg1Dt@enp0s3: <broadcast,multicast,up,lower_up> mtu 1500 master lxcbr0 state forwarding priority 32 cost 2 

Vidíme tedy, že rozhraní vethwfg1Dt je připojeno do bridge (softwarového switche) lxcbr0, tento interface má IP adresu 10.0.3.1 a masku /24. Adresa kontejneru, kterou jsme viděli ve výpisu příkazu ip address o kousek výše byla 10.0.3.9 a měla také masku /24. Obě tyto adresy jsou tedy v jednom subnetu a přes veth pár jsou propojeny virtuálním L2 propojem.

Jaktože ale funguje konektivita z kontejneru do vnějšího Internetu (o kousek výše jsme z kontejneru úspěšně vyzkoušeli ping 8.8.8.8)? Je to proto, že v kontejneru je nastavena default route na next-hop 10.0.3.1 (viz výpis příkazu ip route výše - v sekci Síť v kontejneru). A to by ještě nestačilo proto, že adresy ze subnetu 10.0.3.0/24 nejsou přímo použítelné v Internetu bez NATu. Proto na VM (hostiteli) LXC při startu automaticky vytvořilo NAT pravidlo:

root@osboxes:/home/osboxes# iptables -t nat -L -vxn
...
Chain POSTROUTING (policy ACCEPT 1388 packets, 111604 bytes)
    pkts      bytes target     prot opt in     out     source               destination         
       2      124 MASQUERADE  all  --  *      *       10.0.3.0/24         !10.0.3.0/24 

Schématicky vypadá konektivita kontejneru následovně:

LXC network

Základní nástroje v Linuxu

iproute2

Pro zobrazení seznamu a stavu síťových rozhraní jak v userspacu hostitele (VM), tak v kontejnerech slouží nástroje ip link, ip address a ip route. Nástroj ip je součást balíčku iproute2 a obsahuje množství dalších sub-programů, ke kterým se časem dostaneme.

V našem případě jsme už viděli v minulé kapitole výstupy příkazů (sub-programů) ip jak z hostitelského userspace, tak z kontejneru.

O iproute2 rovnou řekněme, že to je základní nástroj pro zobrazení a změnu stavu síťového stacku. Doporučujeme proto aspoň na chvíli nahlédnout do manuálové stránky man ip resp. https://man7.org/linux/man-pages/man8/ip.8.html.

Pokud ještě znáte Unixovou klasiku - programy ifconfig, route, arp nebo netstat, tak na ně na Linuxu zkuste zapomenout. Neměly by se používat, protože jsou považovány za zastaralé, mají různé špatné vlastnosti - např. ifconfig nezobrazuje správně další (sekundární) IPv4 adresy na interfacech.

Jakási mapa přechodu na iproute2 může vypadat např. takto:

UNIX / zastaralý nástroj v Linuxu Název
ifconfig ip link, ip -s link, ip address
route ip route
arp ip neighbor
netstat ss

ping

Nástroj ping posíla ICMP echo packety na zvolenou adresu a očekává ICMP echo reply. Běh programu ping pak ukončíme po pár pokusech stiskem Ctrl-C. Výhodou pingu je, že nepotřebuje žádný server, ale je součástí implementace ICMP v jádru operačního systému cíle a je proto implementován na prakticky každém uzlu sítě, který podporuje protokol IP (IPv4 i IPv6 s odpovídající verzí ICMP). Na druhou stranu ICMP je na některých místech z bezpečnostních důvodů filtrován a nebo omezován na nějaký definovaný a zpravidla dost malý počet ICMP datagramů za časový úsek. Tyto omezení se projevují buď jako falešná nedostupnost (pingem) a nebo falešný packetloss. V obou případech je přínos zabezpečení diskutabilní, zatímco negativní dopady při hledání potíží v síťové konektivitě jsou neoddiskutovatelné.

V našem případě můžeme zkusit dostupnost kontejneru c1 z VM, tedy ping 10.0.3.9:

root@osboxes:/home/osboxes# ping 10.0.3.9
PING 10.0.3.9 (10.0.3.9) 56(84) bytes of data.
64 bytes from 10.0.3.9: icmp_seq=1 ttl=64 time=0.466 ms
64 bytes from 10.0.3.9: icmp_seq=2 ttl=64 time=0.132 ms
64 bytes from 10.0.3.9: icmp_seq=3 ttl=64 time=0.132 ms
64 bytes from 10.0.3.9: icmp_seq=4 ttl=64 time=0.153 ms
^C
--- 10.0.3.9 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3039ms
rtt min/avg/max/mdev = 0.132/0.220/0.466/0.141 ms

tcpdump

Nejdůležitější nástroj je ale tcpdump. Tím se můžeme podívat na jednotlivé IP datagramy s ICMP echo requesty, které nám program ping generuje. V první řadě spustíme ping na pozadí. Na to se hodí program screen (pokud není nainstalován, stačí apt install screen, doporučujeme man screen) man screen. Screen upozadíme stiskem trojhmatu Ctrl-A D (tedy Ctrl-A stiskněte najednou, pak klávesy uvolněte a stiskněte D).

root@osboxes:/home/osboxes# screen
root@osboxes:/home/osboxes# ping 10.0.3.9
PING 10.0.3.9 (10.0.3.9) 56(84) bytes of data.
64 bytes from 10.0.3.9: icmp_seq=1 ttl=64 time=0.063 ms
64 bytes from 10.0.3.9: icmp_seq=2 ttl=64 time=0.083 ms
64 bytes from 10.0.3.9: icmp_seq=3 ttl=64 time=0.079 ms

Ctrl-A D

[detached from 67423.pts-0.osboxes]
root@osboxes:/home/osboxes#

Nyní tedy ping běží na pozadí a do běžícího sezení screen se lze vrátit příkazem screen -r.

Můžeme tedy spustit tcpdump a podívat se na provoz mezi kontejnerem a hlavním userspacem. Jeho běh ukončíme opět po pár zachycených vzorcích stiskem Ctrl-C:

root@osboxes:/home/osboxes# tcpdump -n -i lxcbr0
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on lxcbr0, link-type EN10MB (Ethernet), capture size 262144 bytes
17:05:44.788820 IP 10.0.3.1 > 10.0.3.9: ICMP echo request, id 3, seq 19, length 64
17:05:44.788855 IP 10.0.3.9 > 10.0.3.1: ICMP echo reply, id 3, seq 19, length 64
17:05:45.813091 IP 10.0.3.1 > 10.0.3.9: ICMP echo request, id 3, seq 20, length 64
17:05:45.813183 IP 10.0.3.9 > 10.0.3.1: ICMP echo reply, id 3, seq 20, length 64
17:05:46.836810 IP 10.0.3.1 > 10.0.3.9: ICMP echo request, id 3, seq 21, length 64
17:05:46.836838 IP 10.0.3.9 > 10.0.3.1: ICMP echo reply, id 3, seq 21, length 64
17:05:47.860831 IP 10.0.3.1 > 10.0.3.9: ICMP echo request, id 3, seq 22, length 64
17:05:47.860900 IP 10.0.3.9 > 10.0.3.1: ICMP echo reply, id 3, seq 22, length 64
17:05:48.884832 IP 10.0.3.1 > 10.0.3.9: ICMP echo request, id 3, seq 23, length 64
17:05:48.884866 IP 10.0.3.9 > 10.0.3.1: ICMP echo reply, id 3, seq 23, length 64

Ctrl-C

10 packets captured
10 packets received by filter
0 packets dropped by kernel

A nyní můžeme vstoupit do screen -r, stiskem Ctrl-C ukončit běžící ping a celé sezení pak uzavřít stiskem Ctrl-D. Tím screen skončí a vrátíme se do terminálu hlavního (hostitelského) userspacu.

root@osboxes:/home/osboxes# screen -r
64 bytes from 10.0.3.9: icmp_seq=1 ttl=64 time=0.063 ms
64 bytes from 10.0.3.9: icmp_seq=2 ttl=64 time=0.083 ms
64 bytes from 10.0.3.9: icmp_seq=3 ttl=64 time=0.079 ms
...

Ctrl-C

root@osboxes:/home/osboxes#

Ctrl-D
[screen is terminating]
root@osboxes:/home/osboxes#

Mimochodem: Uvnitř v čistě nainstalovaném kontejneru program tcpdump není. Lze jej ale snadno doinstalovat:

root@osboxes:/home/osboxes# lxc-attach c1

root@c1:/# apt install tcpdump

Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following additional packages will be installed:
  libpcap0.8
Suggested packages:
  apparmor
The following NEW packages will be installed:
  libpcap0.8 tcpdump
0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded.
Need to get 539 kB of archives.
After this operation, 1,470 kB of additional disk space will be used.
Do you want to continue? [Y/n] 
Get:1 http://deb.debian.org/debian buster/main amd64 libpcap0.8 amd64 1.8.1-6 [139 kB]
Get:2 http://deb.debian.org/debian buster/main amd64 tcpdump amd64 4.9.3-1~deb10u2 [400 kB]
Fetched 539 kB in 0s (1,696 kB/s)
debconf: delaying package configuration, since apt-utils is not installed
Selecting previously unselected package libpcap0.8:amd64.
(Reading database ... 11046 files and directories currently installed.)
Preparing to unpack .../libpcap0.8_1.8.1-6_amd64.deb ...
Unpacking libpcap0.8:amd64 (1.8.1-6) ...
Selecting previously unselected package tcpdump.
Preparing to unpack .../tcpdump_4.9.3-1~deb10u2_amd64.deb ...
Unpacking tcpdump (4.9.3-1~deb10u2) ...
Setting up libpcap0.8:amd64 (1.8.1-6) ...
Setting up tcpdump (4.9.3-1~deb10u2) ...
Processing triggers for libc-bin (2.28-10) ...

root@c1:/#

K jednotlivým nástrojům se budeme ještě vracet podrobněji. Nyni jsme ale připraveni na teoretickou následující část, v níž si ale můžeme na experimentálním labu snadno tuto teorii ověřit.