Moderní linuxový firewall nftables si získal srdce mnoha administrátorů. Postupně nahrazuje zastaralý a těžkopádný iptables. Přestože je nftables s námi už řadu let – psalo se o něm v seriálech na Rootu od Petra Krčmáře a objevoval se i na LinuxDays – stále ne všechno software se bez iptables obejde. Typickým příkladem je Docker. Pokud do Googlu zadáte dotaz docker nftables, nenajdete jasnou a praktickou odpověď. V tomto článku vám proto ukážu, jak si trvale vygenerovat pravidla pro vaši Docker aplikaci.
Pro tyto účely použiju Matomo – moderní OpenSource náhradu Google Analytics. Pravidla se naučíme uložit do samostatného souboru a includovat k našim existujícím nftables pravidlům. Následně zakážeme dockeru vytvářet iptables pravidla. Až budete instalovat další aplikaci, budete už umět si ty pravidla odchytit a použít.
Hlavní výhody moderního firewallu nftables ve zkratce:
- Sjednocení: Nahrazuje a sjednocuje iptables, ip6tables, arptables a ebtables do jediného konzistentního frameworku.
- Moderní a flexibilní syntaxe: Umožňuje psát přehlednější a efektivnější pravidla, včetně pokročilých datových struktur (sady, mapy, proměnné).
- Atomické operace: Změny pravidel se aplikují okamžitě a konzistentně, bez rizika dočasného nezabezpečeného stavu.
- Vyšší výkon a efektivita: Optimalizováno pro moderní linuxová jádra, což vede k nižší systémové zátěži a lepšímu využití prostředků.
- Snadnější správa komplexních pravidel: Díky pokročilým funkcím je správa rozsáhlých a složitějších firewallových konfigurací přehlednější a méně náchylná k chybám.
Co se stane, když používáte iptables s dockerem a restartujete nftables
Je možné používat iptables i nftables současně, protože dnešní iptables ve skutečnosti běží nad nftables pomocí kompatibilitní vrstvy (iptables-nft), která rozumí původním iptables příkazům.
Na serveru, kde neběží jen Docker, ale řešíte i celkovou bezpečnost, není dobré míchat nftables a iptables. Pokud totiž dojde k restartu nftables (například při ručním doplnění pravidla nebo po restartu přes systemd), Docker v tu chvíli přestane fungovat. Jeho pravidla totiž zmizí a znovu se zavedou teprve po restartu služby docker.service. Důvod je jednoduchý – při každém restartu nftables se nejprve kompletně vymažou všechna existující pravidla.
#!/usr/sbin/nft -f
flush ruleset
Code language: JavaScript (javascript)
Problém není ani tak v kompatibilitní vrstvě iptables-nft, ale spíše v pohodlnosti administrátorů. Ti si totiž zvykli, že Docker při startu automaticky nastaví potřebná pravidla ve firewallu a vše tak zdánlivě funguje bez jejich zásahu.
Pravidla, která Docker nastaví při svém startu, nemusí po delší době běhu serveru fungovat správně. Pokud dojde k restartu nftables, kontejnery si často přestanou mezi sebou rozumět a aplikace v nich přestanou fungovat.
Jak lze situaci s dockerem a nftables řešit?
Docker při svém startu vytváří iptables pravidla (pokud mu to výslovně nezakážeme v /etc/docker/daemon.json) a zavádí je do systému. Součástí tohoto procesu je i vytváření bridge rozhraní, která dostávají náhodné názvy a při každém dalším spuštění se mohou jmenovat jinak. Řešením je používat pevně určené názvy rozhraní, například pomocí docker-compose.yml. Tím zajistíme, že Docker vygeneruje konzistentní pravidla, která můžeme znovu použít i po restartu serveru, aniž bychom se museli spoléhat na jejich nové generování.
Iptables pravidla, která Docker vygeneruje, lze díky kompatibilní vrstvě iptables-nft zobrazit jako nativní nftables pravidla a uložit je do samostatného souboru. Tento soubor pak můžeme jednoduše includovat do naší hlavní konfigurace nftables. Díky tomu máme jistotu, že i po restartu nftables se firewall nastaví přesně podle námi schválené a uložené konfigurace.
Krok za krokem, jak probíhá instalace Matomo do dockeru s nftables
- Nachystáte si reverzní proxy. Doporučuji Caddy.
- Dočasně povolíte iptables v `/etc/docker/daemon.json` (`“iptables“: true`).
- Vytvoříte `docker-compose.yml` pro Matomo se stabilním jménem bridge (např. `br-matomo`).
- Nainstalujte Matomo (např. spuštěním docker-compose a následným webovým průvodcem instalace)
- Zastavíte ostatní kontejnery a necháte jen `matomo` a `matomo-db`.
- Do `/etc/nftables.conf` přidáte `include „/etc/nftables.d/*.conf“`, vytvoříte adresář `/etc/nftables.d` a prázdný soubor `/etc/nftables.d/3_docker_matomo.conf`.
- Vyresetujete nftables pravidla (`nft flush ruleset`) – pozor, tím na chvíli vypnete firewall.
- Restartujete Docker.
- Přesměrujete aktuální pravidla (která vytvořil Docker při restartu) do souboru:
`nft list ruleset > /etc/nftables.d/3_docker_matomo.conf`.
Doporučeno projít a případně pročistit. - Restartujete nftables (`systemctl restart nftables`).
- Ověříte `nft list ruleset`, že máte jak své původní pravidla, tak i nově přidaná pravidla pro Matomo.
- V `/etc/docker/daemon.json` zakážete iptables (`“iptables“: false`) a restartujete Docker (`systemctl restart docker`).
- Restartujete server a ověříte, že vše funguje.
Reverzní proxy (Caddy) a proč nevázat kontejnery na 0.0.0.0
Pro produkční nasazení Matoma (a obecně webových aplikací v Dockeru) je vhodné dát před aplikaci reverzní proxy. Doporučuji Caddy: automaticky řeší HTTPS (Let’s Encrypt), HTTP/2/3 a bezpečnostní hlavičky. Zároveň je dobrá praxe nevázat kontejnery na všechna rozhraní (0.0.0.0), ale na konkrétní IP – konfigurace je předvídatelnější a bezpečnější.
Většina ukázek docker-compose mapuje jen porty:
ports:
– „8080:80“
Tím Docker naslouchá na všech rozhraních (0.0.0.0). Já preferuji vázat službu na konkrétní IP (např. 127.0.0.2):
ports:
– target: 80
published: 8080
protocol: tcp
mode: host
host_ip: „127.0.0.2“
Výhody:
- služba není „otevřená všude“, ale jen na zvolené IP,
- reverzní proxy ví přesně, kam směrovat (žádné překvapení po restartu),
- firewall/nftables pravidla se píší a udržují lépe (deterministická adresa i porty).
- je možné používat různé aplikace používající stejné porty na různých IP adresách
Důležité: IP adresa a port v Caddyfile musí odpovídat tomu, co máte v docker-compose. Pokud v compose běží Matomo na 127.0.0.2:8080, stejnou adresu použijte v reverse_proxy.
Poznámky:
- DNS A/AAAA záznamy směřujte na veřejnou IP serveru, Caddy si certifikát obstará sám. Nepoužívejte subdoménu se jménem matomo, stats, analytics, piwik a pod. Nepoužívejte CNAME záznam. Používejte subdoménu, na webu, na kterém měříte, ale z jejího názvu by nemělo nic nasvědčovat tomu, že slouží k měření.
- Pokud používáte IPv6, můžete analogicky vázat i na vyhrazenou ::1/lo adresu (nebo jinou lokální v6), případně v Caddy reverse_proxy použít http://[::1]:8080.
- Kdo nechce bind na 127.0.0.2, může zvolit jinou lokální adresu (např. 127.0.0.10); důležité je mít shodu compose ↔ Caddy ↔ nftables pravidla.
- Adresu si před použitím opingujte, ať víte, že tam fakt je. Přes ip a s nemusí být vidět, a přesto lze tyto adresy použít.
/etc/caddy/Caddyfile
Příklad konfigurace webserveru Caddy:
# The Caddyfile is an easy way to configure your Caddy web server.
#
# Unless the file starts with a global options block, the first
# uncommented line is always the address of your site.
#
# To use your own domain name (with automatic HTTPS), first make
# sure your domain's A/AAAA DNS records are properly pointed to
# this machine's public IP, then replace ":80" below with your
# domain name.
{
servers {
protocols h3 h2 h2c h1
trusted_proxies static private_ranges
log_credentials
}
}
(logging) {
log {
level DEBUG
output file /var/log/caddy/access.log {
roll_size 1gb
roll_keep 1
roll_keep_for 720h
}
}
}
(canonical_domain) {
@canonicalPath {
not query
}
rewrite @canonicalPath {http.request.uri.path}
header {
Link "<https://{args[0]}{http.request.uri.path}>; rel=\"canonical\""
}
}
matomo.example.com {
encode zstd gzip
# Backend běží na HTTP/80 → vynucený HTTP transport
reverse_proxy /* http://127.0.0.2:8080 {
transport http {
}
}
import logging
header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
header Content-Security-Policy "upgrade-insecure-requests;"
header Referrer-Policy "no-referrer-when-downgrade"
header Access-Control-Allow-Origin "https://{host}"
import canonical_domain "{host}"
}
m1.example1.com m1.example2.cz {
encode zstd gzip
# Backend běží na HTTP/80 → vynucený HTTP transport
reverse_proxy /* http://127.0.0.2:8080 {
transport http {
}
}
import logging
header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
header Content-Security-Policy "upgrade-insecure-requests;"
header Referrer-Policy "no-referrer-when-downgrade"
header Access-Control-Allow-Origin "https://{host}"
import canonical_domain "{host}"
@js path /matomo.js /m.js
handle @js {
uri replace /m.js /matomo.js
reverse_proxy 127.0.0.2:8080
}
@hit path /matomo.php /t
handle @hit {
uri replace /t /matomo.php
reverse_proxy 127.0.0.2:8080
}
# cokoliv jiného nevracej (zabrání UI přes tracker host)
respond 404
}
Code language: PHP (php)
/etc/docker/daemon.json
Slouží pro konfiguraci Dockeru, například v něm nastavujeme, zda má použít iptables pro generování pravidel. Dočasně povolíme iptables => vygenerujeme pravidla => zakážeme. Takto vypadá soubor na jednom z mých serverů:
{
"experimental": true,
"iptables": false,
"ip6tables": false,
"dns": ["1.1.1.1"],
"dns-search": []
}
Code language: JSON / JSON with Comments (json)
~/docker/matomo/docker-compose.yml
Soubor docker-compose.yml zajišťuje, aby se Matomo při startu spustilo správně. Podle potřeby si v něm upravte například hesla a další parametry.
services:
db:
image: mariadb:11
container_name: matomo-db
command: >-
--max-allowed-packet=64M
--innodb-log-file-size=512M
--skip-name-resolve
restart: unless-stopped
volumes:
- db_data:/var/lib/mysql
- ./my.cnf:/etc/mysql/conf.d/my.cnf:ro
tmpfs:
- /tmp:size=1g,noexec,nosuid,nodev
ulimits:
nofile:
soft: 1048576
hard: 1048576
environment:
MYSQL_ROOT_PASSWORD: KrutoPrisneHeslo123
MYSQL_DATABASE: matomo
MYSQL_USER: matomo
MYSQL_PASSWORD: NejkrutesjiZnejkrutejsich357
networks: [net]
dns:
- 1.1.1.1
- 8.8.8.8
matomo:
image: matomo:latest
container_name: matomo
restart: unless-stopped
ports:
- target: 80
published: 8080
protocol: tcp
mode: host
host_ip: "127.0.0.2"
environment:
MATOMO_DATABASE_HOST: db
MATOMO_DATABASE_ADAPTER: mysql
MATOMO_DATABASE_TABLES_PREFIX: matomo_
MATOMO_DATABASE_USERNAME: matomo
MATOMO_DATABASE_PASSWORD: NejkrutesjiZnejkrutejsich357
MATOMO_DATABASE_DBNAME: matomo
volumes:
- matomo_data:/var/www/html
networks: [net]
dns:
- 1.1.1.1
- 8.8.8.8
volumes:
db_data:
name: matomo_db_data
matomo_data:
name: matomo_matomo_data
networks:
net:
driver: bridge
driver_opts:
com.docker.network.bridge.name: br-matomo # stálý název
ipam:
driver: default
config:
- subnet: 172.30.0.0/16
gateway: 172.30.0.1
Code language: YAML (yaml)
/etc/nftables.d/3_docker_matomo.conf
Do tohoto souboru uložíte nftables pravidla pro Matomo. Pokud použijete můj docker-compose.yml, měla by fungovat beze změny.
table ip nat {
chain DOCKER {
iifname "docker0" counter return
iifname "br-matomo" counter return
ip daddr 127.0.0.2 iifname != "br-matomo" tcp dport 8080 counter dnat to 172.30.0.3:80
}
chain PREROUTING {
type nat hook prerouting priority dstnat; policy accept;
fib daddr type local counter jump DOCKER
}
chain OUTPUT {
type nat hook output priority dstnat; policy accept;
ip daddr != 127.0.0.0/8 fib daddr type local counter jump DOCKER
}
chain POSTROUTING {
type nat hook postrouting priority srcnat; policy accept;
ip saddr 172.17.0.0/16 oifname != "docker0" counter masquerade
ip saddr 172.30.0.0/16 oifname != "br-matomo" counter masquerade
}
}
table ip filter {
chain DOCKER {
ip daddr 172.30.0.3 iifname != "br-matomo" oifname "br-matomo" tcp dport 80 counter accept
iifname != "br-matomo" oifname "br-matomo" counter drop
iifname != "docker0" oifname "docker0" counter drop
}
chain DOCKER-FORWARD {
counter jump DOCKER-CT
counter jump DOCKER-ISOLATION-STAGE-1
counter jump DOCKER-BRIDGE
iifname "br-matomo" counter accept
iifname "docker0" counter accept
}
chain DOCKER-BRIDGE {
oifname "br-matomo" counter jump DOCKER
oifname "docker0" counter jump DOCKER
}
chain DOCKER-CT {
oifname "br-matomo" ct state related,established counter accept
oifname "docker0" ct state related,established counter accept
}
chain DOCKER-ISOLATION-STAGE-1 {
iifname "br-matomo" oifname != "br-matomo" counter jump DOCKER-ISOLATION-STAGE-2
iifname "docker0" oifname != "docker0" counter jump DOCKER-ISOLATION-STAGE-2
}
chain DOCKER-ISOLATION-STAGE-2 {
oifname "docker0" counter drop
oifname "br-matomo" counter drop
}
chain FORWARD {
type filter hook forward priority filter; policy accept;
counter jump DOCKER-USER
counter jump DOCKER-FORWARD
}
chain DOCKER-USER {
}
}
table ip raw {
chain PREROUTING {
type filter hook prerouting priority raw; policy accept;
ip daddr 172.30.0.2 iifname != "br-matomo" counter drop
ip daddr 172.30.0.3 iifname != "br-matomo" counter drop
ip daddr 127.0.0.2 iifname != "lo" tcp dport 8080 counter drop
}
}
Code language: JavaScript (javascript)
Líbil se vám článek? Sdílejte ho dál.
Potřebujete Matomo na svůj server? Ozvěte se.
Hledáte správce, který se vám bude starat o servery? Klidně mě kontaktujte.

Kdo jsem:
IT nadšenec žijící v Kladně, system engineer, sysadmin, správce informačních systémů.
Proč jsem si založil tento web: někdo si píše deníček, někdo hraje hry, mne linux a svobodný software nepouští ani ve volném čase. Takže sem občas hodím nějakou svojí poznámku, která někomu možná pomůže.
Navíc, kdyby někdo potřeboval pomoc, tak mne může díky webu najít.
S čím vám mohu pomoci:
Počítač: Rád Vám pomohu s omlazením vašeho počítače (desktopu, notebooku) nebo sestavím nový.
Server: Chcete mít vlastní webový server, NAS (síťové úložiště), VPN server nebo CLOUD? Provozovat e-shop? I v tom vám mohu pomoci.
Domácí síť: Potřebujete vyřešit domácí síť, nejste spokojeni s rychlostí a kvalitou WiFi? Potřebujete připojit zařízení k VPN?
Počítač pro home office: Potřebujete nutně počítač pro home office, ale nechcete platit moc?
Počítač pro online výuku: Jste učitel nebo žák/student, či máte doma někoho, kdo je? Nemáte na čem pracovat? Pomohu vám to vyřešit.
Mám rád počítače a moderní technologie, Linux, zejména distribuce Ubuntu a Debian, CentOS a Rhel mi také nejsou cizí. Ve své práci se starám o více než 6000 linuxových serverů (Ubuntu, Red Hat Enterprise Linux, CentOS).
V minulosti jsem kromě správy linuxových serverů získal zkušenosti i se správou Windows Serverů a instalací a konfigurací linuxových a windowsových terminálů (například na docházku, nebo pro jídelny).
Jiří Meitner
IČ: 73763004
Fyzická osoba zapsaná v živnostenském rejstříku
podpora@ITisLove.cz
WhatsApp
Karla Tomana 830
Kladno
Středočeský kraj
272 04
Česko
Systémový inženýr, Linux administáror, správce informačních systémů, admin, IT specialista, IT help

Napsat komentář