Sieci w Linuksie/brctl

Narzędzie brctl służy do tworzenia i zarządzania mostami sieciowymi w Linuksie. Most sieciowy w jądrze Linuks wygląda na zewnątrz jak zwykły przełącznik (switch), tzn. przekazuje ramki ethernet pomiędzy swoimi portami. Poniżej znajdują się polecenia obsługiwane przez brctl.

Aby móc skorzystać z mostów pod Linuksem należy mieć skompilowaną ich obsługę (Networking support --> Networking options --> 802.1d Ethernet Bridging w menuconfig, lub CONFIG_BRIDGE w pliku .config). Program brctl znajduje się w większości dystrybucji w pakiecie bridge-utils.

W systemie może znajdować się dowolna liczba niezależnych mostów - każdy most zachowuje się wtedy jak osobny switch. Każdy most może dodatkowo posiadać własny adres IP, wtedy interfejs mostu dla podsystemu IP zachowuje się jak zwykły interfejs sieciowy. Adres MAC mostu jest taki sam, jak najmniejszy adres MAC spośród jego portów (najmniejszy w sensie wartości liczbowej).

addbr most - tworzy interfejs mostu o nazwie most. Aby most zaczął działać musi zostać włączony (`ip link set dev most up`) oraz posiadać porty (patrz niżej).
delbr most - niszczy interfejs mostu. Aby most został zniszczony nie może posiadać zdefiniowanych portów, ani być włączony (`ip link set dev down`).
show - wyświetla skonfigurowane mosty.

Każdy most może posiadać dowolnie wiele portów. Jeden port może należeć tylko do jednego mostu. Portem mostu mogą być:

  • rzeczywisty interfejs sieci Ethernet (np. eth0)
  • rzeczywisty interfejs WiFi (np. wlan0)
  • wirtualny interfejs zagregowany (ang. bonding) (np. bond0)
  • wirtualny interfejs VLAN (np. vlan1456, eth0.12)
  • wirtualny interfejs programowy kompatybilny z ethernet (np. tap0 utworzone przez demona OpenVPN)

Porty mostu nie mogą posiadać własnego adresu IP, dlatego należy je usunąć przed przydziałem interfejsu do mostu.

addif most interfejs - dodaje interfejs do mostu.
delif most interfejs - usuwa interfejs z mostu.
show most - wyświetla konfigurację danego mostu (wraz z jego portami).

Adresy MAC

edytuj

Aby przyspieszyć pracę oraz zmniejszyć obciążenie sieci most pamięta adresy MAC dostępne przez poszczególne porty i przekazuje ramki do portu, o którym wie, że przez niego osiągalny jest dany adres MAC. Mechanizm ten można wyłączyć, wtedy most pracuje w trybie flood - każda ramka przychodząca na dany port jest kopiowana na każdy z pozostałych portów.

showmacs most - wyświetla znane mostowi adresy MAC (wraz z portami, na których się znajdują oraz czasem życia).
setageingtime most czas - ustawia dla danego mostu czas (w sekundach), jaki most będzie pamiętał dany adres MAC. Licznik czasu jest restartowany po zaobserwowaniu ramki z danym adresem MAC, a po upływie czasu dany adres MAC w bazie danych przekazywania jest oznaczany do odśmiecania.
setgcint most czas - ustawia dla danego mostu interwał odśmiecania. Co podaną liczbę sekund nastąpi odśmiecanie bazy danych przekazywania.

Protokół drzewa rozpinającego (ang. Spanning Tree Protocol) służy do ustalania przez mosty topologii sieci. W jądrze Linux zaimplementowana jest tylko obsługa najstarszego protokołu STP. Obecnie stosowane są nowsze RSTP (Rapid STP) oraz MSTP (Multiple STP), które jednak są kompatybilne wstecz z STP. Protokół RSTP pozwala na znacznie szybszą reakcję mostów na zmianę topologii sieci (włączenie/wyłączenie mostu, zerwanie łącza pomiędzy dwoma mostami). Protokół MSTP jest szczególnie użyteczny w przypadku używaniu VLANów, ponieważ umożliwia tworzenie osobnych drzew rozpinających dla poszczególnych VLANów. Ze względu na sposób zarządzania mostami w Linuksie potrafi on uczestniczyć w drzewach MSTP pomimo braku obsługi protokołu. Jest to związane z tym, że mosty zbudowane na VLANach są niezależne od siebie i każdy z nich osobno uczestniczy w budowaniu drzewa rozpinającego. Po rozpoznaniu topologii sieci stosowane jest następujące nazewnictwo:

  • ramka BPDU (ang. Bridge Protocol Data Unit) - specjalna ramka Ethernet służąca do wymiany komunikatów protokołów STP.
  • root bridge - most wybrany przez STP jako korzeń drzewa rozpinającego, najważniejszy most w sieci, to w nim łączą się wszystkie poddrzewa.
  • root port - port korzeniowy - port mostu, przez który następuje komunikacja w kierunku mostu-korzenia.
  • designated port - port desygnowany - każdy port, który nie jest korzeniowy.

