Linux jako internetová gateway (4)

4. 2. 2004
Doba čtení: 9 minut

Sdílet

V dnešním, posledním dílu seriálu o stavbě linuxového routeru si nastavíme firewall pomocí iptables.

Firewall a překlad adres

Firewall nám bude sloužit k zabezpečení sítí schovaných za routerem a také k ochraně routeru jako takového, no a v poslední řadě bude dělat nat neboli překlad adres, což umožní několika počítačům ve vnitřní síti chodit ven přes jednu IP adresu. Na Linuxu je toto vše realizováno programem iptables. Na ROOTu proběhl seriál Stavíme firewall, kde je návod na mnohem širší využití firewallu, než jakým se zde budeme zabývat my. Nastíním zde pouze základní model, kompletní využití všech vymožeností, a není jich málo, prostudujte v článku, o kterém jsem se již zmínil výše.

Iptables má tři základní směry toku dat, řetězce – INPUT, OUTPUT a FORWARD. Input a output se týkají pouze komunikace mezi kýmkoliv a naším serverem. Ale pokud plní server funkci routeru, veškerá komunikace, která skrz něj projde z vnitřní sítě do internetu a opačně, používá forward. Tedy pokud já zakáži na server ping pomocí řetězce INPUT nebo OUTPUT, ping do internetu projde, protože řetězce INPUT a OUTPUT se na něj nevztahují. Samozřejmě řetězce si lze i přidávat vlastní, ale tím se zde zabývat nebudeme, to už je složitější a pro naši potřebu zbytečné.

Nejdříve si zavedeme moduly, které budeme potřebovat. Předpokládám, že máme použito jádro bare.i, které má pro tyto moduly podporu.

Tabulka č. 541
modprobe ip_tables základ, spustí firewall, kterému pak budeme dávat pravidla přes iptables
modprobe ip_conntrack_ftp umožňuje průchod aktivního ftp firewallem
modprobe ip_nat_ftp umožňuje průchod aktivního ftp firewallem
modprobe ip_MASQUERADE maškaráda – překlad adres

Nyní se můžeme podívat na naše pravidla příkazem iptables -L -v, jak vidíte, vše je prázdné a firewall volně průchozí, no a my můžeme začít blokovat. Uvedu příklad a na něm si vysvětlíme všechny možné parametry.

iptables -A INPUT -i eth1 -p tcp --dport 23 -j ACCEPT

Tímto příkazem přidáme pravidlo, které nám povolí jakékoliv spojení přicházející interfacem ethernet1 na náš server, ale pouze na portu 23, což je telnet.

Pokud místo -A  dáme -D, pravidlo se smaže. Zkuste si to zadat a vypsat pravidla ( iptables -L -v). Nedělejte ale nic jiného, protože zde už si můžete snadno odříznout spojení. Parametr -I pravidlo vloží na začátek řetězce, toto má cenu pouze při ladění firewallu. Tím jsme si vysvětlili, jak pravidla přidávat a odebírat, a řekneme si teď něco k dalším parametrům.

-i eth1 určuje směr a interface, kterým paket přijde; pokud přijde paket jiným rozhraním, pravidlo se na něj nevztahuje; dalším směrem je logicky odchod  -o eth0

-p tcp nám říká, že paket je z protokolu TCP, další možné protokoly jsou zapsány v souboru /etc/protocols, nás bude asi zajímat pouze TCP, UDP a ICMP

--dport 23 určuje, že paket má cílový port, port určuje, o jakou službu se jedná, 23 je telnet; seznam portů a služeb je v /etc/services; obdobným parametrem je --sport; pokud uvádíte port, je nutno si uvědomit, na jakém protokolu služba běží

-j ACCEPT, to je akce, co se s paketem má udělat; ACCEPT – přijmout, DROP – zahodit, REJECT – odmítnout

-s 192.168.1.2 tento parametr zatím není v příkladu uveden, ale znamená zdrojovou adresu; -d 192.168.1.2 znamená zase cílovou adresu; za adresu se píše s lomítkem maska, pokud se jedná o síť, jinak je to vždy host

! znamená negaci, takže třeba -p ! tcp  – kromě protokolu tcp

Pokud některý z těchto parametrů vynecháme, tak to platí pro všechny, v našem případě nejsou zmínky o IP adresách, pravidlo tedy platí pro libovolnou ip adresu. Stejně pokud uvedete port bez protokolu, tak to platí pro všechny protokoly.

No a teď praktický příklad:

iptables -A INPUT -s 192.168.1.2 -p tcp --dport 23 -j ACCEPT
iptables -A FORWARD -i eth1 -o eth0 -p tcp --dport 23 -j DROP 

První pravidlo nám povolí přístup na náš server jen z jedné IP adresy, pakety z jiných IP adres nebudou vůbec vpuštěny do routeru, tedy pokud zbytek inputu defaultně zahazujeme, ale o tom dále.

