Базовые настройки nftables для веб сервера на Debian

Сейчас в большинстве популярных дистрибутивов на базе Linux в качестве файрвола по умолчанию используется nftables. Конкретно в Debian начиная с Debian 10 Buster. Пришло время разобраться с его базовой настройкой и использованием.

Онлайн-курс по устройству компьютерных сетей

На углубленном курсе "Архитектура современных компьютерных сетей" вы с нуля научитесь работать с Wireshark и «под микроскопом» изучите работу сетевых протоколов. На протяжении курса надо будет выполнить более пятидесяти лабораторных работ в Wireshark.

Введение

Я обычно делаю вот так в нём:

# apt remove --auto-remove nftables
# apt purge nftables
# apt update
# apt install iptables

Но это не может продолжаться вечно. Для какого-нибудь одиночного сервера эти действия просто не нужны. Проще сразу настроить nftables. К тому же у него есть и явные преимущества, про которые я знаю:

  • единый конфиг для ipv4 и ipv6;
  • более короткий и наглядный синтаксис;
  • nftables умеет быстро работать с огромными списками, не нужен ipset;
  • экспорт правил в json, удобно для мониторинга.

Я точно помню, что когда-то писал набор стандартных правил для nftables, но благополучно его потерял. Пришлось заново составлять, поэтому и пишу сразу заметку, чтобы не потерять ещё раз. Правила будут для условного веб сервера, где разрешены на вход все соединения на 80 и 443 порты, на порт 10050 zabbix агента разрешены только с zabbix сервера, а на 22-й порт SSH только для списка IP адресов. Всё остальное закрыто на вход. Исходящие соединения сервера разрешены.

Основные команды nftables

Начну с базы, нужной для управления правилами. Смотрим существующий список правил и таблиц:

# nft -a list ruleset
# nft list tables

Очистка правил nftables:

# nft flush ruleset

Набор правил nftables для веб сервера

Дальше сразу привожу готовый набор правил. Отдельно отмечу, что в nftables привычные таблицы и цепочки нужно создать отдельно. В iptables они были по умолчанию.

nft add table inet filter
nft add chain inet filter input { type filter hook input priority 0\; }
nft add rule inet filter input ct state related,established counter accept
nft add rule inet filter input iifname "lo" counter accept
nft add rule inet filter input ip protocol icmp counter accept
nft add rule inet filter input tcp dport {80, 443} counter accept
nft add rule inet filter input ip saddr { 192.168.100.0/24, 172.20.0.0/24, 1.1.1.1/32 } tcp dport 22 counter accept
nft add rule inet filter input ip saddr 2.2.2.2/32 tcp dport 10050 counter accept
nft chain inet filter input { policy drop \; }

Вот и всё, настроили базовый набор правил. Мы создали таблицу filter, добавили цепочку input, закинули туда нужные нам разрешающие правила и в конце изменили политику по умолчанию на drop. Так как никаких других правил нам сейчас не надо, остальные таблицы и цепочки можно не создавать. Осталось только сохранить эти правила и применить их после загрузки сервера.

Автозагрузка правил при запуске сервера

У nftables есть служба, которая при запуске читает файл конфигурации /etc/nftables.conf и применяет правила. Запишем туда наш набор правил для автоматического применения после перезагрузки. Так как мы перезапишем существующую конфигурацию, где в начале стоит очистка всех правил, нам надо отдельно добавить её туда:

# echo "flush ruleset" > /etc/nftables.conf
# nft -s list ruleset >> /etc/nftables.conf
# systemctl enable nftables.service

Можно перезагружаться и проверять автозагрузку правил nftables.

Настройка Nftables в Debian

Ещё полезная команда, которая пригодится в процессе настройки. Удаление правила по номеру:

# nft delete rule inet filter input handle 9

Добавление правила nftables в конкретное место с номером в списке:

# nft add rule inet filter input position 8 tcp dport 22 counter accept

В целом, ничего сложного. Подобным образом настраиваются остальные цепочки output или forward, если нужно. Синтаксис удобнее, чем у iptables. Как-то более наглядно и логично, особенно со списками ip адресов и портов, если они небольшие.

Единственное, что не нашёл пока как делать - как подгружать очень большие списки с ip адресами. Вываливать их в список правил - плохая идея. Надо как-то подключать извне. По идее это описано в sets, но я пока не разбирался.

Документация по nftables

Онлайн-курс по устройству компьютерных сетей.

На углубленном курсе "Архитектура современных компьютерных сетей" вы с нуля научитесь работать с Wireshark и «под микроскопом» изучите работу сетевых протоколов. На протяжении курса надо будет выполнить более пятидесяти лабораторных работ в Wireshark.

Помогла статья? Подписывайся на telegram канал автора

Анонсы всех статей, плюс много другой полезной и интересной информации, которая не попадает на сайт.

Автор Zerox

Владимир, системный администратор, автор сайта. Люблю настраивать сервера, изучать что-то новое, делиться знаниями, писать интересные и полезные статьи. Открыт к диалогу и сотрудничеству. Если вам интересно узнать обо мне побольше, то можете послушать интервью. Запись на моем канале - https://t.me/srv_admin/425 или на сайте в контактах.

