Hlavní navigace

OpenVZ: síťujeme na virtuálním serveru

2. 10. 2012
Doba čtení: 8 minut

Sdílet

V posledním, pátém dílu seriálu o OpenVZ se podíváme na síťování. Ukážeme si, jak přidělit containeru IPv4 nebo IPv6 adresu, jak provozovat container na privátní adrese s port forwardingem z hostitele. Ukážeme si také, jak containeru přidělit virtuální ethernet adaptér a umožnit mu přistupovat ke druhé síťové vrstvě.

V posledním dílu seriálu o OpenVZ se podíváme na síťování. Defaultním síťovým rozhraním OpenVZ je venet (Virtual NETwork). Pracuje na třetí vrstvě síťového modelu a funguje jako point-to-point linka mezi VE0 a containerem. Potřebujete-li, aby rozhraní mělo MAC adresu, bylo použitelné pro bridge a fungoval na něm broadcast, je nutné použít rozhraní veth (Virtual ETHernet), pracující na druhé vrstvě.

Rozhraní venet

Virtuální server, jehož vytvoření jsem demonstroval v prvním dílu seriálu, používá síťové rozhraní venet. Uvnitř containeru je rozhraní vidět takto:

root@deb6:/# ifconfig
...

venet0    Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
          inet addr:127.0.0.1  P-t-P:127.0.0.1  Bcast:0.0.0.0  Mask:255.255.255.255
          UP BROADCAST POINTOPOINT RUNNING NOARP  MTU:1500  Metric:1
          RX packets:2 errors:0 dropped:0 overruns:0 frame:0
          TX packets:11 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:168 (168.0 B)  TX bytes:840 (840.0 B)

venet0:0  Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
          inet addr:172.16.206.100  P-t-P:172.16.206.100  Bcast:0.0.0.0  Mask:255.255.255.255
          UP BROADCAST POINTOPOINT RUNNING NOARP  MTU:1500  Metric:1

Každá další IP adresa se ve výpisu objeví jako další alias k rozhraní venet0. Uživatel containeru si IP adresu nemůže sám změnit. IP adresy a některé další síťové parametry jsou nastavovány pomocí skriptů umístěných v adresáři /etc/vz/dists/scripts. Je jich tam celá řada pro všechny prováděné operace a různé operační systémy. To, co se provádí, najdete zapsáno v konfiguračním souboru umístěném o úroveň výš, tedy v /etc/vz/dists. Název konfiguračního souboru je dostatečně návodný, např. debian-6.0.conf.

Na hostiteli virtuálních serverů je vidět pouze jediné rozhraní venet0; ve výpisu routovací tabulky je pak vidět, že všechny IP adresy jednotlivých virtuálních serverů jsou směrovány do tohoto jediného venet0 rozhraní. O roztřídění provozu do správného virtuálního serveru se stará kernelový modul vznetdev.

root@ve0:~# ifconfig
...

venet0    Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
          UP BROADCAST POINTOPOINT RUNNING NOARP  MTU:1500  Metric:1
          RX packets:345 errors:0 dropped:0 overruns:0 frame:0
          TX packets:3 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:22997 (22.4 KiB)  TX bytes:271 (271.0 B)

root@ve0:~# ip route
172.16.206.100 dev venet0  scope link
172.16.206.101 dev venet0  scope link
172.16.28.0/24 dev eth0  proto kernel  scope link  src 172.16.28.133
default via 172.16.28.2 dev eth0

Pokud má virtuální server IP adresu veřejně dostupnou na síti, je ve výstupu programu traceroute vidět jak IP adresa virtuálního serveru, tak předchozí IP adresa konkrétního hostitele virtuálních serverů. To se vám může hodit, když budete hledat, kde ten který virtuál běží.

IP adresu containeru můžete přidělit hned při vytváření parametrem –ipadd <addr>, anebo kdykoliv později pomocí volání vzctl:

vzctl set <CTID> --ipadd <IPv4addr|IPv6addr> --save

Potřebujete-li odebrat IP adresu z virtuálního serveru, použijte přepínač –ipdel <addr>. Při stěhování virtuálních serverů (anebo jen IP adres z virtuálního serveru na server) se vám může hodit program arpsend. Ten slouží k rozeslání ARP požadavku na okolní počítače v síti, aby si upravily ARP tabulku - neuděláte-li to, budete čekat poměrně dlouho, než začne přestěhovaná IP adresa fungovat.

IPv6

Abyste uvnitř containeru mohli použít IPv6, musíte nejprve protokol zapnout v konfiguračním souboru /etc/vz/vz.conf, hledejte proměnou IPV6 a nastavte na „yes“ (nebude-li tak již nastavena). Defaultně je podpora IPv6 vypnutá a změna vyžaduje restart.

