Задача урока - превратить обычный сервер в полноценный шлюз: заставить его пропускать чужой трафик между интерфейсами (форвардинг), подменять адреса для выхода локальной сети в интернет (NAT и masquerade) и закрыть периметр пакетным фильтром. В 2026 году актуальный инструмент фильтрации - nftables, а старый iptables живёт только как совместимость поверх того же ядерного движка. Разберём, как это устроено внутри, и научимся писать и сохранять правила.

Как это работает
По умолчанию Linux ведёт себя как хост: пакет, чей адрес назначения не принадлежит самой машине, молча отбрасывается. Чтобы ядро начало пересылать такие пакеты между интерфейсами, нужно включить форвардинг - параметр sysctl net.ipv4.ip_forward. Только тогда машина становится маршрутизатором и смотрит в таблицу маршрутизации, куда отправить транзитный пакет дальше.
NAT - это переписывание адресов на лету. Когда хосты из сети 192.168.0.0/24 идут в интернет через шлюз, их приватные адреса наружу выпускать нельзя. SNAT подменяет адрес источника на внешний адрес шлюза, а masquerade - это частный случай SNAT, который сам подхватывает текущий IP исходящего интерфейса. Masquerade нужен там, где внешний адрес динамический (PPPoE, DHCP от провайдера); если адрес статический, выгоднее явный SNAT - он чуть быстрее, так как не дёргает интерфейс на каждый поток.
Внутри ядра весь фильтр и NAT работают через подсистему netfilter - набор хуков (prerouting, input, forward, output, postrouting), через которые проходит каждый пакет. И nftables, и legacy iptables вешают свои правила именно на эти хуки. Разница в том, что у iptables таблицы и цепочки жёстко зашиты (filter, nat, mangle), а в nftables вы создаёте таблицы и цепочки сами и задаёте их тип и приоритет. nftables даёт единый синтаксис для IPv4 и IPv6 (семейство inet), атомарную загрузку всего набора правил и наборы (sets) - быстрые хеш-структуры для списков адресов и портов вместо сотни отдельных правил.
Команды и примеры
Включаем форвардинг. Временно - через sysctl, постоянно - файлом в /etc/sysctl.d/:
Код: Выделить всё
sysctl -w net.ipv4.ip_forward=1
echo 'net.ipv4.ip_forward=1' > /etc/sysctl.d/99-router.conf
sysctl --system # перечитать все конфиги
cat /proc/sys/net/ipv4/ip_forward # проверка, должно быть 1
Базовый шлюз на nftables. eth0 - наружу, eth1 - в локальную сеть:
Код: Выделить всё
nft add table inet fw
nft 'add chain inet fw forward { type filter hook forward priority 0; policy drop; }'
nft 'add chain inet fw postrt { type nat hook postrouting priority 100; }'
# выпускаем локалку наружу с подменой адреса
nft add rule inet fw postrt oifname "eth0" masquerade
# разрешаем установленные и обратные соединения
nft add rule inet fw forward ct state established,related accept
# разрешаем новые соединения из локалки наружу
nft add rule inet fw forward iifname "eth1" oifname "eth0" accept
Код: Выделить всё
nft add rule inet fw postrt oifname "eth0" snat ip to 203.0.113.10
Код: Выделить всё
nft 'add chain inet fw input { type filter hook input priority 0; policy drop; }'
nft add rule inet fw input ct state established,related accept
nft add rule inet fw input iif lo accept
nft add rule inet fw input tcp dport { 22, 80, 443 } accept
nft add rule inet fw input ip protocol icmp accept
Код: Выделить всё
nft list ruleset # показать всё
nft list table inet fw # одну таблицу
nft -s list ruleset > /etc/nftables.conf # выгрузить (-s без счётчиков)
nft -f /etc/nftables.conf # загрузить из файла (атомарно)
systemctl enable --now nftables # автозагрузка при старте
Legacy iptables - дать коротко, для экзамена. В 2026 это наследие, на современных дистрибутивах команда iptables на деле iptables-nft (обёртка над тем же движком):
Код: Выделить всё
iptables -P FORWARD DROP
iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -i eth1 -o eth0 -j ACCEPT
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
Код: Выделить всё
iptables-save > /etc/iptables/rules.v4
ip6tables-save > /etc/iptables/rules.v6
Частые грабли
- Забыли включить ip_forward - правила NAT написаны верно, а пакеты не идут. Проверяйте /proc/sys/net/ipv4/ip_forward первым делом.
- Поставили sysctl только через sysctl -w - после перезагрузки форвардинг отключается. Нужна запись в /etc/sysctl.d/.
- masquerade в цепочке с типом filter или с неправильным priority - правило не срабатывает. NAT работает только в цепочке type nat hook postrouting (для SNAT/masquerade) или prerouting (для DNAT).
- policy drop в цепочке forward или input, но не разрешили established,related и loopback - сервер режет ответы на собственные запросы и теряет связь по SSH. Сначала правило accept для lo и established, потом меняйте политику.
- Смешали iptables-legacy и iptables-nft на одной машине - правила из разных бэкендов не видят друг друга, хотя ядро одно. Используйте update-alternatives и не плодите оба.
- Редактировали /etc/nftables.conf, но не перезагрузили nftables.service - в памяти ядра остались старые правила.
- Поднимите ВМ с двумя интерфейсами: eth0 в режиме NAT/моста наружу, eth1 в internal-сети с клиентом.
- Включите net.ipv4.ip_forward через /etc/sysctl.d/ и убедитесь, что значение пережило reboot.
- Создайте таблицу inet, цепочку postrouting типа nat и добавьте masquerade на oifname eth0.
- С клиента из internal-сети пропингуйте 8.8.8.8 и через nft list ruleset посмотрите счётчики пакетов на правиле.
- Закройте input политикой drop, разрешив lo, established,related и tcp dport 22 через set.
- Выгрузите ruleset в /etc/nftables.conf, перезагрузите ВМ и проверьте, что правила и связь восстановились автоматически.
- Какой sysctl-параметр превращает Linux-хост в маршрутизатор и как сделать его постоянным?
- Чем masquerade отличается от SNAT и в каком случае каждый из них предпочтительнее?
- Через какие хуки netfilter проходит транзитный пакет и в какой цепочке выполняется NAT источника?
- Зачем в цепочке с политикой drop нужно правило для состояния established,related?
- Какие преимущества дают наборы (sets) в nftables по сравнению с отдельными правилами?
- Какие команды сохраняют и восстанавливают ruleset nftables и как обеспечить его автозагрузку?