7 комментариев

  1. Добрый день. Я любитель. Хочу арендовать VPS под Debian. Стал разбираться с настройкой firewall. Так как нет уверенных знаний ни в iptables ни в nftables смотрю и туда и сюда. По iptables больше примеров, нашел ваш скрипт. Решил попробовать "перевести" его в nftables с помощью ChatGPT. Оценить правильность не могу, но может Вам будет интересно глянуть :) . Привожу его ниже:
    #!/bin/bash

    # Внешний интерфейс
    export WAN=eth0
    export WAN_IP=85.31.203.127

    # Локальная сеть
    export LAN1=eth1
    export LAN1_IP_RANGE=10.1.3.0/24

    # Очищаем правила
    nft flush ruleset

    # Создаем таблицы и цепочки
    nft add table inet filter
    nft add chain inet filter input { type filter hook input priority 0 \; policy drop \; }
    nft add chain inet filter forward { type filter hook forward priority 0 \; policy drop \; }
    nft add chain inet filter output { type filter hook output priority 0 \; policy drop \; }

    nft add table ip nat
    nft add chain ip nat prerouting { type nat hook prerouting priority -100 \; }
    nft add chain ip nat postrouting { type nat hook postrouting priority 100 \; }

    # Разрешаем localhost и локалку
    nft add rule inet filter input iifname lo accept
    nft add rule inet filter input iifname $LAN1 accept
    nft add rule inet filter output oifname lo accept
    nft add rule inet filter output oifname $LAN1 accept

    # Разрешаем пинги
    nft add rule inet filter input ip protocol icmp icmp type echo-reply accept
    nft add rule inet filter input ip protocol icmp icmp type destination-unreachable accept
    nft add rule inet filter input ip protocol icmp icmp type time-exceeded accept
    nft add rule inet filter input ip protocol icmp icmp type echo-request accept

    # Разрешаем исходящие подключения сервера
    nft add rule inet filter output oifname $WAN accept
    # nft add rule inet filter input iifname $WAN accept

    # Разрешаем установленные подключения
    nft add rule inet filter input ct state established,related accept
    nft add rule inet filter output ct state established,related accept
    nft add rule inet filter forward ct state established,related accept

    # Отбрасываем неопознанные пакеты
    nft add rule inet filter input ct state invalid drop
    nft add rule inet filter forward ct state invalid drop

    # Отбрасываем нулевые пакеты
    nft add rule inet filter input tcp flags == syn && tcp flags == ack drop

    # Закрываемся от syn-flood атак
    nft add rule inet filter input tcp flags & (syn|ack|fin|rst) == syn limit rate 5/second accept

    # Блокируем доступ с указанных адресов
    # nft add rule inet filter input ip saddr 84.122.21.197 reject

    # Пробрасываем порт в локалку
    # nft add rule ip nat prerouting tcp dport 23543 iifname $WAN dnat to 10.1.3.50:3389
    # nft add rule inet filter forward iifname $WAN oifname $LAN1 accept

    # Разрешаем доступ из локалки наружу
    nft add rule inet filter forward iifname $LAN1 oifname $WAN accept
    # Закрываем доступ снаружи в локалку
    nft add rule inet filter forward iifname $WAN oifname $LAN1 reject

    # Включаем NAT
    nft add rule ip nat postrouting oifname $WAN ip saddr $LAN1_IP_RANGE masquerade

    # Открываем доступ к SSH
    nft add rule inet filter input iifname $WAN tcp dport 22 accept

    # Открываем доступ к почтовому серверу
    nft add rule inet filter input tcp dport {25, 465, 110, 995, 143, 993} accept

    # Открываем доступ к web серверу
    nft add rule inet filter input tcp dport {80, 443} accept

    # Открываем доступ к DNS серверу
    # nft add rule inet filter input iifname $WAN udp dport 53 accept

    # Включаем логирование
    # nft add chain inet filter block_in
    # nft add chain inet filter block_out
    # nft add chain inet filter block_fw

    # nft add rule inet filter input log prefix "--IN--BLOCK" level info
    # nft add rule inet filter input drop
    # nft add rule inet filter output log prefix "--OUT--BLOCK" level info
    # nft add rule inet filter output drop
    # nft add rule inet filter forward log prefix "--FW--BLOCK" level info
    # nft add rule inet filter forward drop

    # Сохраняем правила
    nft list ruleset > /etc/nftables.conf

    • Он работает в итоге? Вы пробовали его? Я не работаю постоянно с nftables, на глаз не могу определить корректность синтаксиса.

      • Нет, не пробывал :) Я только разбираюсь, мне еще сложнее сказать :)

        • На тестовой виртуалке проверить - дело 5 минут. Даже быстрее, чем сюда скопировать и написать комментарий. Либо заработает, либо нет. Одно из двух :)

  2. Спасибо за статью, все руки не доходили 😅

    По поводу множества IP подсунуть у них в документации есть пример с GeoIP.
    Я так понял через "include" делается.

    https://wiki.nftables.org/wiki-nftables/index.php/GeoIP_matching

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Нажимая кнопку "Отправить комментарий" Я даю согласие на обработку персональных данных.
Используешь Telegram? Подпишись на канал автора →
This is default text for notification bar