Parametry związane z STP:

showstp most - wyświetla konfigurację STP dla wybranego mostu oraz jego portów.
stp most on|off - włącza/wyłącza obsługę STP dla wybranego mostu.
setbridgeprio most priorytet - ustawia priorytet mostu (0-66535). Priorytet mostu jest najważniejszym parametrem używanym podczas wyboru mostu-korzenia. Domyślną wartością priorytetu dla wszystkich mostów (również sprzętowych) jest 2^15 (32768). Podczas wyboru mostu-korzenia wybierany jest most o najniższym priorytecie, a w przypadku remisu wybierany jest most o najniższym adresie MAC, ...
setfd most czas - ustawia opóźnienie przekazywania (ang. forward delay) - czas jaki port po włączeniu uczy się (nasłuchuje ramek BPDU) topologii zanim rozpocznie przekazywanie pakietów. Domyślną wartością jest 15 sekund.
sethello most czas - ustawia interwał hello, definiujący jak często most powinien wysyłać przez swoje porty desygnowane ramki BPDU. Domyślną wartością są 2 sekundy.
setmaxage most czas - ustawia maksymalny czas przez jaki most może nie otrzymać ramki BPDU przez port korzeniowy. Po tym czasie nadrzędny most jest uznawany za niesprawny i następuje zmiana topologii sieci.
setpathcost most port koszt - ustawia koszt ścieżki przez dany port. Koszt jest wielkością bezwymiarową i służy do definiowana faworyzowanych portów (port o niższym koszcie jest chętniej wybierany). Domyślny koszt trasy zależy od prędkości łącza - szybsze łącze oznacza mniejszy koszt zgodnie z regułą 10mbit>100mbit>1gbit>10gbit.
setportprio most port priorytet - ustawia priorytet dla danego portu. Priorytet podobnie jak koszt służy do definiowania faworyzowanych portów (port o wyższym priorytecie jest chętniej wybierany). Domyślną wartością jest ??.

Przykłady

edytuj

Wyjście programu

edytuj
brctl show
# brctl show
bridge name	bridge id		STP enabled	interfaces
br0		8000.000d88cd49b0	no		eth1
							eth2
							eth3
							eth4
br1		8000.00145e822cc0	no		vlan1838
							vlan2827
brctl showmacs
# brctl showmacs br1
port no	mac addr		is local?	ageing timer
  2	00:12:1e:0c:6c:1f	no		   0.25
  1	00:14:5e:82:2c:c0	yes		   0.00
  1	00:16:e0:72:d1:40	no		  10.13
  1	00:19:5b:5d:f3:aa	no		   2.97
  1	00:1b:2a:34:e7:9d	no		   2.18
brctl showstp
# brctl showstp
br0
 bridge id		ffff.000d88cd49b0
 designated root	8000.0012cf6a62c0
 root port		   1			path cost		5004
 max age		  19.99			bridge max age		  19.99
 hello time		   1.99			bridge hello time	   1.99
 forward delay		  14.99			bridge forward delay	  14.99
 ageing time		 299.95
 hello timer		   0.00			tcn timer		   0.00
 topology change timer	   0.00			gc timer		  11.76
 flags			


eth1 (1)
 port id		8001			state		     forwarding
 designated root	8000.0012cf6a62c0	path cost		   4
 designated bridge	8000.0012cf967820	message age timer	  18.60
 designated port	8012			forward delay timer	   0.00
 designated cost	5000			hold timer		   0.00
 flags			

eth2 (2)
 port id		8002			state		     forwarding
 designated root	8000.0012cf6a62c0	path cost		   4
 designated bridge	ffff.000d88cd49b0	message age timer	   0.00
 designated port	8002			forward delay timer	   0.00
 designated cost	5004			hold timer		   0.76
 flags			

eth3 (3)
 port id		8003			state		     forwarding
 designated root	8000.0012cf6a62c0	path cost		  19
 designated bridge	ffff.000d88cd49b0	message age timer	   0.00
 designated port	8003			forward delay timer	   0.00
 designated cost	5004			hold timer		   0.76
 flags			

