# 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

```bash
iptables -L -n -v --line-numbers          # tabulka filter
iptables -t nat -L -n -v                  # tabulka nat
iptables-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í politika
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT

# nezablokovat sám sebe
iptables -A INPUT -i lo -j ACCEPT

# stavovost: odpovědi na vlastní spojení
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -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žby
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -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:

```bash
iptables -A INPUT -p tcp --dport 22 -s 192.168.1.0/24 -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -s 10.10.0.0/24 -j ACCEPT
iptables -A INPUT -p tcp --dport 22 -j DROP
```

## NAT

Masquerade, tedy překlad na adresu odchozího rozhraní. Tohle dělá router:

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

DNAT, tedy [port forwarding](NAT-a-port-forwarding) dovnitř:

```bash
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 443 -j DNAT --to-destination 192.168.1.10:443
iptables -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:

```bash
sysctl -w net.ipv4.ip_forward=1
echo "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í.

```bash
iptables -I INPUT 3 -p tcp --dport 8080 -j ACCEPT   # vloží na třetí pozici
iptables -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:

```bash
apt install iptables-persistent
netfilter-persistent save
```

Uloží do `/etc/iptables/rules.v4` a `rules.v6`.

Ručně:

```bash
iptables-save > /etc/iptables/rules.v4
iptables-restore < /etc/iptables/rules.v4
```

## IPv6 je zvlášť

Tohle je klasická díra. `iptables` řeší jen IPv4. Pro IPv6 je samostatný příkaz:

```bash
ip6tables -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í

```bash
iptables -A INPUT -j LOG --log-prefix "IPTABLES-DROP: " --log-level 4
iptables -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).