Dokumentace OpenVZ k IPv6 říká, že "… venet devices are not fully IPv6 compliant… ". Moje praktická zkušenost je, že to funguje zcela spolehlivě. Používám statickou konfiguraci jak na hostitelích, tak na virtuálních serverech, a jediné, co je třeba po startu virtuálního serveru provést, je:

/sbin/ip -6 route replace default dev venet0

Příkaz mám nastavený v souboru /etc/rc.local.

Containery s veřejnou IPv4 adresou

Typickou instalací OpenVZ jsou containery používající veřejnou IP adresu. V případě, že je hostitel containerů nainstalován v té samé síti, jako mají být containery, je kromě výše uvedeného ještě nutný zapnutý IPv4 forwarding.

echo 1 > /proc/sys/net/ipv4/ip_forward

Firewall lze nastavovat buď na hostiteli, anebo v containeru tak, jako by to byl fyzický server. První možnost, tedy nastavovat ho přímo na hostiteli, je vhodná pouze pro speciální případy. V běžné praxi si budou chtít správci containerů nastavovat firewall sami. V takovém případě je třeba dbát, aby UBC parametr numiptent byl dostatečně vysoký, aby se všechna potřebná pravidla vešla OpenVZ do paměti.

Aby iptables firewall fungoval správně, potřebuje moduly v kernelu; zdaleka ne všechny dostupné jsou dostupné uvnitř containeru. Dostupnost modulů je řízena globální konfigurací OpenVZ umístěnou v konfiguračním souboru /etc/vz/vz.conf, moduly pro IPv4 firewall jsou exportovány prostřednictvím proměnné IPTABLES a moduly pro IPv6 firewall prostřednictvím proměnné IP6TABLES. Změna globálního konfiguračním souboru vyžaduje restart všech CT prostřednictvím příkazu /etc/init.d/vz restart.

Budete-li chtít upravit dostupné moduly jen pro nějaký konkrétní container, je to možné pomocí příkazu:

vzctl set <CTID> --iptables 'module1 module2 ...'

kde module1 module2 představuje kompletní seznam modulů, které mají být danému containeru k dispozici.

Ne všechny moduly, které iptables umí, jsou k dispozici. Zkusíte-li použít nějaký, který k dispozici není, vzctl vás na to upozorní:

root@ve0:~# vzctl set 1000 --iptables 'ipt_REJECT ipt_tos ipt_limit ipt_multiport iptable_filter iptable_mangle ipt_TCPMSS ipt_tcpmss ipt_ttl ipt_length ipt_LOG ipt_state ipt_conntrack ip_conntrack ip_conntrack_ftp ipt_MASQUERADE' --save
Warning: Unknown iptable module: ipt_MASQUERADE, skipped

Výše uvedený příklad představuje seznam modulů, které mám otestované, že fungují, tedy až na ipt_MASQUERADE. Kompletní seznam podporovaných modulů se mi nepodařilo najít. Na OpenVZ wiki je článek Setting up an iptables firewall, který by se vám mohl hodit, budete-li potřebovat firewallování na OpenVZ prozkoumat detailněji.

Containery s privátní IPv4 adresou (NAT)

Možná si teď ťukáte na čelo a myslíte si něco nepěkného o bláznech provozujících servery na nedostupných privátních adresách. Zadržte. Existují aplikace, které potřebují jeden či dva TCP/UDP porty a jinak nic jiného. Z mé praxe je to například kombinace LDAP, TACACS+ a RADIUS serveru. Rozdělení jednotlivých služeb na různé virtuální servery mi umožnilo zpřístupnit virtuální servery poskytující jednotlivé služby administrátorům, kteří ty služby využívají, aniž bych jim musel poskytovat přístup k ostatním službám.

Všichni uživatelé služeb využívají společnou IP adresu, řekněme 195.113.aaa.bbb, a obvyklý port dané služby. Firewall hostitele těchto služeb potom obsahuje konfiguraci, která zajistí předání paketů do patřičného virtuálního serveru. Jednotlivé virtuální servery mají pouze privátní adresu 192.168.1.b. SSH těchto virtuálních serverů je potom dostupné na portech 9722–24.

iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth0 -j MASQUERADE

# LDAP
iptables -A PREROUTING -t nat -i eth0 -p tcp -d 195.113.aaa.bbb --dport 389 -j DNAT --to 192.168.1.3:389
iptables -A PREROUTING -t nat -i eth0 -p tcp -d 195.113.aaa.bbb --dport 636 -j DNAT --to 192.168.1.3:636
iptables -A PREROUTING -t nat -i eth0 -p tcp -d 195.113.aaa.bbb --dport 9722 -j DNAT --to 192.168.1.3:22

