Vlastní řetězce
Netfilter umožňuje definovat vlastní řetězce, a tím pravidla paketového filtru logicky členit a zjednodušit. Je to podobné jako práce s funkcemi v programovacím jazyce. Jak už víte, Netfilter zná tři základní řetězce: INPUT
, OUTPUT
a FORWARD
. Tyto řetězce nelze smazat, pouze vyčistit. Je možné vytvořit nový řetězec a v existujících řetězcích se na něj pak odkázat, tedy poslat paket, který vyhoví danému pravidlu, do daného řetězce. Uživatelem definované řetězce nemají politiku, takže pokud paket uživatelským řetězcem projde, aniž by byl zachycen nějakým pravidlem, vrací se zpět do řetězce, odkud byl do uživatelsky definovaného řetězce odeslán.
Asi nejlepší bude demonstrovat tuto funkci na příkladu. Za tímto účelem rozšířím firewall, který jsem vám předvedl v minulém díle:
1. iptables -F 2. iptables -X 3. iptables -P INPUT DROP 4. iptables -P OUTPUT ACCEPT 5. iptables -P FORWARD DROP 6. iptables -N ssh 7. iptables -A ssh -s 10.0.0.0/8 -j ACCEPT 8. iptables -A ssh -s 43.21.12.34 -j DROP 9. iptables -A ssh -m limit --limit 5/sec --limit-burst 100 -j ACCEPT 10. iptables -A ssh -j DROP 11. iptables -A INPUT -i lo -j ACCEPT 12. iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT 13. iptables -A INPUT -m state --state INVALID -j DROP 14. iptables -A INPUT -p tcp --dport 22 -m state --state NEW -j ssh 15. iptables -A INPUT -p tcp --dport 80 -m state --state NEW -j ACCEPT 16. iptables -A INPUT -p icmp -j ACCEPT 17. iptables -A INPUT -j DROP
Příkaz na prvním řádku odstraní všechna pravidla ze všech řetězců, druhý příkaz odstraní všechny prázdné uživatelem definované řetězce. Následuje vytvoření nového řetězce s názvem ssh
, kde je naznačen whitelist a blacklist (řádky 7 a 8), a poté následuje omezení počtu spojení na SSH (řádek 9). Poslední pravidlo v řetězci (řádek 10) zahazuje všechny pakety, které neodpoví některému z pravidel v řetězci.
Na řetězec ssh
je odkázáno na řádku 14, kde je uživatelsky definovaný řetězec předán parametru -j
, který určuje, co se má s paketem vyhovujícím danému pravidlu provést. Příchozí pakety tedy v případě takto definovaného firewallu dorazí nejprve do řetězce INPUT
, tedy na řádek č. 11, a teprve pakety, které vyhoví pravidlu na řádku č. 14, budou poslány do řetězce ssh
.
Na další příklad užití vlastních řetězců (a o něco lepší metodu zabezpečení SSH na úrovni firewallu) se můžete podívat ve čtvrtém dílu miniseriálu o zabezpečení SSH.
Pokud potřebujete paket z řetězu propustit, aniž by byl přijat, odmítnut nebo zahozen, tedy aby se vrátil zpět do původního řetězu, odkud byl do daného uživatelem definovaného řetězu vyslán, použijte RETURN
jako parametr pro -j
, takto:
[...] 1. iptables -N whitelist 2. iptables -A whitelist -s 10.0.0.0/8 -j RETURN 3. iptables -A whitelist -j DROP [...] 4. iptables -A INPUT [...] -j whitelist [...]
V tomto případě bude paket vyhovující čtvrtému pravidlu poslán do řetězce whitelist
, kde projde pravidlem č. 2, přičemž pokud mu vyhoví, poputuje zpět do řetězce INPUT
za pravidlo č. 4, pokud mu nevyhoví, pak dorazí k pravidlu č. 3 a bude zahozen.
Logování paketů
Někdy může být velice žádoucí, abyste určitý specifický síťový provoz monitorovali trošku blíže, tedy abyste nechali jisté pakety logovat. Pokud se ještě chvilku budu držet příkladů na vlastní řetězce, mohl by příklad na logování paketů vypadat třeba takto:
[...] 1. iptables -N 2. iptables -A strange -s 10.0.0.0/8 -j LOG --log-prefix "iptables-strange-local: " 3. iptables -A strange -s 12.23.34.45 -j LOG --log-prefix "iptables-strange-offender: " 4. iptables -A strange -j DROP [...] 5 iptables -A INPUT -m state --state INVALID -j strange [...]
V tomto příkladu jsou všechny pakety ve stavu INVALID
poslány do uživatelsky definovaného řetězce strange
, ve kterém dochází k výběru jedné sítě a jedné IP adresy, u nichž se provádí logování. Všechno ostatní se zahazuje.
Samotné logování je průchozí operace, tzn. pokud paket pravidlu s cílem LOG
vyhoví, je zalogován, ale pokračuje dál. Proto je zde na řádku č. 4 definováno pravidlo, které všechny pakety v tomto řetězci zahodí. Samotné logování má nepovinnou volbu --log-prefix
, která umožňuje specifikovat, čím bude hlášení na řádce se záznamem v logu začínat. Výsledek pak v logu může vypadat třeba takto:
Jul 25 03:49:51 debian kernel: [5466089.604926] iptables-strange-local: IN=eth0 OUT=eth1 SRC=10.0.1.15 DST=1.2.3.4 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=22177 DF PROTO=TCP SPT=45320 DPT=22 WINDOW=5840 RES=0x00 SYN URGP=0 UID=0 GID=0
Množství informací, které jsou o daných paketech získávány, můžete ovlivnit volbou --log-level
.
Malý příklad na procvičení
Podívejte se na následující příklad a zauvažujte, co se stane s paketem, který je ve stavu INVALID
a má zdrojovou IP adresu 10.0.1.12
?
1. iptables -P INPUT ACCEPT 2. iptables -N 3. iptables -A strange -s 10.0.0.0/8 -j LOG --log-prefix "iptables-strange-local " 4. iptables -A strange -s 12.23.34.45 -j LOG --log-prefix "iptables-strange-offender " 5. iptables -A INPUT -i lo -j ACCEPT 6. iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT 7. iptables -A INPUT -m state --state INVALID -j strange
Paket dorazí do řetězce INPUT
, kde je zachycen pravidlem na řádku č. 7 a odeslán do řetězce strange
. Zde vyhoví pravidlu na řádku č. 3 a je zalogován. Jelikož logování je průchozí operace, pokračuje paket po zalogování dál, avšak v řetězci strange
již nejsou žádná další pravidla, tudíž bude příslušný paket vrácen zpět do řetězce INPUT
. Zde již také nejsou žádná pravidla, tudíž bude s paketem naloženo dle výchozí politiky pro řetězec INPUT
, a paket bude propuštěn, což je samozřejmě v případě INVALID
paketů patrně nežádoucí.
Řetězec FORWARD a routing v GNU/Linuxu
GNU/Linux může fungovat jako router, tedy předávat pakety z jednoho rozhraní na jiné, z jedné sítě do druhé. Pakety, které nejsou určeny pro daný počítač, nýbrž jím jen prochází, putují v rámci paketového filtru řetězcem FORWARD
. To je důvodem, proč v dřívějších příkladech byla politika pro řetězec FORWARD
nastavena na DROP
.
K samotnému zprovoznění routingu je však zapotřebí routing povolit v konfiguraci jádra, tedy v sysctl.conf
:
net.ipv4.ip_forward=1 net.ipv6.conf.all.forwarding=1
Všimněte si, že je zde opět oddělen protokol IPv4 a IPv6, tzn. předávání paketů se nastavuje individuálně pro každý z protokolů. Změna tohoto konfiguračního souboru se projeví až po restartu, i když je samozřejmě možné příslušnou změnu provést ručně a okamžitě, prostřednictvím nástroje sysctl
:
sysctl -w net.ipv4.ip_forward=1 sysctl -w net.ipv6.conf.all.forwarding=1
Samotné filtrování předávaných paketů pak může vypadat třeba takto:
[...] 1. iptables -P FORWARD DROP 2. iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT 3. iptables -A FORWARD -i eth0 -o eth1 -j ACCEPT 4. iptables -A FORWARD -s 10.0.0.0/24 -d 10.0.1.0/24 -j ACCEPT 5. iptables -A FORWARD -s 10.0.1.0/24 -d 10.0.0.0/24 -j ACCEPT [...]
Zde je na prvním řádku nastavena výchozí politika řetězce FORWARD
, na druhém řádku je povolen průchod paketů, které náleží již vytvořeným spojením, nebo se jich týkají, na třetím řádku je pak povolen veškerý síťový provoz směřující z rozhraní eth0
na rozhraní eth1
, a konečně na posledních dvou řádcích je povolen provoz v obou směrech mezi sítěmi 10.0.0.0/24
a 10.0.1.0/24
.
Alternativy k iptables
Nastavovat firewall je komplikovaná záležitost, což je patrně z dosavadních dílů o základech iptables
více než jasné. Proto existuje řada projektů, které si kladou za cíl stavbu firewallu zjednodušit. Existují dokonce i jisté ekvivalenty "osobních" firewallů, které se snaží být uživatelsky přívětivé a zaměřují se na běžné uživatele. Tím je třeba nástroj Firestarter.
Jiné typy nástrojů se pokouší usnadnit vytváření pravidel, ať již snahou o usnadnění návrhu komplikovaného firewallu (fwbuilder), nebo značným zjednodušením syntaxe (ufw, FireHOL, atd.).
Na závěr jsem si nechal projekt Shorewall, což je de facto nadstavba nad iptables
, která z několika přehledných konfiguračních souborů vygeneruje příslušná pravidla pro nástroj iptables
a nastaví linuxový paketový filtr. Pokud se chcete o Shorewallu dozvědět více, můžete se podívat na článek Shorewall 2 - rychlá obrana na stanici a dvoudílný miniseriál o Shorewallu (1. díl, 2. díl).