eth4 (4)
 port id		8004			state		     forwarding
 designated root	8000.0012cf6a62c0	path cost		  19
 designated bridge	ffff.000d88cd49b0	message age timer	   0.00
 designated port	8004			forward delay timer	   0.00
 designated cost	5004			hold timer		   0.76
 flags

Prosta konfiguracja

edytuj
Opis sieci

W naszej sieci o adresacji 192.168.160.0/24 posiadamy sprzętowy router o adresie 192.168.160.1 (który jest bramą domyślną), przed którym chcemy postawić most sieciowy (w celu na przykład użycia firewalla, lub transparentnego proxy). Komputer, na którym tworzymy most posiada 2 interfejsy sieciowe: eth0 od strony LAN i eth1 od strony routera. Interfejs mostu musi więc posiadać własny adres IP.

Polecenia konfiguracyjne
ip addr flush dev eth0		# 1
ip addr flush dev eth1		# 2
ip link set dev eth0 up	# 3
ip link set dev eth1 up	# 4

brctl addbr br0		# 5
brctl addif br0 eth0		# 6
brctl addif br0 eth1		# 7
brctl stp br0 off		# 8

ip addr add 192.168.160.5/24 dev br0	# 9
ip route add default 192.168.160.1	# 10
ip link set dev br0 up			# 11
Opis konfiguracji
  • Linijki (1-4) gwarantują, że porty mostu są poprawnie skonfigurowane (nie posiadają adresu i są włączone).
  • Linijki (5-8) tworzą most.
  • Linijki (9-11) włączają most.
Rozszerzenie przykładu

Dodatkowo możemy chcieć, aby to 192.168.160.5 był domyślną bramą w naszej sieci, a nie 192.168.160.1 (bo np. ma dodatkowo zestawiony tunel VPN z innym oddziałem naszej firmy). W tym celu musimy zrobić tylko 2 rzeczy: upewnić się, że mamy odpowiednią konfigurację firewalla (np. domyślną politykę ACCEPT w łańcuchu FORWARD w iptables) oraz włączyć przekazywanie pakietów w naszym systemie:

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

Lub dopisać następującą linijkę do pliku /etc/sysctl.conf

net.ipv4.ip_forward = 1

Gdy 192.168.128.5 będzie domyślną bramą działać będzie to w następujący sposób:

  1. Komputer łączący się z adresem IP w internecie np. 80.44.176.22 wyśle ramkę z pierwszym pakietem na adres MAC interfejsu br0 (bo IP przypisany do br0 jest domyślną bramą).
  2. Nasza maszyna linuksowa odeśle pakiet ICMP redirect z informacją, że w sieci istnieje lepsza brama - 192.168.160.1
  3. Komputer wyśle ponownie ten sam pakiet, tym razem na adres MAC routera. Ramka z tym pakietem przejdzie normalnie przez most.
  4. Kolejne pakiety tego połączenia będą wysyłane bezpośrednio do routera (za pośrednictwem mostu).
Równoważna konfiguracja dla Gentoo Linux

Gentoo Linux posiada wbudowane wsparcie dla tworzenia mostów za pomocą swoich skryptów startowych. W tym celu należy do pliku /etc/conf.d/net dopisać następującą konfigurację:

config_eth0=("null");		# 1
config_eth1=("null");		# 2

bridge_br0=("eth0 eth1");	# 3
brctl_br0=("stp off");		# 4
depend_br0() {			# 5
	need net.eth0 net.eth1
};
config_br0=("192.168.160.5/24");		# 6
routes_br0=("default via 192.168.160.1");	# 7

utworzyć odpowiednie skrypty startowe:

ln -s /etc/init.d/net.lo /etc/init.d/net.eth0
ln -s /etc/init.d/net.lo /etc/init.d/net.eth1
ln -s /etc/init.d/net.lo /etc/init.d/net.br0

oraz dodać do skryptów startowych net.br0

rc-update add net.br0 default

Od tej pory interfejs br0 będzie poprawnie inicjowany podczas startu systemu. Opis konfiguracji:

  • Linijki (1-2) definiują pustą konfigurację dla interfejsów eth0 i eth1 (jest to konieczne, ponieważ domyślną konfiguracją jest użycie DHCP)
  • Linijka (3) definiuje porty mostu
  • Linijka (4) zawiera parametry dodatkowe mostu, które należy ustawić za pomocą polecenia brctl
  • Linijka (5) tworzy zależność interfejsu br0 od interfejsów eth0 i eth1 (dzięki temu skrypty net.eth0 i net.eth1 są automatycznie uruchamiane przed uruchomieniem net.br0)
  • Linijki (6-7) zawierają konfigurację IP dla mostu