# TACACS+
iptables -A PREROUTING -t nat -i eth0 -p tcp -d 195.113.aaa.bbb --dport 49 -j DNAT --to 192.168.1.4:49
iptables -A PREROUTING -t nat -i eth0 -p tcp -d 195.113.aaa.bbb --dport 9723 -j DNAT --to 192.168.1.4:22

# RADIUS
iptables -A PREROUTING -t nat -i eth0 -p udp -d 195.113.aaa.bbb --dport 1812 -j DNAT --to 192.168.1.5:1812
iptables -A PREROUTING -t nat -i eth0 -p udp -d 195.113.aaa.bbb --dport 1813 -j DNAT --to 192.168.1.5:1813
iptables -A PREROUTING -t nat -i eth0 -p udp -d 195.113.aaa.bbb --dport 1645 -j DNAT --to 192.168.1.5:1645
iptables -A PREROUTING -t nat -i eth0 -p udp -d 195.113.aaa.bbb --dport 1646 -j DNAT --to 192.168.1.5:1646
iptables -A PREROUTING -t nat -i eth0 -p tcp -d 195.113.aaa.bbb --dport 9724 -j DNAT --to 192.168.1.5:22

Umístění virtuálního serveru na privátní adresu také znamená, že veškerý provoz, který není přeložen, je firewallem hostitele zahozen, tudíž není nutné se dalším firewallem uvnitř virtuálního serveru zabývat.

Rozhraní veth

Potřebujete-li uvnitř virtuálního serveru provozovat služby vyžadující broadcast nebo provozovat síťovou kartu v promiskuitním režimu, musíte použít rozhraní veth. To pracuje na druhé síťové vrstvě a má tak blíže ke skutečnému síťovému rozhraní, byť se stále jedná o emulované zařízení. Konfigurace je o něco složitější než v případě rozhraní typu venet, předvedeme si ji na příkladu.

Cointaineru 1000 přidělím rozhraní eth0. Označení eth0 je z pohledu containeru, na hostiteli pak bude automaticky vytvořeno rozhraní veth1000.0. Pokud bych v containeru vytvořil eth1, pak by se rozhraní na hostiteli jmenovalo veth1000.1.

root@ve0:~# vzctl set 1000 --netif_add eth0 --save
Configure veth devices: veth1000.0
Saved parameters for CT 1000
root@ve0:~# ifconfig veth1000.0
veth1000.0 Link encap:Ethernet  HWaddr 00:18:51:69:43:26
          inet6 addr: fe80::218:51ff:fe69:4326/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:0 (0 B)  TX bytes:0 (0 B)

Vstoupím do containeru 1000, na rozhraní eth0 nastavím veřejnou IP adresu 195.113.aaa.bbb a defaultní routu. Toto nastavení je pochopitelně žádoucí zanést do patřičného konfiguračního souboru uvnitř virtuálního serveru.

root@ve0:~# vzctl enter 1000
root@deb6:/# ifconfig eth0 195.113.aaa.bbb
root@deb6:/# ip route add default dev eth0
root@deb6:/# exit

Poslední konfigurační krok se sestává ze zapnutí IP forwardingu (to už asi budete mít zapnuté kvůli rozhraním typu venet). Dále je třeba zapnout ARP proxy a nastavit routování provozu IP adresy 195.113.aaa.bbb do virtuálního rozhraní veth1000.0. Tím je konfigurace dokončena.

CS24_early

root@ve0:~# echo 1 > /proc/sys/net/ipv4/conf/veth1000.0/forwarding
root@ve0:~# echo 1 > /proc/sys/net/ipv4/conf/eth0/forwarding
root@ve0:~# echo 1 > /proc/sys/net/ipv4/conf/veth1000.0/proxy_arp
root@ve0:~# echo 1 > /proc/sys/net/ipv4/conf/eth0/proxy_arp
root@ve0:~# ip route add 195.113.aaa.bbb dev veth1000.0

Aby byla konfigurace permanentní, je třeba zapnutí forwardingu a ARP proxy uvést v souboru /etc/sysctl.conf. Nastavení routingu potom provádějte pomocí start skriptu, viz předchozí díl seriálu.

Tento díl seriálu o síťování v OpenVZ je současně posledním dílem celého seriálu. Děkuji za pozornost a doufám, že se mi povedlo alespoň někoho zaujmout. OpenVZ není mrtvé!

Byl pro vás článek přínosný?

Autor článku

Jan Tomášek v současnosti pracuje pro CESNET, z. s . p. o. jako vývojář v oblasti PKI a správy uživatelských identit. Ve volném čase se věnuje krajinné fotografii a geocachingu.