Как защитить веб-сервер на Ubuntu 24.04 с помощью nftables? Разбираем настройку файрвола: SSH, HTTP/HTTPS, защита от SYN-флуда и брутфорса. В статье — готовые правила и объяснение каждого шага.
Введение
В этой статье мы настроим nftables на Ubuntu 24.04 под веб-сервер. Вы получите готовую конфигурацию, которая:
- защитит SSH-доступ от брутфорса и несанкционированных подключений,
- разрешит входящий трафик для HTTP/HTTPS,
- сохранит базовую функциональность (ping, loopback, ответы на запросы),
- добавит защиту от SYN-флуда.
Подготовка среды и создание первых правил файрвола
Первым делом убедимся, что nftables уже есть в вашей системе:
sudo apt policy nftables
В выводе должно быть installed, так как nftables предустановлен на Ubuntu 24.04. Если пакет отсутствует (был удалён), установите его:
sudo apt install nftables -y
Теперь активируем системный сервис nftables — он будет загружать правила при старте сервера:
sudo systemctl enable --now nftables
Создаём первую таблицу с именем firewall (имя может произвольным) и семейством inet для одновременной работы с IPv4/IPv6:
sudo nft add table inet firewall
Если вы подключены по SSH, то в первую очередь добавьте разрешающее правило для SSH — чтобы не потерять доступ к серверу.
Только с вашего IP (замените 203.0.113.5 на реальный адрес):
sudo nft add rule inet firewall input tcp dport ssh ip saddr 203.0.113.5 ct state new accept
Или с любого IP:
sudo nft add rule inet firewall input tcp dport ssh ct state new accept
Теперь добавим в эту же таблицу базовые цепи, реализующие принцип «запрещено всё, что не разрешено явно».
Цепь для входящего трафика (к серверу):
sudo nft add chain inet firewall input {
type filter hook input priority 0;
policy drop; # Всё запрещено по умолчанию
}
Цепь для пересылки (через сервер):
sudo nft add chain inet firewall forward {
type filter hook forward priority 0;
policy drop; # Запрет пересылки, веб-серверу это не нужно
}
Цепь для исходящего трафика:
sudo nft add chain inet firewall output {
type filter hook output priority 0;
policy accept; # Разрешаем весь исходящий трафик
}
Здесь:
- hook input — трафик, предназначенный серверу;
- priority 0 — высокий приоритет обработки;
- policy drop — по умолчанию блокируется весь неразрешённый трафик.
Проверяем:
sudo nft list ruleset
Вы должны увидеть все только что созданные правила.
Обязательные базовые правила: localhost, ответы на запросы и ping
У нас уже есть правила, запрещающие всё по умолчанию, теперь добавим три важных исключения, которые нужны для нормальной работы сервера. Они позволят внутренним сервисам взаимодействовать, серверу — получать ответы на свои запросы, а администраторам — проводить диагностику сети.
Разрешение loopback-трафика
Интерфейс lo (localhost) используется для внутренней коммуникации сервисов: веб-сервер обращается к базе данных, PHP-FPM общается с Nginx, Docker-контейнеры взаимодействуют с хостом:
sudo nft add rule inet firewall input iifname "lo" accept
Здесь iifname "lo" означает, что пакет пришёл с интерфейса loopback, а accept — разрешение. Это правило ставим первым в цепи input, так как локальный трафик максимально безопасен и имеет высокий приоритет.
Разрешение ответного трафика
Когда система сама инициирует соединение (запрос к репозиторию apt, вызов API, DNS-запрос), она должна получить ответ. Правило:
sudo nft add rule inet firewall input ct state established,related accept
ct state отслеживает статус соединений, established разрешает пакеты для уже открытых соединений, related — для связанных сессий (например, FTP data channel).
Разрешение ICMP (ping)
ping незаменим для диагностики сети, но без ограничений он становится оружием в DoS-атаках. Настраиваем отдельно для IPv4 и IPv6:
sudo nft add rule inet firewall input ip protocol icmp icmp type echo-request limit rate 5/second accept # IPv4
sudo nft add rule inet firewall input ip6 nexthdr icmpv6 icmpv6 type echo-request limit rate 5/second accept # IPv6
Здесь ip protocol icmp / ip6 nexthdr icmpv6 фильтрует по протоколу, icmp type echo-request / icmpv6 type echo-request — запросы ping, а limit rate 5/second — ограничение скорости. Это защищает от флуда ICMP-пакетами, разрешая легитимную диагностику.
Проверяем текущую конфигурацию:
sudo nft list ruleset
Вы увидите последовательную обработку:
- безусловное принятие localhost-трафика,
- разрешение ответов на исходящие соединения,
- ограниченный по скорости ping для IPv4/IPv6,
- полный запрет всего остального.
Порядок правил важен, так как nftables обрабатывает их сверху вниз до первого совпадения. К тому же размещение «тяжёлых» проверок (состояние соединения) после «лёгких» (интерфейс, протокол) снижает нагрузку на CPU.
Настройка доступа по SSH для разных сценариев
Рассмотрим два подхода в настройке SSH, адаптированных под разные инфраструктурные требования — от максимально жёсткого ограничения до динамической защиты.
Вариант 1. Разрешение только из доверенных сетей
Этот метод обеспечивает максимальную безопасность и подходит для корпоративных сред. Правило будет выглядеть так:
sudo nft add rule inet firewall input tcp dport ssh ip saddr { 192.168.1.0/24, 203.0.113.5 } ct state new accept
Механизм работы:
- tcp dport ssh фильтрует трафик на порт 22 (стандартный для SSH);
- ip saddr { ... } разрешает только указанные IPv4-адреса;
- ct state new принимает только новые подключения (существующие обрабатываются ранее добавленным правилом для established).
Вариант 2. Адаптивная защита от брутфорса
Когда ограничение по IP невозможно (например, для публичных серверов, облачного VPS), реализуем динамическую защиту в четыре этапа:
- Создаём «чёрный список» с автоматическим удалением IP через час:
sudo nft add set inet firewall ssh_blacklist { type ipv4_addr; flags timeout; }
add set создаёт динамическую хеш-таблицу ssh_blacklist, где timeout 1h автоматически очищает записи через час.
- Разрешаем новые подключения с лимитом 3 попытки в минуту, этого достаточно для подключения вручную, но блокирует боты:
sudo nft add rule inet firewall input tcp dport ssh ct state new limit rate 3/minute accept
- При превышении лимита помещаем IP в чёрный список и блокируем пакет:
sudo nft add rule inet firewall input tcp dport ssh ct state new add @ssh_blacklist { ip saddr timeout 1h } counter drop
- Запрещаем весь трафик из заблокированных адресов:
sudo nft add rule inet firewall input ip saddr @ssh_blacklist counter drop
Дополнительные меры безопасности и проверка конфигурации
Оба варианта требуют дополнительной настройки в /etc/ssh/sshd_config:
PasswordAuthentication no # Отключение входа по паролю, требует настройки ssh-ключей
PermitRootLogin no # Запрет прямого входа под root
AllowUsers [user] # Разрешение только перечисленным пользователям
После изменений в sshd_config выполните:
sudo systemctl restart sshd
Просмотр динамического чёрного списка:
sudo nft list set inet firewall ssh_blacklist
Поиск SSH-правил в цепочке:
sudo nft list chain inet firewall input | grep -A 10 'tcp dport ssh'
Настройка доступа к веб-серверу
После настройки SSH переходим к ключевой функции сервера — обслуживанию веб-трафика. Мы разрешим доступ к HTTP/HTTPS портам и добавим защиту от DDoS-атак.
Разрешение базового веб-трафика
Чтобы пользователи могли обращаться к вашему сайту, нужно открыть стандартные порты:
sudo nft add rule inet firewall input tcp dport { http, https } ct state new accept
Команда разрешает новые входящие подключения (ct state new) к портам 80 (HTTP) и 443 (HTTPS), используя встроенные синонимы http и https. Установленные соединения уже обрабатываются ранее добавленным правилом для established-состояний. Разделение новых и установленных соединений позволяет реализовать более тонкую фильтрацию. В дальнейшем мы добавим ограничения именно для новых подключений, так как они наиболее уязвимы для атак.
Защита от SYN-флуда
SYN-флуд — распространённая DDoS-атака: злоумышленник отправляет множество запросов на подключение (TCP-SYN пакеты), которые остаются полуоткрытыми. Это переполняет очередь соединений веб-сервера. Решение состоит из двух правил:
- Ограничение скорости SYN-пакетов для веб-портов:
sudo nft add rule inet firewall input tcp flags syn tcp dport { http, https } limit rate 30/second burst 50 packets accept
- Блокировка всех остальных SYN-пакетов:
sudo nft add rule inet firewall input tcp flags syn drop
Первое правило разрешает SYN-пакеты (начало соединения) на порты 80/443, но не более 30 в секунду с бурстом до 50 пакетов. Значения можно увеличить для высоконагруженных проектов (например, 100/second burst 200). Второе правило отбрасывает все SYN-пакеты, не попавшие под первое ограничение. Правила нужно добавлять именно в таком порядке. Если поставить drop перед accept, все SYN-пакеты будут блокироваться без анализа.
Проверка конфигурации:
sudo nft list ruleset | grep -A 10 'chain input' | grep 'http\|https\|syn'
Пример вывода:
tcp dport { http, https } ct state new accept # Разрешение веб-трафика
tcp flags syn tcp dport { http, https } limit rate 30/second burst 50 packets accept # Защита веб-портов
tcp flags syn drop # Блокировка остальных SYN
Сохранение правил и управление конфигурацией
После добавления правил важно настроить их автоматическую загрузку при перезапуске сервера. Рассказываем, как сохранить конфигурацию и проверить её корректность.
Экспорт текущих правил в конфигурационный файл, который будет загружаться автоматически:
sudo nft list ruleset > /etc/nftables.conf
Команда nft list ruleset выводит текущую конфигурацию в формате, пригодном для повторной загрузки. Оператор > перенаправляет этот вывод в системный конфигурационный файл /etc/nftables.conf. По умолчанию сервис nftables настроен загружать правила именно из этого файла.
Просмотрите содержимое файла:
sudo cat /etc/nftables.conf
Вы должны увидеть все созданные таблицы, цепи и правила в упорядоченном виде.
Ошибка в конфиге может привести к полной блокировке сервера при перезагрузке или, что хуже, к неработоспособности файрвола без вашего ведома. Поэтому, прежде чем перезагружать сервис, убедитесь, что конфиг без ошибок:
sudo nft -c -f /etc/nftables.conf
Флаг -c (check) включает режим проверки без реального применения правил, -f указывает на файл для анализа. Если вывод пуст — синтаксис корректен. Если есть ошибки — будут показаны конкретные строки с описанием проблемы.
Теперь активируем сохранённую конфигурацию и обеспечим её загрузку при старте системы:
sudo systemctl restart nftables
Сервис остановится и текущие правила будут удалены из памяти ядра. Затем загрузится новая конфигурация из /etc/nftables.conf. Правила будут применяться в том порядке, в котором они записаны в файле.
Проверка статуса:
sudo systemctl status nftables
Вывод должен показать active (exited).
Также просмотрите список активных правил и сравните вывод с содержимым конфиг-файла:
sudo nft list ruleset
Дополнительные рекомендации
Перед внесением изменений создавайте копии конфига:
sudo cp /etc/nftables.conf /etc/nftables.conf.bak_$(date +%F)
Всегда редактируйте копию, затем проверяйте и заменяйте основной файл:
sudo nano /etc/nftables.new
sudo nft -c -f /etc/nftables.new && sudo mv /etc/nftables.new /etc/nftables.conf
Если после перезагрузки сервиса вы потеряли доступ, выполните через консоль управления хостингом (KVM/IPMI) следующее.
- Остановка сервиса:
sudo systemctl stop nftables
- Откройте конфиг и исправьте настройки:
sudo nano /etc/nftables.conf
- Повторная загрузка:
sudo systemctl start nftables
В экстренных случаях поможет сброс всех правил:
sudo nft flush ruleset
Правила в /etc/nftables.conf обрабатываются сверху вниз. Правильный порядок:
- разрешение localhost,
- разрешение established/related,
- разрешение ICMP,
- правила для SSH,
- правила для веб-сервера,
- блокировка всего остального.
Читайте в блоге:
- Как обновить ядро Linux на Ubuntu 24.04 и откатить изменения при ошибках
- Как перенести Ubuntu 24.04 на новый сервер без переустановки
- Настройка автоматического удаления старых логов с logrotate на Ubuntu 24.04