📝 Adequate

iptables / nftables — шпаргалка

Швидка довідка команд Linux firewall. Для теорії та архітектури — Firewall в Linux.

💡 Конвенція
Ubuntu 22.04+ та Debian 12+ за замовчуванням використовують **nftables** (`nft`). `iptables` працює через трансляційний шар `iptables-nft`. Нові правила пиши в nftables, старі скрипти `iptables` продовжують працювати.

Базові поняття

Ланцюг Коли спрацьовує
INPUT Пакет адресований цьому хосту
OUTPUT Пакет згенерований цим хостом
FORWARD Пакет транзитом (потрібен net.ipv4.ip_forward=1)
PREROUTING До рішення про маршрут — DNAT, fwmark
POSTROUTING Після маршрутизації — SNAT, masquerade

iptables — швидкий старт

Перегляд правил

iptables -L -n -v --line-numbers      # filter (default)
iptables -t nat -L -n -v              # таблиця NAT
iptables -t mangle -L -n -v           # mangle (marking, MSS)
iptables -S                           # як команди для backup

Політика за замовчуванням

# Default deny для вхідних, дозволити вихідні та forward
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT

# ПЕРШИМ — дозволити established/related, інакше навіть response на свій запит дропнеться
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -i lo -j ACCEPT
⚠️ Порядок критичний
Перед зміною політики INPUT на DROP ЗАВЖДИ спочатку додайте правило для SSH та `ESTABLISHED,RELATED`, інакше втратите з'єднання.

Типові правила

# SSH з конкретної підмережі
iptables -A INPUT -p tcp --dport 22 -s 10.10.10.0/24 -j ACCEPT

# HTTP / HTTPS публічно
iptables -A INPUT -p tcp --dport 80  -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT

# WireGuard (UDP 51820)
iptables -A INPUT -p udp --dport 51820 -j ACCEPT

# SMTP (outgoing 25), submission 587, IMAPS 993
iptables -A INPUT -p tcp --dport 25  -j ACCEPT
iptables -A INPUT -p tcp --dport 587 -j ACCEPT
iptables -A INPUT -p tcp --dport 993 -j ACCEPT

# ICMP (ping) з лімітом
iptables -A INPUT -p icmp --icmp-type echo-request -m limit --limit 5/s -j ACCEPT

# Дропнути все інше з логуванням
iptables -A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables-drop: "
iptables -A INPUT -j DROP

NAT та masquerade

# Masquerade для LAN → WAN (наприклад, на VPN хабі)
iptables -t nat -A POSTROUTING -s 10.10.10.0/24 -o eth0 -j MASQUERADE

# SNAT з фіксованою адресою (швидше ніж MASQUERADE)
iptables -t nat -A POSTROUTING -s 10.10.10.0/24 -o eth0 -j SNAT --to-source 203.0.113.5

# DNAT (port forwarding) — 443 з публічного IP на внутрішній сервер
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 443 \
  -j DNAT --to-destination 10.10.10.20:443
iptables -A FORWARD -p tcp -d 10.10.10.20 --dport 443 -j ACCEPT

Збереження та відновлення

# Debian/Ubuntu — пакет iptables-persistent
apt install iptables-persistent
netfilter-persistent save           # /etc/iptables/rules.v4
netfilter-persistent reload

# Ручне збереження
iptables-save  > /etc/iptables/rules.v4
ip6tables-save > /etc/iptables/rules.v6

# Відновлення
iptables-restore  < /etc/iptables/rules.v4

nftables — сучасний синтаксис

Перегляд та базова структура

nft list ruleset                      # все
nft list table inet filter            # конкретна таблиця
nft -a list ruleset                   # з handle-ами (для видалення)
nft flush ruleset                     # стерти все (обережно!)

Мінімальний захищений конфіг

Файл /etc/nftables.conf:

#!/usr/sbin/nft -f
flush ruleset

table inet filter {
    chain input {
        type filter hook input priority filter; policy drop;

        iif lo accept
        ct state established,related accept
        ct state invalid drop

        ip protocol icmp icmp type { echo-request } limit rate 5/second accept
        ip6 nexthdr icmpv6 accept

        tcp dport 22    accept comment "SSH"
        tcp dport { 80, 443 } accept comment "HTTP/HTTPS"
        udp dport 51820 accept comment "WireGuard"
    }

    chain forward { type filter hook forward priority filter; policy drop; }
    chain output  { type filter hook output  priority filter; policy accept; }
}