Druhé pravidlo zakazuje jakýkoliv telnet, který přijde ethernetem 0 a bude chtít odejít ethernetem 1, ale pokud bude odcházet třeba ethernetem 2, tak projde.

Paket pravidla se procházejí odshora dolů, a pokud počítač narazí na to, které vyhovuje, aplikuje ho a dále již nepostupuje. Pokud nevyhoví žádné pravidlo, nastupují implicitní pravidla. Ta nastavíme třeba takto:

iptables -P INPUT DROP
iptables -P OUTPUT DROP
iptables -P FORWARD ACCEPT

Toto je jen příklad, jak to psát, já mám třeba drop jen na inputu, ale to si už musí každý rozhodnout sám. Pokud budete dávat na input implicitně drop, to bude asi většina, musíte zároveň povolit vstup na loopback, bez toho zlobí jakýkoliv kontakt na server nebo z něj, takže:

iptables -A INPUT -i lo -j ACCEPT

Ukážeme si to:

iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -s 192.168.1.2 -p tcp --dport 23 -j ACCEPT
iptables -A INPUT -s 192.168.1.3 -p tcp --dport 21 -j DROP
iptables -A INPUT -i eth1 -p tcp --dport 21 -j ACCEPT
iptables -P INPUT DROP 

Předpokládejme, že máme dva interfacy, eth0 – venkovní a eth1 – vnitřní se sítí 192.168.1.0. Po­čítač 192.168.1.2 se jako jediný dostane odkudkoliv, a to i když přijde z venkovního interfacu, telnetem na server. Počítač 192.168.1.3 se nedostane na ftp, ať už jde odkudkoliv, ale ostatní, které jsou ve vnitřní síti a půjdou na ftp, se na server dostanou. Tedy všichni kromě 192.168.1.3 a těch, co to budou zkoušet z venkovního interfacu. No a zbytek je vše zakázano.

Tento firewall bude sice fungovat, ale ohledně ftp bude mít jeden problém, a to, že ftp používá dva porty pro komunikaci, takže půjde používat pouze pasivní mód ftp. A další problém bude, že pokud se přihlásíme na server, nedostaneme se z něj nikam, ani pingem. Je to proto, že my sice paket odešleme, ale ten paket se nám už nevrátí, firewall nám ho zařízne, a tudíž ke spojení nedojde. Zde nastupuje stavový firewall, který sleduje veškerý provoz a pakety patřící už k nějakému vytvořenému spojení nebo související s nějakým spojením (např. s ftp) propustí. Na začátek pravidel tedy přidáme:

iptables -I INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT 

A teď již bude chodit i aktivní ftp a i z routeru se dostanete kamkoliv. To -I  je tam samozřejmě, pokud to dopisujeme, aby se to vložilo na začátek, v  rc.local to bude jako první položka u INPUT s -A.

Tímto jsme si vysvětlili logiku firewallu, pokud je ještě něco nejasného, myslím, že to pochopíte u komentovaných pravidel, která používám já. Teď si ukážeme tu hlavní věc, kterou chceme, a to, aby nám server zprostředkovával připojení pro naši vnitřní síť přes jednu adresu. To zabezpečí příkaz:

iptables -A POSTROUTING -t nat -o eth0 -j MASQUERADE 

Všechny pakety, které budou odcházet ethernetem0, budou překládány. Vypadá to tak, že router vezme z hlavičky paketu zdrojovou neveřejnou adresu a místo ní napíše svou veřejnou. Udělá si poznámku do překladové tabulky, aby mohl paket při odpovědi obdobně upravit a vrátit tazateli do vnitřní sítě. Obsah překladové tabulky zjistíme příkazem netstat -aM (možno přidat ještě parametr n, aby nepřekládal doménová jména), ale mně se to třeba nezobrazí. Lze použít také výpis:

root@thovt:~# cat /proc/net/ip_conntrack
tcp     6 431999 ESTABLISHED src=192.168.1.2 dst=192.168.1.1 sport=1094 dport=23 src=192.168.1.1 dst=192.168.1.2 sport=23 dport=1094 [ASSURED] use=1

tcp     6 188354 ESTABLISHED src=192.168.1.3 dst=212.80.46.58 sport=1436 dport=80 src=212.80.76.58 dst=1.1.1.77 sport=80 dport=1436 [ASSURED] use=1
tcp     6 188215 ESTABLISHED src=192.168.1.3 dst=212.80.46.26 sport=1428
dport=80 src=212.80.76.26 dst=1.1.1.77 sport=80 dport=1428 [ASSURED] use=1 

kde se dozvíte stejné informace, ale zde jsou veškerá spojení realizovaná na server nebo přes něj.

Nyní již byste měli mít dostatek informací pro postavení vlastního firewallu, ale ještě přidám svá vlastní pravidla pro komplexní pohled a pro inspiraci. Výpis pravidel rozdělím na několik částí a ty budu komentovat, části jsou v  rc.local za sebou.

