Multi gateway, aneb jak na dva providery prakticky

24.09.2009

Dejme tomu, že provozujete síť, máte pár uživatelů, router s Linxem, který překládá odchozí spojení a jednoho postkytovatele k internetu. Uživatelé jsou však děsně nenažraní a chtějí stále víc a víc. Vy se proto rozhodnete, že jim pořídíte ještě jedno připojení. Jenže jak to v routeru nastavit? Tak přesně na tuto otázku se pokusí odpovědět tento návod.

Pro zjednodušení se vyhneme řešením, které umožňují dynamicky přidělovat nevyužitou kapacitu jednotlivých linek a jakkoliv zasahovat do rychlostí pro jednotlivé uživatele. Výsledkem bude možnost říct, že uživatelé Franta a Jirka pojedou přes providera A a Tomáš a Jan přes providera B.

Předpoklady

Uvedený postup pracuje na bežném distribučním jádře, konkrétně testováno na Debian Lenny – pro tuto distribuci budou sedět i ukázkové příklady. Nutnou podmínkou je přítomnost programu ip, který je obvykle v balíku iproute. Pokud v základní instalaci není, lze ho doinstalovat takto:

apt-get install iproute

Situace

Na výše uvedeném obrázku je znázorněna typická situace malé sítě s několika uživateli a jedním připojením do Internetu. Odchozí spojení lokálních uživatelů jsou překládána (NAT) na IP adresu přidělenou od poskytovatele. Červenou barvou je znázorněno druhé připojení do Internetu, které má zvýšit komfort lokálním uživatelům. Z obrázku je také zřejmé, že chceme, aby Franta a Jirka využívali stávající připojení přes Poskytovatele A a Tomáš a Honza pak nově zrealizované připojení od Poskytovatele B.

Směrovací tabulky

Pokud využíváme pouze jednoho poskytovatele a nemáme lokální síť komplikovaněji rozdělenou do více podsítí, obsahuje hlavní směrovací tabulka v podstatě jen záznam o výchozí bráně poskytovatele připojení. Zdrojové adresy uživatelů jsou ve směru do internetu nahrazovány IP adresou rozhraní eth1 a vše pracuje bezproblémů.

router:~# route
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
default         88.88.88.1      0.0.0.0         UG    0      0        0 eth1

Pokud však chceme, aby pakety odcházely do sítě Poskytovatele B, narazíme na problém, že ve směrovací tabulce nemůže být vloženo více výchozích bran. A i kdyby šlo, jak Linuxu říct, že chceme, aby Franta a Jan používali právě a tu výchozí bránu? Řešení je v následujících 5-ti bodech.

Postup

1) Odstranění výchozí brány z hlavní směrovací tabulky

V první fázi je nutné odstranit výchozí bránu z hlavní směrovací tabulky a to z důvodu, že výchozí brány pro jednotlivá připojení budeme specifikovat později jinde.

route del default gw 88.88.88.1

Dále je nutné zajistit, aby se výchozí brána nenastavoval automaticky po restartu systému. Je tedy nutné upravit network skripty. V Debianu je to v souboru /etc/network/interfaces, kde se smaže nebo zakomentuje řádek s gateway.

2) Vytvoření dalších směrovacích tabulek

Linux disponuje možností použít více nezávislých směrovacích tabulek a toto využijeme. Jejich seznam lze upravovat v souboru /etc/iproute2/rt_tables. Vzorový obsah souboru po přidání vlastní tabulky table_for_b by měl vypadat následovně:

router: # cat /etc/iproute2/rt_tables
255     local
254     main
253     default
200     table_for_b

Tabulka local obsahuje záznamy lokálních rozhraní, tabulka main je naše hlavní směrovací tabulka a její obsah lze vypsat příkazem route. Tabulka default je implicitně prázdná.

3) Přidání výchozích bran poskytovatelů

Vložení výchozích bran do nově vytvořené tabulky table_for_b a default se provede takto:

ip route add default via 88.88.88.1 table default
ip route add default via 77.77.77.1 table table_for_b

Obsah tabulek table_for_b a default je pak následující:

router:# ip route list table default
default via 88.88.88.1 dev eth1

router:# ip route list table table_for_b
default via 77.77.77.1 dev eth2

Zde je nutno podotknout, že příkaz route nemá v tomto případě smysl, neboť je schopen operovat pouze s tabulkou main a local dohromady – z tohoto důvodu je vhodné si zvyknout používání příkazu ip i při prostém prohlížení obsahu hlavní směrovací tabulky.

4) Vyhodnocování tabulek

Aby mělo používání více směrovacích tabulek smysl, existuje v jádře vyhodnocovací seznam, na jehož základě se jednotlivé tabulky ve směrovacím mechanismu použijí.

router:~# ip rule
0:      from all lookup local
32766:  from all lookup main
32767:  from all lookup default

Z uvedeného vyplývá, že pro všechny pakety se nejprve vyhodnotí tabulka local, následně main a nakonec default. Číslo vlevo se nazývá priorita. Pokud tedy nic jiného neprovedeme, Internet uživatelům pojede a to i přesto, že příkazem route zjistíme, že není definována výchozí brána. Je však uvedena v tabulce default.

Tento seznam v základní podobě příliš nepostačuje, takže ho upravíme a to tím způsobem, že přesuneme vyhodnocování tabulky main z priority 32766 na prioritu 100. Mezi vyhodnocením tabulky main a default tak vznikne poměrně široký interval priorit pro vložení dalších pravidel.

ip rule del prio 32766 
ip rule add table main prio 100 

A nyní to nejhlavnější. Vytvoříme pravidlo, které říká, že pokud přijde paket od uživatele Tomáš nebo Jan, bude na něj, kromě základní tabulky main s prioritou 100, uplatněna i tabulka table_for_b. Že tato tabulka obsahuje výchozí bránu pro Poskytovatele B je již zřejmé.

ip rule add from IP_TOMAS table table_for_b prio 1000
ip rule add from IP_JAN table table_for_b prio 1001

router:~# ip rule
0:      from all lookup local
100:    from all lookup main
1000:   from 192.168.1.4 lookup table_for_b
1001:   from 192.168.1.5 lookup table_for_b
32767:  from all lookup default

Na všechny ostatní uživatele (Franta a Jirka) bude uplatněn obsah tabulky default a tedy výchozí brána Poskytovatele A.

Pravidla lze tvořit podstatně jemněji než jen dle zdrojové IP adresy. Lze využít cílovou IP, port, protokol apod. Pro účel tohoto návodu však plně dostačují pravidla tyto.

5) Úprava NATu

Samozřejmě je nutné nezapomenout upravit příslušná pravidla pro NAT, protože se překládá na jinou IP adresu a pakety jdou na jiné rozhraní:

# franta
iptables -t nat -A POSTROUTING -s 192.168.1.2 -o eth1 -j SNAT --to 88.88.88.2
# jirka
iptables -t nat -A POSTROUTING -s 192.168.1.3 -o eth1 -j SNAT --to 88.88.88.2

# franta
iptables -t nat -A POSTROUTING -s 192.168.1.4 -o eth2 -j SNAT --to 77.77.77.2
# franta
iptables -t nat -A POSTROUTING -s 192.168.1.5 -o eth2 -j SNAT --to 77.77.77.2