markdown
iptables.md
markdown
# iptables Klasika, kterou najdeš ve všech starších návodech. Na moderních distribucích je to už jen [překladová vrstva nad nftables](Linux-firewall), ale příkazy fungují a znát je se vyplatí — velká část internetu je pořád psaná v nich. Pokud stavíš něco nového, zvaž rovnou [nftables](nftables). Tahle stránka je hlavně proto, abys rozuměl tomu, co už běží. ## Struktura Tři úrovně: **tabulky** obsahují **řetězce** a ty obsahují **pravidla**. | Tabulka | K čemu ||---|---|| `filter` | povolit a zakázat. Výchozí, když tabulku neuvedeš. || `nat` | přepis adres, DNAT a SNAT || `mangle` | úpravy hlaviček, TTL, značkování || `raw` | obejití sledování stavu | Doma potřebuješ `filter` a `nat`. Zbytek téměř nikdy. Řetězce a to, kudy paket letí, jsou popsané v [Linux firewall](Linux-firewall). ## Čtení současného stavu ```bashiptables -L -n -v --line-numbers # tabulka filteriptables -t nat -L -n -v # tabulka natiptables-save # všechno v podobě k obnovení``` Přepínač `-n` je zásadní — bez něj se iptables snaží překládat IP na jména a při každém výpisu čekáš. Sloupce `pkts` a `bytes` ukazují, kolik provozu daným pravidlem prošlo. Neocenitelné při ladění: pravidlo s nulou se nikdy nepoužilo, což obvykle znamená, že je špatně umístěné nebo že ho něco výš zachytilo dřív. ## Základní sada pro server ```bash# výchozí politikaiptables -P INPUT DROPiptables -P FORWARD DROPiptables -P OUTPUT ACCEPT # nezablokovat sám sebeiptables -A INPUT -i lo -j ACCEPT # stavovost: odpovědi na vlastní spojeníiptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPTiptables -A INPUT -m conntrack --ctstate INVALID -j DROP # ping (užitečné pro diagnostiku)iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT # službyiptables -A INPUT -p tcp --dport 22 -j ACCEPTiptables -A INPUT -p tcp --dport 80 -j ACCEPTiptables -A INPUT -p tcp --dport 443 -j ACCEPT``` Pořadí je podstatné. **Pravidla se vyhodnocují shora dolů a první shoda vyhraje.** Řádek s `lo` musí být nahoře, jinak si rozbiješ lokální komunikaci mezi procesy. ## Omezení podle zdroje SSH jen z domácí sítě a z VPN: ```bashiptables -A INPUT -p tcp --dport 22 -s 192.168.1.0/24 -j ACCEPTiptables -A INPUT -p tcp --dport 22 -s 10.10.0.0/24 -j ACCEPTiptables -A INPUT -p tcp --dport 22 -j DROP``` ## NAT Masquerade, tedy překlad na adresu odchozího rozhraní. Tohle dělá router: ```bashiptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE``` DNAT, tedy [port forwarding](NAT-a-port-forwarding) dovnitř: ```bashiptables -t nat -A PREROUTING -i eth0 -p tcp --dport 443 -j DNAT --to-destination 192.168.1.10:443iptables -A FORWARD -p tcp -d 192.168.1.10 --dport 443 -j ACCEPT``` Ta druhá řádka se zapomíná pořád. DNAT jen přepíše adresu — paket pak musí ještě projít řetězcem FORWARD, kde ho výchozí politika DROP zahodí. A aby forwarding vůbec fungoval: ```bashsysctl -w net.ipv4.ip_forward=1echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf``` ## Vkládání na správné místo `-A` přidává na konec, `-I` na začátek. Když máš na konci DROP a použiješ `-A`, tvoje nové pravidlo se nikdy neuplatní. ```bashiptables -I INPUT 3 -p tcp --dport 8080 -j ACCEPT # vloží na třetí poziciiptables -D INPUT 3 # smaže třetí pravidlo``` Čísla zjistíš přes `--line-numbers`. ## Přetrvání po restartu Pravidla v paměti zmizí při restartu. Na Debianu a Ubuntu: ```bashapt install iptables-persistentnetfilter-persistent save``` Uloží do `/etc/iptables/rules.v4` a `rules.v6`. Ručně: ```bashiptables-save > /etc/iptables/rules.v4iptables-restore < /etc/iptables/rules.v4``` ## IPv6 je zvlášť Tohle je klasická díra. `iptables` řeší jen IPv4. Pro IPv6 je samostatný příkaz: ```baship6tables -L -n -v``` Server, který má IPv6 a zajištěný jen `iptables`, je z internetu otevřený dokořán. Každé pravidlo, které píšeš, si napiš i v `ip6tables` — nebo použij [nftables](nftables), který umí obojí naráz. ## Logování ```bashiptables -A INPUT -j LOG --log-prefix "IPTABLES-DROP: " --log-level 4iptables -A INPUT -j DROP``` Log pravidlo musí být **před** tím zahazovacím, jinak se nic nezaloguje. Zprávy jdou do `journalctl -k` nebo `/var/log/kern.log`. Nenechávej to zapnuté napořád na pravidle chytajícím provoz z internetu — zaplníš disk během dní. ## Když se to chová divně **Pravidlo nemá žádné pakety** (`-v` ukazuje nuly) → něco výš ho zachytilo dřív, nebo je paket ve špatném řetězci. **Funguje to na hostiteli, ale ne v kontejneru** → Docker si přidává vlastní pravidla a tvoje obchází. Viz [Docker a firewall](Docker-a-firewall). **Po restartu je všechno pryč** → chybí persistence. **Funguje IPv4, ale ne IPv6** → viz výše. Systematický postup je v [diagnostice](Diagnostika).