Nastavení síťového stacku v Linuxu

VLAN, dummy a bridge

Odbočka: Linuxový bridge a VLAN

Celé to má ale jeden háček: zmiňovali jsme, že přes Linuxový bridge procházejí rámce s 802.1Q tagem, jako by to byl "hloupý" switch, tak je to celkem pravda, ale s jednou výjimkou: linuxový bridge není tak docela hloupý switch a rozumí multicastu, rozumí přihlašování do multicast skupin protokoly IGMP a MLD. V naší situaci nám to moc nevadilo, protože jsme nastavili pouze IPv4 adresy na oba kontejnery a ping je unicastová záležitost. MAC adresy si pro naše IP adresy kontejnery vyžádaly protokolem ARP a to je opět L2 broadcast. Mimochodem, ARP si také můžeme odchytit pomoci programutcpdump. Nejprve smažeme ARP záznam na c2 pro adresu kontejneru c1 a pak spustíme ping:

root@c2:/# ip neighbor
172.16.1.1 dev eth0.10 lladdr 00:16:3e:73:04:49 REACHABLE
10.0.3.1 dev eth0 lladdr 00:16:3e:00:00:00 STALE
10.0.3.9 dev eth0 lladdr 00:16:3e:73:04:49 STALE

root@c2:/# ip neighbor del 172.16.1.1 dev eth0.10

root@c2:/# ping 172.16.1.1
PING 172.16.1.1 (172.16.1.1) 56(84) bytes of data.
64 bytes from 172.16.1.1: icmp_seq=1 ttl=64 time=0.197 ms
64 bytes from 172.16.1.1: icmp_seq=2 ttl=64 time=0.153 ms
64 bytes from 172.16.1.1: icmp_seq=3 ttl=64 time=0.147 ms
64 bytes from 172.16.1.1: icmp_seq=4 ttl=64 time=0.179 ms
64 bytes from 172.16.1.1: icmp_seq=5 ttl=64 time=0.137 ms
64 bytes from 172.16.1.1: icmp_seq=6 ttl=64 time=0.147 ms
64 bytes from 172.16.1.1: icmp_seq=7 ttl=64 time=0.149 ms
^C
--- 172.16.1.1 ping statistics ---
7 packets transmitted, 7 received, 0% packet loss, time 85ms
rtt min/avg/max/mdev = 0.137/0.158/0.197/0.023 ms

Program tcpdump nám už musí běžet v druhé SSH session:

root@osboxes:/home/osboxes# tcpdump -n -e -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
01:09:21.924102 00:16:3e:b2:ca:c6 > ff:ff:ff:ff:ff:ff, ethertype 802.1Q (0x8100), length 46: vlan 10, p 0, ethertype ARP, Request who-has 172.16.1.1 tell 172.16.1.2, length 28
01:09:21.924164 00:16:3e:73:04:49 > 00:16:3e:b2:ca:c6, ethertype 802.1Q (0x8100), length 46: vlan 10, p 0, ethertype ARP, Reply 172.16.1.1 is-at 00:16:3e:73:04:49, length 28
01:09:21.924183 00:16:3e:b2:ca:c6 > 00:16:3e:73:04:49, ethertype 802.1Q (0x8100), length 102: vlan 10, p 0, ethertype IPv4, 172.16.1.2 > 172.16.1.1: ICMP echo request, id 124, seq 1, length 64
01:09:21.924219 00:16:3e:73:04:49 > 00:16:3e:b2:ca:c6, ethertype 802.1Q (0x8100), length 102: vlan 10, p 0, ethertype IPv4, 172.16.1.1 > 172.16.1.2: ICMP echo reply, id 124, seq 1, length 64
01:09:22.926072 00:16:3e:b2:ca:c6 > 00:16:3e:73:04:49, ethertype 802.1Q (0x8100), length 102: vlan 10, p 0, ethertype IPv4, 172.16.1.2 > 172.16.1.1: ICMP echo request, id 124, seq 2, length 64
01:09:22.926145 00:16:3e:73:04:49 > 00:16:3e:b2:ca:c6, ethertype 802.1Q (0x8100), length 102: vlan 10, p 0, ethertype IPv4, 172.16.1.1 > 172.16.1.2: ICMP echo reply, id 124, seq 2, length 64

Ctrl-C

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

Tedy vidime, že první, co se stane, než c2 pošle první ICMP echo request, je sekvence ARP dotaz - odpověď. Všechno s VLAN tagem 10. Přesně, jak očekáváme.

Nicméně zpátky k problému, který jsme naznačili - přes Linuxový bridge nám nebude fungovat multicast. Takže nebude fungovat NDP, který potřebuje IPv6 místo ARPu, aby našel MAC adresy pro IPv6 adresy na broadcast doméně. Navíc to nebude fungovat trochu podivným způsobem - závisí to na tom, zda je v síti aktivní MLD querier. Nebudeme teď rozebírat detaily, ale je snadné to zkustit:

  1. Nastavte v obou kontejnerech na rozhraní eth0.10 IPv6 unicast adresy - například na c1 adresu 2001:db8::1/64 a 2001:db8::2/64 na kontejner c2.
  2. Zapněte MLD querierer na VM: echo 1 > /sys/devices/virtual/net/lxcbr0/bridge/multicast_querier.
  3. Vyčkejte přibližně 2 minuty, než querierer nainicializuje MLD.
  4. Vyčkejte až zmizí z ND cache na kontejnerech záznamy pro IPv6 adresy sousedů a zkuste ping z c1 na 2001:db8::2/64.
  5. Výsledkem by mělo být, že ping nebude fungovat, protože se kontejneru c1 nepovede zjistit MAC adresa k IPv6 adrese 2001:db8::2/64.

Řešení jsou dvě možné:

  1. udělat z Linuxového bridge opravdu hloupý switch pomocí echo 0 >/sys/devices/virtual/net/lxcbr0/bridge/multicast_snooping
  2. nadefinovat VLANy pro bridge a zapnout VLAN filtering: https://developers.redhat.com/blog/2017/09/14/vlan-filter-support-on-bridge/