PING z 123.45.67.90 na 123.45.67.80 projde, ale nepůjde přes tunel. To je jasné, neboť tunel spojuje sítě 192.168.0.0/16 a 192.168.1.0/24. Pokud dáme PING z 123.45.67.90 na 192.168.1.1 (což budeme předpokládat, že je vnitřní adresa počítače 123.45.67.80), také neprojde. Co se děje? Pošle se PING packet z 123.45.67.90 na 192.168.1.1. Ten jde (podle routovacích pravidel, jež si můžete vypsat) do tunelu. Ale na druhém konci tunelu nastane problém. Přišel nám tunelem packet od 123.45.67.90. My však máme v konfiguraci, že na druhé straně tunelu je síť 192.168.0.0/16. Takový packet nám nemá co přijít – zahodíme ho. Proto packety neprochází. Odborně se tomu říká „spoofing protection“ :-)
Co s tím? Mohou být situace, kde dostupnost koncových strojů tunelu přes privátní IP nepotřebujeme. Tam je to nejjednodušší, nic dělat nemusíme. Dále má IPSec možnost spoofing protection vypnout. Ale to bych nedoporučoval. Už proto, že packet zpět by nešel přes tunel (byl by na netunelovanou adresu 123.45.67.90).
Využijeme tedy možností balíku iproute2. Pokud si dáte příkaz ip route, uvidíte pravidlo podobné následujícímu:
192.168.1.0/24 via <gateway> dev ipsec0
Toto je pravidlo, podle kterého se routuje vzdálená síť přes IPSec tunel. My si ho upravíme příkazem:
ip route replace 192.168.1.0/24 via <gateway> dev ipsec0 src 192.168.0.1
Předpokládáme, že 192.168.0.1 je vnitřní rozhraní našeho počítače. Toto pravidlo říká, že pokud posíláme do sítě 192.168.1.0/24, máme packet poslat šifrovaným tunelem a zdrojová adresa má být pokud možno 192.168.0.1. K tomu dodám ještě malé vysvětlení: Pokud počítač odesílá packet, musí mu dát nějakou odchozí (zdrojovou) adresu. To může být libovolná adresa některého z rozhraní počítače. V našem příkladu si předtím vybíral adresu venkovní ethernetové karty. My jsme mu ale řekli, že v případě posílání tunelem (uplatnění routovacího pravidla) má použít adresu v privátní síti.
Nyní by již měl projít PING z tohoto počítače na druhý. Podobnou úpravu pravidla musíme provést i na druhém počítači a vše bude chodit.
Bylo by ovšem dosti nešikovné, muset pravidlo upravovat pokaždé ručně. Proto použijeme konfigurační direktivu leftupdown, případně rightupdown. Přidává se do konfigurace tunelu (třeba za leftsubnet) a jejím parametrem je jméno skriptu. Například:
leftupdown=/etc/change_routing.sh
Skript má v proměnných prostředí (environment variables) parametry tunelu. Pro jejich detailní popis odkazuji na dokumentaci. Zde uvedu pouze skript, který zařídí výše uvedenou změnu pravidla:
#!/bin/sh
if [ "$PLUTO_VERB" == "up-client" ]; then
# Akce - spojeni bylo nastartovano
if [ "$PLUTO_CONNECTION" == "centrala-pobocka1" ]; then
# Spojeni na pobocku1 - zmenime pravidlo
ip route replace 192.168.1.0/24 via <gateway> dev ipsec0 src 192.168.0.1
fi
fi
Další zádrhele
Někdy můžeme chtít přes IPSec spojení routovat veškerý provoz do Internetu. Toho můžeme dosáhnout tak, že jako jednu ze sítí dáme 0.0.0.0/0. IPSec toto nastavení „skousne“. Jediné, co působí problémy, je fakt, že nepřidá pravidlo pro routování sítě 0.0.0.0/0 (default route). Musíme ho přidat sami v updown skriptu – podobně, jako jsme měnili routing ve výše uvedeném příkladu. Rovněž je nutné routovat provoz na veřejné IP druhého konce tunelu explicitně přes nešifrované spojení, jinak si počítač odřízneme.
Další problém nastával na Debianu, ale je možné, že bude nastávat i v jiných distribucích. Dělo se tak při restartu nastavení sítě (/etc/init.d/networking restart) – zcela přestala chodit síť. Na vině bylo následující:
Mějme počítač připojený do internetu přes síť 12.34.56.0/30, kde 12.34.56.1 je router a 12.34.56.2 venkovní rozhraní našeho počítače eth0. Potom máme v routing tabulce následující pravidlo:
12.34.56.0/30 dev eth0 proto kernel scope link src 12.34.56.2
Toto pravidlo říká, že zařízením se dostaneme přímo do sítě 12.34.56.0/30. Pokud spustíme IPSec na zařízení eth0, objeví se nám v tabulce pod tímto pravidlem ještě jedno:
12.34.56.0/30 dev ipsec0 proto kernel scope link src 12.34.56.2
Toto pravidlo přidá IPSec. Nyní, co se stane při restartu sítě. Normálně se při rozhodování, kam packet půjde, používá první pravidlo (s eth0), neboť je v tabulce výše. Po shození sítě (zařízení eth0) bude pravidlo vymazáno, protože zařízení je dole, a tudíž přes něj nemůžeme routovat. Jestliže síť znovu nahodíme, tak se pravidlo buď nepřidá, neboť pro danou síť tam už jedno je, nebo, pokud se použije příkaz ip route append, se přidá, ale za pravidlo s ipsec0. V obou případech to ale vyjde nastejno. Při routingu do sítě 12.34.56.0/30 se bude používat pravidlo s ipsec0 – buď proto, že je jediné, nebo proto, že je první. A síť nebude chodit.
Řešením tohoto problému je zajistit, aby se při shození sítě vždy nejprve shodil ipsec a po jejím případném nahození zase nahodil. Na Debianu jsem to vyřešil editací skriptu /etc/init.d/networking, na jiných distribucích by se to řešilo obdobně. Stále je ale nutné dát si pozor a neshazovateth0 bez shození IPSecu.
Možná si řeknete, proč tam IPSec to pravidlo přidává? I to zde vysvětlím. Jak jsme už viděli výše, IPSec přidává pravidlo pro routing do tunelu. V tomto případě by vypadalo následovně:
192.168.1.0/24 via 12.34.56.1 dev ipsec0
Když by se toto pravidlo pouze přidalo, kernel by přidání odmítl, neboť podle jeho informací není počítač 12.34.56.1 přes zařízení ipsec0 dosažitelný. Výše uvedené pravidlo vlastně říká, že tento počítač (respektive celá síť 12.34.56.0/30) je dosažitelný i přes ipsec0 a kernel povolí IPSecu přidat pravidlo pro routing do tunelu.
Seriál o přesměrovávání a tunelování ukončím malou poznámkou k výše uvedenému problému: Teoreticky by IPSec mohl při přidávání routování do tunelu použít parametr onlink příkazu ip a pak by žádný problém neměl. Takže je možné, že dotyčné pravidlo slouží ještě nějakým dalším záhadným účelům IPSecu :-)