Skip to content

Docker a firewall

Martin Skalicky edited this page Aug 4, 2026 · 1 revision

Docker a firewall

Tohle je nejdůležitější stránka celé sekce o firewallu. Popisuje chování, které skoro nikdo nečeká a které tiše otevře služby do internetu.

Problém v jedné větě

Když publikuješ port přes Docker, ufw ho nezablokuje.

ufw default deny incoming
ufw enable
docker run -d -p 8080:80 nginx

Port 8080 je teď dostupný z internetu. ufw status tvrdí, že příchozí provoz je zakázaný. Obojí je pravda a to je celý ten problém.

Proč se to děje

Docker si sám zapisuje pravidla do netfilteru a dělá to v místě, kam se paket dostane dřív, než na něj sáhne ufw.

flowchart LR
    P[paket na port 8080] --> PRE[PREROUTING<br/>Docker sem dá DNAT]
    PRE --> R{pro tenhle stroj?}
    R -->|ne, je pro kontejner| FWD[FORWARD<br/>DOCKER-USER, DOCKER]
    R -->|ano| INP[INPUT<br/>tady sedí ufw]
    FWD --> K[kontejner]
Loading

Docker udělá DNAT už v PREROUTING, čímž z paketu udělá provoz skrz stroj místo provozu na stroj. Ten pak jde přes FORWARD, kde ufw žádná pravidla nemá — ufw pracuje v INPUT.

Souvislosti jsou v Linux firewall.

Není to chyba Dockeru ani ufw. Je to důsledek toho, že spolu nekomunikují a oba mají pravdu ze svého pohledu.

Ověř si to

Než tomu uvěříš, změř to. Z jiného stroje nebo z mobilu na datech:

nmap -Pn -p 8080 adresa.serveru

Nebo se podívej na skutečná pravidla místo na to, co tvrdí ufw:

iptables -L -n -v | grep -A20 DOCKER
nft list ruleset | grep -i docker

Řešení 1: nepublikuj na všechna rozhraní

Nejjednodušší a nejúčinnější. Řekni Dockeru, aby port vystavil jen na loopback:

docker run -d -p 127.0.0.1:8080:80 nginx

V Compose:

services:
  web:
    image: nginx
    ports:
      - "127.0.0.1:8080:80"

Služba je pak dostupná jen ze samotného stroje. Ven ji pustíš přes reverse proxy, která běží taky na tom stroji a je zajištěná normálně přes ufw.

Tohle je správná odpověď pro naprostou většinu případů. Nic dalšího řešit nemusíš.

Zapamatuj si rozdíl:

Zápis Dostupné z
-p 8080:80 odkudkoliv, včetně internetu
-p 127.0.0.1:8080:80 jen z tohoto stroje
-p 192.168.1.5:8080:80 jen přes konkrétní rozhraní
expose: 80 (Compose) jen z jiných kontejnerů

Řešení 2: DOCKER-USER

Docker záměrně nechává prázdný řetězec DOCKER-USER, který se vyhodnocuje před jeho vlastními pravidly. Sem patří tvoje omezení.

# povolit jen z domácí sítě a z VPN
iptables -I DOCKER-USER -i eth0 ! -s 192.168.1.0/24 -j DROP
iptables -I DOCKER-USER -i eth0 -s 10.10.0.0/24 -j RETURN

Pravidlo přežije restart Dockeru, ale ne restart stroje — ulož ho stejně jako ostatní, viz iptables.

Na IPv6 nezapomeň, je to samostatný řetězec:

ip6tables -I DOCKER-USER -i eth0 -j DROP

Řešení 3: vypnout Dockeru správu iptables

/etc/docker/daemon.json
{
  "iptables": false
}

Nedělej to, pokud přesně nevíš proč. Kontejnerům tím rozbiješ odchozí síť a musíš si NAT a forwarding napsat celý ručně. Je to legitimní volba na routeru, kde firewall stavíš od základu, a špatná volba všude jinde.

Compose a expose

Když spolu kontejnery komunikují ve stejné síti Compose, nepotřebují publikované porty vůbec. Oslovují se jménem služby:

services:
  app:
    image: mojeapp
    expose:
      - "3000"
  db:
    image: postgres
    # žádné ports, databáze není zvenku vidět
  proxy:
    image: caddy
    ports:
      - "80:80"
      - "443:443"

Aplikace se na databázi připojí přes db:5432. Ven čouhá jen proxy.

Tohle je zdravý vzor: jediný kontejner s publikovanými porty je reverse proxy. Všechno ostatní zůstane vnitřní. Viz sítě v Dockeru.

Kontrolní seznam

Když ti na stroji běží Docker:

  1. Zjisti, co je skutečně vystavené: docker ps --format "table {{.Names}}\t{{.Ports}}"
  2. Cokoliv ve tvaru 0.0.0.0:port-> je veřejné
  3. Ověř zvenku pomocí nmap
  4. Přidej 127.0.0.1: všude, kde služba nemá být veřejná
  5. Zkontroluj IPv6 zvlášť

Ten první příkaz stojí za spuštění hned teď. Většina lidí je překvapená.

Proxmox a další

Stejný problém, jiný viník. Proxmox, libvirt a další systémy, které dělají virtuální sítě, si taky zapisují vlastní pravidla a ufw status je neukáže.

Univerzální pravidlo: věř nft list ruleset, ne nadstavbě. Viz Proxmox a sítě.

Clone this wiki locally