Vítám vás u třetího dílu o iptables. Minule jsme si ukázali, jak nastavit jednoduchý firewall - nefirewall. Vysvětlili jsme si složitější pravidla a techniky, které dnes použijeme v konfiguraci. Výsledkem dnešního dílu bude úplná a funkční konfigurace iptables. Zautomatizované nastavení firewallu se děje nejlépe pomocí skritpu. V následující části si jeden takový uvedeme a vysvětlíme všechny jeho pravidla.
Skript
Základ tohoto skriptu vytvořil Miroslav Petříček někdy koncem roku 2001. Od té doby prošel korekturou mnoha programátorů a bezpečnostních specialistů. Výsledkem je kvalitní konfigurace. Poslední jeho verzi si můžete stáhnout na http://www.petricek.cz/mpfw/. Následující části tohoto článku korespondují s jednotlivými částmi skriptu.
Nastavení globálních proměnných
Proměnné ve skriptu nám velmi pomohou. Všechny údaje jsou shromážděny na jednom místě. Pokud se změní třeba IP adresa serveru, není třeba zasahovat hluboko do konfigurace firewallu. Stačí jenom změnit údaj na jediném místě a máme firewall přenastavený (samozřejmě po znovunačtení pravidel).
První proměnné určují vaši IP adresu na vnějším rozhraní a určují, které rozhraní je vnější.
INET_IP="1.2.3.4"
INET_IFACE="eth1"
Další proměnné analogicky nastavují IP adresu na vnitřním rozhraní, které rozhraní je vnitřní a broadcast na vnitřní síti
LAN1_IP="192.168.1.1/32"
LAN1_BCAST="192.168.1.255/32"
LAN1_IFACE="eth0"
Následuje nastavení loopback rozhraní, opět adresa a název rozhraní.
LO_IFACE="lo"
LO_IP="127.0.0.1/32"
Je výhodné nastavit cestu k iptables do proměnné. Kdyby se tato změnila, stačí ji upravit na jediném místě a ne v každém pravidle.
IPTABLES="/sbin/iptables"
Moduly
Díky modulům má iptables mnohem větší možnosti, než pouze filtrování pravidel. Proto je výhodné je využít.
Nejprve musíme inicializovat moduly.
/sbin/depmod -a
Pak zavedeme moduly pro nestandardní cíle.
/sbin/modprobe ipt_LOG
/sbin/modprobe ipt_REJECT
/sbin/modprobe ipt_MASQUERADE
Využijeme modul pro FTP přenosy.
/sbin/modprobe ip_conntrack_ftp
/sbin/modprobe ip_nat_ftp
Povolíme směrování packetů. Každý packet z vnitřní sítě, který směřuje do internetu, musí být předán mezi rozhraními, jinak se vám žádný počítač na internet nedostane. Předávání povolíme následujícím kódem.
echo "1" > /proc/sys/net/ipv4/ip_forward
Zapneme rp_filter na kontrolu IP spoofing. IP spoofing je taková technika, kdy útočník změní svou zdrojovou adresu, aby se vydával za někoho jiného (popř. skryl svou skutečnou IP). Samotný spoofing je pojem označující typ útoku s podvrženými údaji. Známe DNS spoofing, DHCP spoofing atd. Rp filtr nám poskytuje jednoduchou obranu proti IP spoofingu - na rozhraní kontroluje zdrojové adresy packetů. Pak rozhodne, jestli se na daném rozhraní může taková adresa objevit. Následující kód zapne rp filtr pro všechny rozhraní.
for interface in /proc/sys/net/ipv4/conf/*/rp_filter; do
echo "1" > ${interface}
done
Implicitní politika
Rozhodně je jednodušší povolovat tu komunikaci, která je žádoucí, než zakazovat všechnu tu komunikaci, která je nežádoucí. Proto volíme implicitní politiku takovou, která všechny packety zahodí. Projdou jenom ty packety, které v pravidlech konkrétně povolíme.
$IPTABLES -P INPUT DROP
$IPTABLES -P OUTPUT DROP
$IPTABLES -P FORWARD DROP
Prerouting
Zde si můžeme nastavit transparentní proxy (co je to transparentní proxy viz. minulý díl)
$IPTABLES -t nat -A PREROUTING -p tcp -i ! $INET_IFACE -d ! $INET_IP --dport 80 -j REDIRECT --to-port 3128
Postrouting
Zde musíme hlavně zprovoznit IP maškarádu (co je to IP masquerade viz. minulý díl)
$IPTABLES -t nat -A POSTROUTING -o $INET_IFACE -j SNAT --to $INET_IP
Pomocné řetězce
Nyní si vytvoříme dva řetězce pro snažší kontrolu rezervované adresy. První řetězec je logdrop. Všechny packety, které zašleme do tohoto řetězce, se nám zalogují podle nastaveného limitu a zahodí. Logování je neterminální cíl (viz. minulý díl) a logy jsou předávány službě syslog s hodnotou kern* a s nastaveným prefixem.
$IPTABLES -N logdrop
$IPTABLES -A logdrop -m limit --limit 5/h --limit-burst 3 -j LOG --log-prefix "Rezervovana adresa: "
$IPTABLES -A logdrop -j DROP
Druhým řetězcem je IN_FW. Ten kontroluje, zda zdrojová adresa packetů je z nějakého vnitřního rozsahu. Další rozsahy lze přidat podle http://www.iana.com/assignments/ipv4-address-space
$IPTABLES -N IN_FW
$IPTABLES -A IN_FW -s 192.168.0.0/16 -j logdrop
$IPTABLES -A IN_FW -s 10.0.0.0/8 -j logdrop
$IPTABLES -A IN_FW -s 172.16.0.0/12 -j logdrop
$IPTABLES -A IN_FW -s 96.0.0.0/4 -j logdrop
Nakonfigurujeme si další řetězec pro ochranu přes syn zahlcením. Jedná se o tzv. techniku syn-flood, kdy útočník neustále navazuje na náš server nová spojení, dokud nedojde k DoS (odepření služby). Podle daného limitu navázání spojení přijmeme (druhé pravidlo - povolíme 4 syn za vteřinu), nebo zahodíme (třetí pravidlo).
$IPTABLES -N syn-flood
$IPTABLES -A syn-flood -m limit --limit 1/s --limit-burst 4 -j RETURN
$IPTABLES -A syn-flood -j DROP
Optimalizace datových cest - prerouting
Nastavíme si TOS optimalizaci cest (viz. minulý díl)
$IPTABLES -t mangle -A PREROUTING -p tcp --sport ssh -j TOS --set-tos Minimize-Delay
$IPTABLES -t mangle -A PREROUTING -p tcp --dport ssh -j TOS --set-tos Minimize-Delay
$IPTABLES -t mangle -A PREROUTING -p tcp --sport ftp -j TOS --set-tos Minimize-Delay
$IPTABLES -t mangle -A PREROUTING -p tcp --dport telnet -j TOS --set-tos Minimize-Delay
$IPTABLES -t mangle -A PREROUTING -p tcp --sport ftp-data -j TOS --set-tos Maximize-Throughput
Forward
V tomto řetězci si nastavujeme pravidla pro packety, které jsou předávány mezi rozhraními.
Zahodíme ty packety, které navazují spojení, ale nemají nastavený příznak SYN
$IPTABLES -A FORWARD -p tcp ! --syn -m state --state NEW -j DROP
Zalogujeme a zamezíme portscan s nastavenými příznaky SYN a FIN. Portscan je častá technika útočníků, kteří se tímto snaží zjistit, které porty jsou otevřeny.
$IPTABLES -A FORWARD -p tcp -i $INET_IFACE --tcp-flags SYN,FIN SYN,FIN -j LOG -m limit --limit 10/m --log-prefix="bogus packet"
$IPTABLES -A FORWARD -p tcp -i $INET_IFACE --tcp-flags SYN,FIN SYN,FIN -j DROP
Odstraníme packety s privátní zdrojovou adresou na vnějším rozhraní pomocí našeho řetězce.
$IPTABLES -A FORWARD -i $INET_IFACE -j IN_FW
Pokud nechceme nijak omezovat přístup vnitřní sítě do internetu, pak povolíme předávání pro všechny packety, které vstupují vnitřním rozhraním.
$IPTABLES -A FORWARD -i $LAN1_IFACE -j ACCEPT
Předávání z vnější do vnitřní sítě povolíme jenom pro dříve navázaná spojení. Zde se projevuje síla stavového firewallu.
$IPTABLES -A FORWARD -i $INET_IFACE -o $LAN1_IFACE -m state --state ESTABLISHED,RELATED -j ACCEPT
Dále můžeme třeba logovat packety, které byly zahozeny.
$IPTABLES -A FORWARD -m limit --limit 12/h -j LOG --log-prefix "forward drop: "
Input
Zde si nastavíme pravidla pro přístup na náš server. Nejprve zahodíme ty packety, které navazují spojení, ale nemají nastavený příznak SYN
$IPTABLES -A INPUT -p tcp ! --syn -m state --state NEW -j DROP
Opět zakážeme portscan s nastavenými příznaky SYN a FIN.
$IPTABLES -A INPUT -p tcp -i $INET_IFACE --tcp-flags SYN,FIN SYN,FIN -j LOG -m limit --limit 10/m --log-prefix="bogus packet"
$IPTABLES -A INPUT -p tcp -i $INET_IFACE --tcp-flags SYN,FIN SYN,FIN -j DROP
Opět se zbavíme privátních adres na veřejném rozhraní
$IPTABLES -A INPUT -i $INET_IFACE -j IN_FW
Odfiltrujeme znova syn-flooding
$IPTABLES -A INPUT -i $INET_IFACE -p tcp --syn -j syn-flood
Stejně tak odfiltrujeme pokusy o zahlcení icmp zprávami.
$IPTABLES -A INPUT -i $INET_IFACE -p icmp -j syn-flood
Nyní můžeme povolovat přístup k jednotlivým službám na našem serveru. Povolíme služby FTP, SSH ,SMTP, DNS (UDP pro dotazy, TCP pro větší zabezpečené přenosy mezi DNS servery) a WWW. Necháme si možnost dalšího rozšíření o proxy relaying, IMAP, HTTPS a rsync.
$IPTABLES -A INPUT -i $INET_IFACE -p TCP --dport 21 -j ACCEPT #FTP server
$IPTABLES -A INPUT -i $INET_IFACE -p TCP --dport 22 -j ACCEPT #SSH server
$IPTABLES -A INPUT -i $INET_IFACE -p TCP --dport 25 -j ACCEPT #SMTP server
$IPTABLES -A INPUT -i $INET_IFACE -p UDP --dport 53 -j ACCEPT #DNS server UDP
$IPTABLES -A INPUT -i $INET_IFACE -p TCP --dport 53 -j ACCEPT #DNS server TCP
$IPTABLES -A INPUT -i $INET_IFACE -p TCP --dport 80 -j ACCEPT #WWW server
$IPTABLES -A INPUT -i $INET_IFACE -p TCP --dport 110 -j ACCEPT #POP3 server
#$IPTABLES -A INPUT -i $INET_IFACE -p TCP --dport 3128 -j ACCEPT #proxy server
#$IPTABLES -A INPUT -i $INET_IFACE -p TCP --dport 143 -j ACCEPT #IMAP server
#$IPTABLES -A INPUT -i $INET_IFACE -p TCP --dport 443 -j ACCEPT #HTTPS server
#$IPTABLES -A INPUT -i $INET_IFACE -p TCP --dport 873 -j ACCEPT #rsync server
Službu auth využívají systémy, aby zjistily, ke komu dané připojení patří. Není dobré ji jenom odmítnout, protože to může způsobit prodlevy při navazování některých spojení. Proto ji odmítneme, ale zašleme chybovou odpověď.
$IPTABLES -A INPUT -i $INET_IFACE -p TCP --dport 113 -m limit --limit 12/h -j LOG
$IPTABLES -A INPUT -i $INET_IFACE -p TCP --dport 113 -j REJECT --reject-with tcp-reset #AUTH server
Propustíme na náš server ping.
$IPTABLES -A INPUT -i $INET_IFACE -p ICMP --icmp-type echo-request -j ACCEPT
Nebudeme omezovat loopback rozhraní, ušetříme si tím spoustu problémů.
$IPTABLES -A INPUT -i $LO_IFACE -j ACCEPT
Povolíme packety z vnitřní sítě, pokud směřují na jedno z našich rozhraní.
$IPTABLES -A INPUT -i $LAN1_IFACE -d $LAN1_IP -j ACCEPT
$IPTABLES -A INPUT -i $LAN1_IFACE -d $INET_IP -j ACCEPT
Povolíme broadcasty na vnitřním rozhraní.
$IPTABLES -A INPUT -i $LAN1_IFACE -d $LAN1_BCAST -j ACCEPT
Další řádek se zabývá DHCP běžícím na klientu od Microsoftu. Musíme povolit udp port 67, jinak by pro počítače nefungovala DHCP služba správně.
$IPTABLES -A INPUT -i $LAN1_IFACE -p udp --dport 67 -j ACCEPT
Povolíme packety od navázaných spojení.
$IPTABLES -A INPUT -d $INET_IP -m state --state ESTABLISHED,RELATED -j ACCEPT
Všechno ostatní je zakázáno a můžeme si tyto packety zalogovat. Zahozeny budou implicitní politikou.
$IPTABLES -A INPUT -m limit --limit 12/h -j LOG --log-prefix "INPUT drop: "
Output
Optimalizujeme datové cesty odcházející z našeho serveru.
$IPTABLES -t mangle -A OUTPUT -o $INET_IFACE -p tcp --sport ssh -j TOS --set-tos Minimize-Delay
$IPTABLES -t mangle -A OUTPUT -o $INET_IFACE -p tcp --dport ssh -j TOS --set-tos Minimize-Delay
$IPTABLES -t mangle -A OUTPUT -o $INET_IFACE -p tcp --sport ftp -j TOS --set-tos Minimize-Delay
$IPTABLES -t mangle -A OUTPUT -o $INET_IFACE -p tcp --dport ftp -j TOS --set-tos Minimize-Delay
$IPTABLES -t mangle -A OUTPUT -o $INET_IFACE -p tcp --dport telnet -j TOS --set-tos Minimize-Delay
$IPTABLES -t mangle -A OUTPUT -o $INET_IFACE -p tcp --sport ftp-data -j TOS --set-tos Maximize-Throughput
Povolíme odeslat ze serveru vše, co má naše IP adresy.
$IPTABLES -A OUTPUT -s $LO_IP -j ACCEPT
$IPTABLES -A OUTPUT -s $LAN1_IP -j ACCEPT
$IPTABLES -A OUTPUT -s $INET_IP -j ACCEPT
Povolíme DHCP broadcasty na vnitřním rozhraní
$IPTABLES -A OUTPUT -o $LAN1_IFACE -p UDP --dport 68 --sport 67 -j ACCEPT
Ostatní packety zahodíme, můžeme je logovat.
$IPTABLES -A OUTPUT -j LOG --log-prefix "OUTPUT drop: "
Nyní už stačí jenom nechat spouštět skript spolu s počítačem a firewall je hotov.
Závěr
Dnes jsme si nakonfigurovali a zprovoznili firewall iptables. Pro základní účely to může stačit. Pro ty náročnější z vás se v příštím dílu budeme zabývat již komplikovanějším nastavením a to přesměrováním portů do vnitřní sítě a přesměrování veřejné adresy.
Autor: Radim Poloch