Изменение nftables на выделенном сервере с отложенным откатом

Изменение nftables на выделенном сервере с отложенным откатом

Изменение nftables на выделенном сервере с отложенным откатом

При удалённом администрировании выделенного сервера легко ошибиться в оценке изменений межсетевого экрана: команды в текущем сеансе SSH продолжают выполняться, и кажется, что новые правила успешно прошли проверку. На деле отслеживание соединений может сохранять старый сеанс, хотя новые подключения уже заблокированы. Надёжный порядок действий — сначала сохранить текущее состояние и запланировать восстановление, затем загрузить правила и только после этого проверить доступ через отдельное подключение.

В статье используются Debian 12, nftables и systemd. Мы рассмотрим точечное изменение, которое ограничивает только источники подключений SSH. Адрес подключения и учётные данные сервера AMDSSH доступны в панели управления после оплаты; если у сервера несколько адресов IPv4, для SSH используется первый. Пример не предполагает заранее заданного имени пользователя или порта и не формирует полную политику для портов рабочих сервисов.

1. Определите границы управления правилами

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

Начните с просмотра текущего состояния:

sudo nft list ruleset
sudo systemctl cat nftables.service
command -v nft

Проверьте существующие правила, файл, загружаемый при запуске, и фактический путь к nft. В статье используется отдельная таблица inet ops_guard. Если таблица с таким именем уже существует, обязательно выясните её назначение: нельзя перезаписывать правила, используемые для других задач.

Таймер отката восстанавливает только правила межсетевого экрана, изменяемые в рамках этой операции. Он не исправит проблемы, вызванные одновременным изменением маршрутизации, службы SSH или источника административных подключений. За одну операцию меняйте только один параметр.

Получите фактические параметры SSH

Выполните команды в Bash текущего удалённого сеанса. Не переходите предварительно в другой сеанс, где могут отсутствовать переменные окружения с параметрами подключения:

test -n "$SSH_CONNECTION" || exit 1
read -r ADMIN_IP CLIENT_PORT SERVER_IP SSH_PORT <<< "$SSH_CONNECTION"
case "$ADMIN_IP" in
  *:*) printf '%s\n' 'IPv4 SSH session required'; exit 1 ;;
esac
printf 'source=%s destination=%s port=%s\n' \
  "$ADMIN_IP" "$SERVER_IP" "$SSH_PORT"

Так определяется адрес источника, который видит сервер. Это может быть внешний адрес офисной сети или промежуточного сервера, а не внутренний адрес рабочей станции. Если внешний адрес может меняться, сначала организуйте стабильный путь для администрирования. В этом примере текущий сеанс должен использовать IPv4; не пытайтесь продолжить, сформировав правила из сеанса IPv6.

2. Сохраните снимок и запланируйте автоматическое восстановление

Снимок должен включать команду очистки старых правил, иначе при восстановлении возможны конфликты с уже существующими объектами. Доступ к каталогу разрешается только администраторам, чтобы обычные пользователи не могли прочитать сведения об адресации из правил.

sudo install -d -m 700 /root/firewall-change
sudo sh -c '
set -e
umask 077
{
  printf "flush ruleset\n"
  nft list ruleset
} > /root/firewall-change/before.nft
'
sudo nft -c -f /root/firewall-change/before.nft

Параметр -c выполняет только проверку, без загрузки правил. Он позволяет обнаружить ошибки синтаксиса и ссылок на объекты правил, но не подтверждает, что удалённый вход останется доступен. Если проверка завершилась с ошибкой, остановите изменение; нельзя игнорировать ошибку и продолжать.

Убедитесь, что не осталось ранее созданного задания с тем же именем, и запланируйте восстановление через три минуты:

sudo systemctl status ops-firewall-rollback.timer
sudo systemd-run \
  --unit=ops-firewall-rollback \
  --on-active=3m \
  "$(command -v nft)" \
  -f /root/firewall-change/before.nft
sudo systemctl list-timers ops-firewall-rollback.timer

При первой проверке сообщение об отсутствии юнита нормально. Если задание уже существует, сначала выясните, откуда оно появилось. Три минуты — это время ожидания отката для данной операции, а не обещанный срок предоставления услуги. Переходите к загрузке правил только после того, как убедитесь, что таймер запланирован. Не изменяйте в этот промежуток другие сетевые правила: восстановление полного набора отменит и эти изменения.

3. Ограничьте источники административных подключений отдельной таблицей

При первом использовании создайте пустую таблицу. Выполняйте команду создания только после проверки, что таблицы с таким именем нет. Если выделенная для этой операции таблица уже существует, пропустите этот шаг:

sudo nft add table inet ops_guard