table ip nat {
    chain postrouting {
        type nat hook postrouting priority srcnat; policy accept;
        ip saddr 10.10.10.0/24 oif "eth0" masquerade
    }
}

Активація:

systemctl enable --now nftables
nft -f /etc/nftables.conf
systemctl reload nftables

Редагування "на льоту"

# Додати правило в кінець chain
nft add rule inet filter input tcp dport 8448 accept comment "Matrix federation"

# Вставити на початок
nft insert rule inet filter input position 0 tcp dport 2022 accept

# Видалити за handle
nft -a list chain inet filter input    # знайти handle
nft delete rule inet filter input handle 7

iptables vs nftables — переклад правил

iptables nftables
iptables -A INPUT -p tcp --dport 22 -j ACCEPT nft add rule inet filter input tcp dport 22 accept
iptables -I INPUT 1 ... nft insert rule inet filter input position 0 ...
iptables -t nat -A POSTROUTING -j MASQUERADE nft add rule ip nat postrouting masquerade
iptables -m conntrack --ctstate ESTABLISHED,RELATED ct state established,related
-m multiport --dports 80,443 tcp dport { 80, 443 }
iptables-save > file nft list ruleset > file

Міграція з iptables на nftables

# Конвертувати існуючі iptables правила в nftables синтаксис
iptables-save | iptables-restore-translate -f - > /etc/nftables.conf

# Перевірити
nft -c -f /etc/nftables.conf
ℹ️ Коли залишатись на iptables
Docker досі генерує правила через `iptables` (через shim). На хості Docker краще не заважати — пиши власні правила в окрему таблицю nftables, або в ланцюг `DOCKER-USER`.

UFW (спрощений фронт)

ufw default deny incoming
ufw default allow outgoing

ufw allow 22/tcp comment 'SSH'
ufw allow 51820/udp comment 'WireGuard'
ufw allow from 10.10.10.0/24 to any port 22
ufw limit 22/tcp                      # rate-limit brute force

ufw enable
ufw status numbered
ufw delete 3                          # видалити правило номер 3

Troubleshooting

Заблокував себе по SSH
- Симптом: після iptables -P INPUT DROP (без правила ACCEPT для SSH) сесія замерзла, нове підключення висить.
- Причина: політика DROP застосовується до ВСІХ пакетів включно зі свіжими SYN на порт 22.
- Рішення: якщо активна сесія ще жива — НЕ закривай її, виправ через неї: iptables -I INPUT 1 -p tcp --dport 22 -j ACCEPT, потім iptables-save. Якщо сесія закрилась — через console VPS-провайдера скинути правила: iptables -F; iptables -P INPUT ACCEPT. Превентивно — at now + 5 min <<< 'iptables -F' перед ризикованими змінами.

Правила є, але трафік дропається
- Симптом: iptables -L показує ACCEPT для потрібного порту, але підключення не проходить.
- Причина: порядок правил. iptables обробляє згори вниз, перше збіжне правило виграє. Якщо вище стоїть DROP — ACCEPT внизу не спрацює.
- Рішення: подивитись з лічильниками: iptables -L INPUT -n -v --line-numbers. Якщо pkt counter на потрібному правилі 0 — воно не досягається. Переставити: iptables -D INPUT <N>; iptables -I INPUT 1 <rule>.

nftables не стартує після reboot
- Симптом: nft list ruleset порожнє після перезавантаження.
- Причина: сервіс nftables.service вимкнено, або /etc/nftables.conf з синтаксичною помилкою.
- Рішення: systemctl enable --now nftables, перевірити конфіг nft -c -f /etc/nftables.conf — покаже помилку з номером рядка. Логи: journalctl -u nftables -n 50.

Docker ламає власні правила iptables
- Симптом: після systemctl restart docker або docker compose up власні правила зникають або перестають працювати.
- Причина: Docker створює власні ланцюги (DOCKER, DOCKER-USER) у таблиці filter та NAT, і перевизначає правила при старті.
- Рішення: не чіпати ланцюги DOCKER*. Додавати власні правила в DOCKER-USER — вони виконуються ДО правил Docker: iptables -I DOCKER-USER -i eth0 -s 1.2.3.4 -j DROP. Для host-level firewall використовуй nftables в окремій таблиці (Docker її не чіпає).


Пов'язані статті

Шлях: reference/iptables-cheatsheet.md

UMTC Wiki © 2026 | Ukrainian Military Tactical Communications