Konfiguracja mostu między VLANami

edytuj
Opis sieci

W naszej (rozbudowanej) sieci używamy VLANów w celu podłączenia serwerów za pomocą pojedynczego interfejsu zarówno do sieci LAN jak i sieci publicznej (sieć LAN jako nietagowane ramki Ethernet, a sieć publiczna jako tagowane). Router dostawcy internetu jest podłączony do nietagowanego portu w przełączniku sieciowym o numerze VLAN 1357, natomiast serwery używają tagowanego VLANu o numerze 3578. Naszym celem jest utworzenie mostu pomiędzy tymi VLANami w celu filtrowania przechodzącego ruchu. Nasza maszyna linuksowa jest wpięta interfejsem eth0 do przełącznika, gdzie ma dostęp zarówno do tagowanego VLAN 1357 jak i 3578.

Polecenia konfiguracyjne
vconfig set_name_type VLAN_PLUS_VID	# 1
vconfig add eth0 1357			# 2
vconfig add eth0 3578			# 3

ip link set dev eth0 up			# 4
ip link set dev vlan1357 up		# 5
ip link set dev vlan3578 up		# 6

brctl addbr br0				# 7
brctl addif br0 vlan1357		# 8
brctl addif br0 vlan3578		# 9
brctl stp br0 on			# 10

ip link set dev br0 up			# 11
Opis konfiguracji
  • Polecenia (1-3) tworzą odpowiednie interfejsy VLAN (vlan1357 i vlan3578). Opis programu vconfig znajduje się w rozdziale Sieci:Linux/vconfig. Alternatywnie można użyć polecenia ip (Sieci:Linux/iproute2/ip), w tedy utworzenie VLANów wyglądałoby tak:
ip link add link eth0 name vlan1375 type vlan id 1375		# 1.alt
ip link add link eth0 name vlan3578 type vlan id 3578		# 2.alt
  • Polecenia (4-6) włączają interfejsy (na wszelki wypadek)
  • Polecenia (7-9) tworzą nowy interfejs mostu
  • Polecenie (10) włącza obsługę STP (ze względu na skomplikowaną topologię sieci).
  • Polecenie (11) włącza interfejs mostu
Rozszerzenie przykładu

Nic nie stoi na przeszkodzie, aby intefejs br0 posiadał adres IP, dzięki czemu będzie dostępny pod publicznym adresem IP (oczywiście oznacza to, że będzie narażony na wszelkie ataki, na co należy go uodpornić odpowiednią konfiguracją firewalla). W tym celu wystarczy przypisać mu odpowiedni adres IP.

ip addr add 195.247.0.12/27 dev br0		# 12
Równoważna konfiguracja dla Gentoo Linux

Konfiguracja mostu na bazie VLANów w Gentoo jest podobna do tej z poprzedniego przykładu, z jedną różnicą - interfejsy VLAN dla danego interfejsu sieciowego są tworzone (i konfigurowane) automatycznie przez skrypt startowy tego interfejsu, dlatego wystarczy zdefiniować zależność mostu od interfejsu eth0. Obecnie skrypty startowe potrafią używać do tworzenia VLANów tylko narzędzia vconfig. Zawartość pliku /etc/conf.d/net

config_eth0=("null");		# 1

vlans_eth0=("1357 3578");	# 2
vconfig_eth0=( "set_name_type VLAN_PLUS_VID" );	# 3

config_vlan1357=("null");		# 4
config_vlan3578=("null");		# 5

bridge_br0=("vlan1357 vlan3578");	# 6
brctl_br0=("stp on");			# 7
depend_br0() {				# 8
	need net.eth0
};

Podobnie jak w poprzednim przykładzie należy utworzyć odpowiednie skrypty startowe:

ln -s /etc/init.d/net.lo /etc/init.d/net.eth0
ln -s /etc/init.d/net.lo /etc/init.d/net.br0

Oraz dodać net.br0 do uruchamianych usług

rc-update add net.br0 default

Opis konfiguracji:

  • Linijka (1) zawiera konfigurację interfejsu eth0, jeżeli ma być on jednocześnie interfejsem LAN, to należy ją zastąpić poprawną konfiguracją eth0, np.
