V našem příkladu budeme mít dvě sítě, každá z nich má dvě konektivity a sítě jsou propojené dvěma vpn tunely. Budeme řešit dostupnost sítí při výpadku konektivity. To znamená testování stavu připojení a reakce na změnu – v našem případě úpravu routování. Další použití může být pro jednoduchý multihoming. V případě výpadku hlavní konektivity se na internet dostaneme přes záložní linku.
Takovou věc je možné řešit několika způsoby, třeba i shell skripty, které budou periodicky pingat a dle výsledku změní routovací tabulky. Další možnost je použití nějakého dynamického routovacího protokolu, např. OSPF. Ale proč brát kanón (OSPF + quagga) na vrabce? Postačí nám jeden malý démon.
tunel main _________ tunel main _________ 10.1.0.1 _____/ \ 10.1.0.2 __________ | ______________ / \__ ________________ | | ______________ | internet \ ________________ | FreeBSD | | / | FreeBSD 1 | ______________ \_______ / ________________ | 2 | ______________ \_________/ ________________ | _________| |__________ sit tunel back tunel back sit 2 192.168.60.0 10.1.0.5 10.1.0.6 192.168.70.0 255.255.255.0 255.255.255.0
Ifstatet pochazi z OpenBSD a je portován i do dalších systémů. Je to démon, který reaguje na změny sítě a dle těchto změn spouští námi definované příkazy. Démon se často používá v kombinaci s carp (Common Address Redundancy Protocol, viz man carp), tedy více strojů a sdílení adres. Dnes si ukážeme řešení bez něj, někdy příště se podíváme i na carp.
Změny v síti je schopen testovat dvěma metodami:
– stav síťových rozhraní – up, down a unknown
– externí testy – jsou spouštěné periodicky, nejčastěji se jedná o ping
Dále definujeme stavy, které mají dvě části:
– init blok – příkazy, které se vykonají při aktivaci stavu
– tělo – podmínky (if, if not), které se testují při změně stavů a na jejich vyhodnocení se přepne příslušný stav
Asi lépe si to ukázat na příkladu, zde je uvedena část konfiguračního souboru ifstated.conf
.
# co a jak testovat - v kazdem testu dva pingy # ukoncit po uspesnem prichodu prvniho a timeout jednu sekundu tun_main = '( "ping -q -c 2 -o -W1000 10.1.0.2 > /dev/null" every 10)' tun_back = '( "ping -q -c 2 -o -W1000 10.1.0.6 > /dev/null" every 10)' # definice stavu primary state primary { init { # toto se spusti pri aktivaci tohoto stavu run "route delete 192.168.70.0/24" run "route add 192.168.70.0/24 10.1.0.2" } # telo # pokud nebezi ani jeden z tunelu, prepni se do stavu nic if ! $tun_back && ! $tun_main set-state nic # kdyz nefunguje hlavni tunel, ale jde zalozni, prepni na backup if ! $tun_main && $tun_back set-state backup }state backup { init { ...
A teď praktická ukázka. Ta předpokládá funkční L3 tunely mezi lokalitami. To je nad rámec článku, já jsem použil OpenVPN.
Instalace démona ve FreeBSD je jednoduchá:
# cd /usr/ports/net/ifstated # make install
Automatické spouštění zajistíme v rc.conf
:
ifstated_enable="YES"
Konfigurační soubor si uložíme do /usr/local/etc/ifstated.conf
.
Konfigurace pro LAN 1:
init-state primary tun_main = '( "ping -q -c 2 -o -W1000 10.1.0.2 > /dev/null" every 10)' tun_back = '( "ping -q -c 2 -o -W1000 10.1.0.6 > /dev/null" every 10)' state primary { init { run "route delete 192.168.70.0/24" run "route add 192.168.70.0/24 10.1.0.2" } if ! $tun_back && ! $tun_main set-state nic if ! $tun_main && $tun_back set-state backup } state backup { init { run "route delete 192.168.70.0/24" run "route add 192.168.70.0/24 10.1.0.6" } if ! $tun_back && ! $tun_main set-state nic if ! $tun_back && $tun_main set-state primary } state nic { init { run "echo vypadek | mail -s vypadek admin@nekde.cz" } if $tun_main set-state primary if ! $tun_main && $tun_back set-state backup }
Konfigurace pro LAN 2:
init-state primary # init-state backup tun_main = '( "ping -q -c 2 -o -W1000 10.1.0.1 > /dev/null" every 10)' tun_back = '( "ping -q -c 2 -o -W1000 10.1.0.5 > /dev/null" every 10)' state primary { init { run "route delete 192.168.60.0/24" run "route add 192.168.60.0/24 10.1.0.1" } if ! $tun_back && ! $tun_main set-state nic if ! $tun_main && $tun_back set-state backup } state backup { init { run "route delete 192.168.60.0/24" run "route add 192.168.60.0/24 10.1.0.5" } if ! $tun_back && ! $tun_main set-state nic if ! $tun_back && $tun_main set-state primary } state nic { init { run " echo vypadek | mail -s vypadek admin@nekde.cz" } if $tun_main set-state primary if ! $tun_main && $tun_back set-state backup }
V sekci init nemusí být jen routování, můžeme si například zalogovat změnu nebo si poslat e-mail/SMS o stavu.
Pokud pingáte dost rychle, přepnutí bude rychlejší než u defaultně nastaveného OSPF. Pozor ale na timeout u pingu. Pokud nevhodně nastavíte počet pingů a jejich timeout, může se stát, že test nestihne doběhnout a je násilně ukončen dalším testem, a tím nedostáváme správný stav. Např. timeout pingu je tři sekundy, spouštíte test každých pět sekund a nastane stav, že ze tří testovacích pingů první dva vyprší a už jsme na šesti sekundách a test je ukončen. Parametry u pingu je nutné si také upravit dle vašeho systému.
Ping testů může být víc, lze snadno detekovat chybu u poskytovatele, když například dopingneme výchozí bránu, ale zařízení za touto branou již ne. Jen vzniknou trošku složitější podmínky v jednotlivých stavech.
Pokud nechceme řešit podobné hrátky s VPN, ale jen jednu lokalitu a dvě konektivity, stačí nastavit správně ping testy a měnit si výchozí bránu, případně nastavení firewallu. Jak jsem uváděl – podobné řešení je možné postavit třeba jen na shell skriptu, i to má své kouzlo. Záměrem bylo, ukázat podobné řešení elegantněji. Toto řešení nedokáže vše, při přepnutí konektivity samozřejmě přijdete o navázaná TCP spojení, to IPv4 neumí řešit.