Затем сформируйте файл с предлагаемыми правилами:

sudo tee /root/firewall-change/candidate.nft > /dev/null <<EOF
delete table inet ops_guard
table inet ops_guard {
  chain input {
    type filter hook input priority 10; policy accept;
    iifname "lo" accept
    ct state established,related accept
    ip saddr $ADMIN_IP tcp dport $SSH_PORT accept
    tcp dport $SSH_PORT counter drop
  }
}
EOF
sudo chmod 600 /root/firewall-change/candidate.nft
sudo nft -c -f /root/firewall-change/candidate.nft
sudo nft -f /root/firewall-change/candidate.nft
sudo nft -a list table inet ops_guard

Удаление и повторное создание таблицы из файла выполняются в одной транзакции nftables, а не как отдельная очистка с последующим добавлением правил по одному. При каждой загрузке этого файла выделенная таблица уже должна существовать, поэтому использовать его напрямую как конфигурацию для запуска системы нельзя.

Правила разрешают трафик через loopback-интерфейс и уже установленные соединения, допускают текущий источник администрирования IPv4 к фактическому порту SSH, а затем блокируют обращения к этому порту из остальных источников. Последнее правило также совпадает с трафиком IPv6, поэтому новые подключения SSH по IPv6 в этом примере не разрешены. Если нужен административный доступ по IPv6, заранее добавьте явное разрешающее правило ip6 saddr и проверьте его отдельно.

Эта таблица не ограничивает другие порты рабочих сервисов. При этом accept в ней не отменяет drop в других базовых цепочках: существующие правила по-прежнему могут блокировать новые подключения. Не рассматривайте этот пример как полную базовую конфигурацию безопасности и тем более не удаляйте на его основании действующие правила для рабочих сервисов.

4. Решайте, принимать ли изменения, по результатам отдельного нового подключения

Не закрывайте исходный сеанс и установите ещё одно подключение из разрешённого источника. Если на клиенте включено повторное использование соединений, отключите его: иначе новое окно может продолжить использовать старое TCP-соединение.

Следующие команды выполняются в Bash на клиенте. Введите интерактивно параметры из панели управления:

read -r -p 'Host: ' HOST
read -r -p 'User: ' LOGIN
read -r -p 'Port: ' PORT
ssh -o ControlMaster=no -o ControlPath=none \
  -p "$PORT" "$LOGIN@$HOST"

Проверка должна включать как минимум три пункта:

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

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

sudo systemctl stop ops-firewall-rollback.timer
sudo systemctl is-active ops-firewall-rollback.timer

Также убедитесь, что служба восстановления ещё не запустилась. Если таймер сработал как раз в этот момент, заново прочитайте действующие правила. Успешное выполнение команды остановки не доказывает, что предложенная конфигурация всё ещё активна.

5. Отдельно сохраните конфигурацию и проверьте запуск

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

Когда правила стабильны и другие средства управления их не изменяют, выгрузите полный действующий набор в файл с командой flush ruleset, выполните проверку nft -c -f, затем создайте резервную копию исходного загрузочного файла и только после этого замените его. Нельзя сохранять лишь выделенную таблицу: после перезагрузки в таком случае могут отсутствовать прежние правила для рабочих сервисов.

Сохранение постоянной конфигурации — это второе изменение. Заново запланируйте откат, загрузите полный загрузочный файл и повторите проверку отдельным входом. Не объединяйте включение службы, замену конфигурации и перезагрузку сервера в одну команду. Проверку после перезагрузки запланируйте отдельно; проверьте правила, вход из разрешённого источника и доступность рабочих сервисов.

В завершение зафиксируйте фактический адрес источника, порт SSH, файл с предлагаемыми правилами, снимок и результаты проверки. Основание для принятия изменений — не «команда завершилась успешно», а одновременное выполнение трёх условий: новые подключения проходят, блокировка работает ожидаемым образом, а загрузочная конфигурация воспроизводит правила.

Часто задаваемые вопросы

Можно ли отменить откат, если прежний сеанс SSH продолжает работать?

Нет. Правило отслеживания состояния может пропускать уже установленное соединение. Сначала требуется отдельное новое подключение с разрешённого адреса и успешная аутентификация.

Закрывают ли приведённые правила порты приложений?

Нет. Ограничиваются только новые подключения к фактически используемому порту SSH. Остальные порты обрабатываются существующими правилами; пример не является полной политикой запрета по умолчанию.

Выделенный сервер EPYC 7543Pот $450.2/мес.

От выбора ресурсов до настройки сервера

Стоимость модели и дополнительных опций рассчитывается за месяц; полный перечень компонентов указан на странице конфигурации. Данные для подключения доступны в консоли после выдачи сервера.