iptables -P INPUT DROP
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -i eth1 -p tcp --dport 23 -j ACCEPT
iptables -A INPUT -i eth2 -p tcp --dport 23 -j ACCEPT
iptables -A INPUT -i ppp0 -p tcp --dport 23 -j ACCEPT
iptables -A INPUT -i eth1 -p tcp --dport 21 -j ACCEPT
iptables -A INPUT -i eth2 -p tcp --dport 21 -j ACCEPT
iptables -A INPUT -i ppp0 -p tcp --dport 21 -j ACCEPT
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -i eth1 -p icmp -j ACCEPT
iptables -A INPUT -i eth2 -p icmp -j ACCEPT
iptables -A INPUT -i ppp0 -p icmp -j ACCEPT 

Výchozí pravidlo pro input je vše zahodit, povoluji loopback. Na router se dá dostat telnetem a ftp pouze z vnitřních rozhraní. Ping funguje také pouze z vnitřních rozhraní.

iptables -A POSTROUTING -t nat -o eth0 -j MASQUERADE
iptables -A FORWARD -p tcp ! --syn -m state --state NEW -j DROP
iptables -A FORWARD -i eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -i eth0 -j DROP 

První řádek nám zapíná nat, samozřejmě každý firewall nemusí natovat. Druhý řádek tohoto výpisu zakazuje spojení, která vymyslel Microsoft, spojení bez syn paketu, což odporuje RFC, a tudíž je zakazuji, ale není to nutné tam mít. Další řádek povoluje vytvořená spojení a další zahazuje všechna spojení, která nenesou příznaky, že se jedná o spojení vytvořené zevnitř. Pokud by byly tyto dva řádky obráceně, spojení skrz router by nefungovalo. Pokud by někdo potřeboval propouštět něco dovnitř, pak se to píše před třetí řádek.

iptables -A FORWARD -o eth0 -p tcp --dport 80 -j ACCEPT
iptables -A FORWARD -o eth0 -p tcp --dport 443 -j ACCEPT
iptables -A FORWARD -o eth0 -p tcp --dport 25 -j ACCEPT
iptables -A FORWARD -o eth0 -p tcp --dport 110 -j ACCEPT
iptables -A FORWARD -o eth0 -p tcp --dport 53 -j ACCEPT
iptables -A FORWARD -o eth0 -p udp --dport 53 -j ACCEPT
iptables -A FORWARD -o eth0 -p tcp --dport 21 -j ACCEPT
iptables -A FORWARD -o eth0 -p tcp --dport 22 -j ACCEPT
iptables -A FORWARD -o eth0 -p tcp --dport 23 -j ACCEPT
iptables -A FORWARD -o eth0 -p tcp --dport 5190 -j ACCEPT
iptables -A FORWARD -o eth0 -p icmp -j ACCEPT
iptables -A FORWARD -o eth0 -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -o eth0 -j DROP 

Zde povoluji služby, které chci z Internetu poskytovat, toto omezení je na každém z vás, takže třeba s tímto nastavením si nespustíte irc nebo gamespy. Řádka s established je zde kvůli aktivnímu ftp. Zahazuji to na outputu proto, aby mezi vnitřními síťovými rozhraními chodilo vše, třeba síťové hry, ale do netu ne. Na komunikaci mezi vnitřními rozhraními totiž také platí forward.

iptables -A FORWARD -p tcp --dport 445 -j DROP
iptables -A FORWARD -p udp --dport 445 -j DROP
iptables -A FORWARD -p tcp --dport 135 -j DROP
iptables -A FORWARD -p udp --dport 135 -j DROP
iptables -A FORWARD -p tcp --dport 69 -j DROP
iptables -A FORWARD -p udp --dport 69 -j DROP
iptables -A FORWARD -p tcp --dport 1434 -j DROP
iptables -A FORWARD -p udp --dport 1434 -j DROP
iptables -A FORWARD -p tcp --dport 6667 -j DROP 

No a poslední část blokuje jakoukoliv komunikaci některých služeb, a to z důvodu šíření virů. Z praxe vím, že na těchto portech se viry nejvíce šíří, viry typu Red Code a Slammer. Já to mám omezeno, protože tyto služby nepoužívám, ale někdo si je třeba bude muset povolit, aby mu chodilo například SQL. Omezení proti virům je zde proto, abych zbytečně neucpával kapacitu naší wifi sítě balastem.

bitcoin_skoleni

No a to je vše, doufám, že se vám váš vlastní router podaří rozchodit a že vám bude sloužit k plné spokojenosti. Linuxu zdar.

Související odkazy:

Stavíme firewall velice podrobně rozebraný firewall
CZ Free.net
Seriály na ABC Linuxu
Slabook v češtině a další věci

Autor článku

V současné době pracuje jako správce linuxových systémů na Univerzitě Pardubice.