config_eth0=("192.168.100.20/24");		# 1.alt.1
routes_eth0=("default via 192.168.100.1");	# 1.alt.2
  • Linijki (2-3) definiują VLANy dla interfejsu eth0. Linijka (2) specyfikuje ID VLANów, a linijka (3) sposób nazewnictwa
  • Linijki (4-5) definiują pustą konfigurację interfejsów VLAN (ponieważ brak konfiguracji jest równoważny z użyciem DHCP)
  • Linijka (6) definiuje porty mostu
  • Linijka (7) włącza STP
  • Linijka (8) ustanawia zależność br0 od eth0

Konfiguracja mostu między siecią lokalną, a tunelem OpenVPN

edytuj
Opis sieci

Nasza firma posiada dwa równoważne oddziały, które chcemy połączyć za pomocą tunelu VPN w jedną sieć LAN. W obu oddziałach znajdują się takie same maszyny linuksowe, które posłużą do stworzenia tunelu VPN w oparciu o technologię OpenVPN (szczegóły konfiguracji OpenVPN znajdują się w rozdziale Sieci:Linux/OpenVPN). Każdy z komputerów bram posiada interfejs eth1 ze skonfigurowanym dostępem do Internetu. Na każdym z tych komputerów skonfigurowano demona OpenVPN tak, aby możnabyło zestawić tunel. Na obu komputerach interfejs tunelu nazywa się tap12.

Polecenia konfiguracyjne
/etc/init.d/openvpn start		# 1
ip addr flush dev eth0			# 2
ip link set dev eth0 up			# 3

brctl addbr br0				# 4
brctl addif br0 eth0			# 5
brctl addif br0 tap12			# 6
brctl stp br0 on			# 7

ip link set dev br0 up			# 8
Opis konfiguracji
  • Linijka (1) jest odpowiedzialna za uruchomienie demona openvpn, który tworzy interfejs tap12
  • Linijki (2-3) są odpowiedzialne za przygotowanie interfejsu eth0.
  • Linijki (4-7) konfigurują interfejs br0.
  • Linijka (8) uruchamia most.

Po uruchomieniu powyższego skryptu na obu maszynach oba oddziały znajdą się w jednym segmencie sieci LAN. Oznacza to, że dla obu oddziałów prawdą jest:

  • posiadają taki sam adres sieci (np. 192.168.100.0/24)
  • wystarczy pojedynczy serwer DHCP dla obu sieci
  • wystarczy pojedyncza brama domyślna
  • komputery w obu oddziałach widzą swoje pakiety rozgłoszeniowe (np. SAMBA, lub mDNS)
Uwagi
  • Aby zestawić połączenie OpenVPN najpierw musi być uruchomiony interfejs sieciowy pozwalający na połączenie sieciowe z drugim końcem tunelu.
  • W konfiguracji OpenVPN należy wymusić użycie konkretnej nazwy interfejsu tap (tak jak w naszym przykładzie tap12) oraz ustawić, aby zerwanie połączenia nie powodowało usunięcia urządzenia (opcja persist-tun, która jest również przydatna w innych sytuacjach).
  • OpenVPN obsługuje wywoływanie zewnętrznych skryptów w momencie zestawienia/zerwania tunelu, więc w dystrybucjach, w których nie można tego zrobić sprytniej można skrypty tworzące i kasujące most wywoływać z poziomu demona openvpn.
Równoważna konfiguracja dla Gentoo Linux

Dzięki możliwości definiowania zależności jednej usługi od drugiej można w prosty sposób w konfiguracji interfejsów sieciowych powiązać most br0 z demonem OpenVPN. Dodatkowo Gentoo obsługuje wiele instancji demona openvpn na raz w podobny sposób jak interfejsy sieciowe - skrypt startowy /etc/init.d/openvpn.XYZ uruchamia demona openvpn z plikiem konfiguracyjnym /etc/openvpn/XYZ.conf. Zawartość pliku /etc/conf.d/net:

config_eth0=("null");			# 1

bridge_br0=("eth0 tap12");		# 2
brctl_br0=("stp on");			# 3
depend_br0() {				# 4
	need net.eth0 openvpn.tap12
};

Polecenia do wykonania:

ln -s /etc/init.d/net.lo /etc/init.d/net.eth0
ln -s /etc/init.d/net.lo /etc/init.d/net.br0
ln -s /etc/init.d/openvpn /etc/init.d/openvpn.tap12
rc-update add net.br0 default

Opis konfiguracji:

  • Linijka (1) ustawia pustą konfigurację interfejsu eth0.
  • Linijki (2-3) ustawia konfigurację mostu.
  • Linijka (4) ustawia zależność interfejsu br0 od usługi openvpn.tap12. Dzięki temu zatrzymanie usługi openvpn.tap12 wymusi wcześniej zniszczenie mostu, a włączenie mostu wymusi najpierw start OpenVPN.