UFW: настройка фаервола

«Запереть дверь — ещё не значит обезопасить дом. Но оставить её открытой — значит, гарантированно потерять всё, что внутри. — Воланд»

Введение

Настоящее руководство описывает установку и настройку фаервола UFW (Uncomplicated Firewall) — фронтенда к iptables/nftables, который является стандартным средством защиты сетевого периметра в Ubuntu.

Мы начинаем с сервера, на котором уже выполнены предыдущие шаги: SSH работает (порт 22022, только ключи), пользователь uservpn имеет sudo без пароля, базовая система настроена (локаль, часовой пояс, hostname, swap).

Цель данного руководства — закрыть все входящие сетевые порты, кроме тех, которые действительно нужны, и настроить rate limiting для SSH.

Все шаги пронумерованы и должны выполняться в указанном порядке. Перескакивать не рекомендуется.

Входные данные: вы подключены к серверу по SSH пользователем uservpn на порт 22022. Команды с sudo не запрашивают пароль.


Раздел 1. Что такое фаервол и зачем он нужен

1.1. Краткая теория

Фаервол (брандмауэр, межсетевой экран) — компонент операционной системы, который фильтрует сетевой трафик по заданным правилам. Он решает, какие пакеты пропустить, какие заблокировать, а какие ограничить по частоте.

Без фаервола все порты сервера открыты для всего интернета. Любой сканер, ботнет или любопытный прохожий может попытаться подключиться к любому сервису. Это как оставить входную дверь квартиры открытой и надеяться, что никто не войдёт.

1.2. Почему UFW

В Linux существует несколько уровней фильтрации:

Уровень Инструмент Сложность
Ядро (netfilter) iptables / nftables Высокая — десятки параметров в одной команде
Обёртка UFW Низкая — понятные команды вида ufw allow 22/tcp
Обёртка над UFW firewalld Средняя — зоны, сервисы, динамические правила

UFW — выбор по умолчанию для Ubuntu. Он не заменяет iptables, а упрощает работу с ним: за каждой командой ufw стоит набор правил iptables/nftables, которые UFW генерирует автоматически.

1.3. Какие порты должны быть открыты

На нашем сервере работают следующие сервисы, требующие сетевого доступа:

Порт Протокол Правило Сервис Назначение
22022 TCP LIMIT SSH Удалённый доступ (rate limit — защита от брутфорса)
80 TCP ALLOW Nginx HTTP — Let's Encrypt validation + редирект на HTTPS
443 TCP ALLOW Xray (VLESS + Reality) VPN-туннель, маскируется под обычный HTTPS
8443 TCP ALLOW Nginx (Grav CMS) Блог на psj-notes.ru
4443 TCP ALLOW Nginx (x-ui dashboard) Панель управления VPN (Basic Auth)
2096 TCP ALLOW VLESS-Reality Альтернативный порт VPN (резерв)

Все остальные входящие соединения — заблокированы. Исходящие — разрешены без ограничений (сервер должен иметь возможность скачивать обновления, отправлять почту и т.д.).

Коровьев, разглядывая таблицу портов:
«Шесть открытых дверей из сотен возможных. Остальные — наглухо заперты. И заметьте, гражданин: даже в этих шести есть засовы, цепочки и глазок. Квартирный вопрос, как известно, испортил не только москвичей, но и всех, кто пытается зайти на сервер без приглашения.»


Раздел 2. Установка UFW

2.1. Проверка наличия

В некоторых образах Ubuntu UFW уже установлен. Проверим:

sudo ufw version

Если команда выводит версию (например, ufw 0.36.2) — пакет установлен. Если видите command not found — устанавливаем.

2.2. Установка

sudo apt install -y ufw

После установки проверьте, что UFW доступен:

sudo ufw status

Ожидаемый вывод:

Status: inactive

Важно: UFW не активен после установки. Это правильно — сначала настраиваем правила, потом включаем. Если включить фаервол без правил — он заблокирует всё, включая текущую SSH-сессию.


Раздел 3. Настройка политик по умолчанию

3.1. Что такое политики по умолчанию

Политика по умолчанию (default policy) — правило, которое применяется к пакетам, не подошедшим ни под одно конкретное правило. UFW поддерживает две политики:

Политика Поведение
allow Пропускать всё, что не запрещено явно
deny Блокировать всё, что не разрешено явно

Для сервера единственно правильный выбор — deny для входящих, allow для исходящих. Это называется «белый список»: разрешено только то, что мы явно указали.

3.2. Установка политик

sudo ufw default deny incoming
sudo ufw default allow outgoing

Ожидаемый вывод каждой команды:

Default incoming policy changed to 'deny'
(be sure to update your rules accordingly)

3.3. Проверка

sudo ufw status verbose

Ожидаемый вывод (пока без правил):

Status: inactive
Default: deny (incoming), allow (outgoing), deny (routed)

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


Раздел 4. Настройка логирования

4.1. Зачем логировать

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

4.2. Установка уровня логирования

sudo ufw logging low

Уровни логирования:

Уровень Что записывает Когда использовать
off Не записывает ничего Никогда — вы останетесь слепыми
low Только заблокированные пакеты Рекомендуется для продакшена
medium Заблокированные + разрешённые + rate limit Для отладки
high medium + дополнительная информация Для глубокой диагностики
full Всё, включая фрагментированные пакеты Только при расследовании инцидентов

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


Раздел 5. Добавление правил

5.1. Правило 1: SSH (порт 22022) с rate limiting

sudo ufw limit 22022/tcp

Что делает limit: разрешает подключения, но блокирует IP-адрес, если с него поступает более 6 новых соединений за 30 секунд. Это защита от брутфорса на уровне фаервола — дополнительный рубеж после Fail2ban.

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

5.2. Правило 2: HTTP (порт 80)

sudo ufw allow 80/tcp

Порт 80 нужен для двух вещей:

  1. Let's Encrypt validation — Certbot ставит challenge-файлы в .well-known/acme-challenge/ и проверяет их доступность по HTTP. Без открытого 80-го порта продление сертификатов не работает.
  2. Редирект на HTTPS — Nginx принимает HTTP-запросы и перенаправляет их на HTTPS. Пользователь вводит http://psj-notes.ru — получает https://psj-notes.ru.

5.3. Правило 3: VLESS + Reality (порт 443)

sudo ufw allow 443/tcp

Порт 443 — стандартный HTTPS. На нашем сервере его слушает Xray с протоколом VLESS + Reality. Для внешнего наблюдателя это выглядит как обычный HTTPS-сайт: трафик шифруется, SNI указывает на psj-notes.ru. Только клиент с правильным конфигурационным файлом получит доступ к VPN-туннелю.

5.4. Правило 4: Grav CMS (порт 8443)

sudo ufw allow 8443/tcp

Порт 8443 — HTTPS-виртуальный хост Nginx для блога Grav CMS. Доступен по адресу https://psj-notes.ru:8443.

5.5. Правило 5: Панель управления (порт 4443)

sudo ufw allow 4443/tcp

Порт 4443 — HTTPS-виртуальный хост Nginx для дашборда и панели x-ui. Защищён Basic Auth (логин + пароль). Доступен по адресу https://consol.psj-notes.ru:4443.

5.6. Правило 6: VLESS-Reality резерв (порт 2096)

sudo ufw allow 2096/tcp comment 'VLESS-Reality'

Порт 2096 — альтернативный порт для VPN-подключений. Полезен, если основной порт 443 по какой-то причине недоступен или занят другим сервисом.

Коровьев, подсчитывая правила на пальцах:
«Шесть правил — шесть дверей. Каждая с замком, каждая с охраной. И ни одной лишней. Заметьте: мы не открыли ни порта для базы данных, ни для FTP, ни для чего-нибудь экзотического. Если серверу это не нужно — дверь остаётся запертой.»


Раздел 6. Включение фаервола

6.1. Предварительная проверка

Перед включением убедитесь, что правило для SSH (порт 22022) добавлено:

sudo ufw status

Ожидаемый вывод:

Status: inactive

To                         Action      From
--                         ------      ----
22022/tcp                  LIMIT       Anywhere
80/tcp                     ALLOW       Anywhere
443/tcp                    ALLOW       Anywhere
8443/tcp                   ALLOW       Anywhere
4443/tcp                   ALLOW       Anywhere
2096/tcp                   ALLOW       Anywhere

Критично: если в списке нет правила для порта 22022 — не включайте фаервол. Вы потеряете SSH-доступ. Вернитесь к разделу 5.1 и добавьте правило.

6.2. Включение

sudo ufw --force enable

Флаг --force подашивает предупреждение о возможном разрыве SSH-соединения. Поскольку мы уже добавили правило для SSH, предупреждение нам не нужно.

Ожидаемый вывод:

Firewall is active and enabled on system startup

6.3. Проверка

sudo ufw status verbose

Ожидаемый вывод:

Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), deny (routed)
New profiles: skip

To                         Action      From
--                         ------      ----
22022/tcp                  LIMIT IN    Anywhere
80/tcp                     ALLOW IN    Anywhere
443/tcp                    ALLOW IN    Anywhere
8443/tcp                   ALLOW IN    Anywhere
4443/tcp                   ALLOW IN    Anywhere
2096/tcp                   ALLOW IN    Anywhere
22022/tcp (v6)             LIMIT IN    Anywhere (v6)
80/tcp (v6)                ALLOW IN    Anywhere (v6)
443/tcp (v6)               ALLOW IN    Anywhere (v6)
8443/tcp (v6)              ALLOW IN    Anywhere (v6)
4443/tcp (v6)              ALLOW IN    Anywhere (v6)
2096/tcp (v6)              ALLOW IN    Anywhere (v6)

Обратите внимание: UFW автоматически создал правила и для IPv6 (строки с v6). Это правильно — если IPv6 включён, фаервол должен защищать оба стека.


Раздел 7. Проверка работы

7.1. Не закрывайте текущую SSH-сессию

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

ssh -p 22022 uservpn@<IP-АДРЕС-СЕРВЕРА>

Если подключились — фаервол не блокирует SSH. Если нет — вернитесь в старую сессию и проверьте правила.

7.2. Проверка заблокированных соединений

Попробуйте подключиться к порту, который не открыт (например, 3306 — MySQL):

nc -zv <IP-АДРЕС-СЕРВЕРА> 3306

Ожидаемый результат:

nc: connect to <IP-АДРЕС-СЕРВЕРА> port 3306 (tcp) failed: Connection refused

Или таймаут — это означает, что фаервол блокирует соединение.

7.3. Просмотр логов UFW

Заблокированные попытки подключений записываются в системный журнал:

sudo dmesg | grep -i 'UFW BLOCK' | tail -5

Или через journalctl:

sudo journalctl -k | grep 'UFW BLOCK' | tail -5

Пример записи:

[UFW BLOCK] IN=eth0 OUT= MAC=... SRC=1.2.3.4 DST=194.50.94.224 ... DPT=3306 ...

Здесь SRC — IP-адрес источника (сканера), DPT — порт, к которому он пытался подключиться.

Воланд, просматривая логи:
«Вот видите — уже кто-то стучится в порт 3306. А MySQL у нас даже не установлен. Фаервол вежливо ответил: „Нет, сударь, здесь такого нет." И записал в журнал — для потомков. Через неделю таких записей будет тысячи. Это нормально. Интернет — место шумное.»


Раздел 8. Управление правилами

8.1. Просмотр правил с номерами

sudo ufw status numbered

Ожидаемый вывод:

Status: active

     To                         Action      From
     --                         ------      ----
[ 1] 22022/tcp                  LIMIT IN    Anywhere
[ 2] 80/tcp                     ALLOW IN    Anywhere
[ 3] 443/tcp                    ALLOW IN    Anywhere
[ 4] 8443/tcp                   ALLOW IN    Anywhere
[ 5] 4443/tcp                   ALLOW IN    Anywhere
[ 6] 2096/tcp                   ALLOW IN    Anywhere

Номера правил нужны для удаления.

8.2. Удаление правила

Чтобы удалить правило, укажите его номер:

sudo ufw delete <номер>

Например, удалить правило 6 (порт 2096):

sudo ufw delete 6

Система спросит подтверждение:

Deleting:
  allow 2096/tcp comment 'VLESS-Reality'
Proceed with operation (y|n)? y

8.3. Удаление правила по описанию

Альтернативный способ — указать правило текстом:

sudo ufw delete allow 2096/tcp

8.4. Сброс всех правил

Если нужно начать заново:

sudo ufw reset

Это удалит все пользовательские правила и вернёт политики по умолчанию. Фаервол останется включённым.

Предупреждение: после reset правило для SSH будет удалено. Перед повторным включением добавьте его заново.


Раздел 9. Сводная таблица правил

Порт Протокол Правило Назначение Комментарий
1 22022 TCP LIMIT SSH Rate limit — макс. 6 соединений за 30 сек
2 80 TCP ALLOW HTTP Let's Encrypt + редирект на HTTPS
3 443 TCP ALLOW VLESS + Reality VPN-туннель (Xray)
4 8443 TCP ALLOW Grav CMS Блог на psj-notes.ru
5 4443 TCP ALLOW x-ui dashboard Панель управления (Basic Auth)
6 2096 TCP ALLOW VLESS-Reality Резервный порт VPN

Политики по умолчанию: входящие — deny, исходящие — allow.

Логирование: low (только заблокированные пакеты).


Раздел 10. Итоги

На данном этапе мы имеем:

Что Статус
UFW установлен
Политика по умолчанию: deny incoming
Политика по умолчанию: allow outgoing
Логирование: low
SSH (22022) — rate limit
HTTP (80) — разрешён
VLESS (443) — разрешён
Grav CMS (8443) — разрешён
x-ui dashboard (4443) — разрешён
VLESS резерв (2096) — разрешён
Фаервол активен

Следующее руководство: настройка Fail2ban — три тюрьмы для SSH: sshd, sshd-ddos, recidive.


Конец документа. Настроившему — спокойный сон, забывшему правило SSH — да поможет ufw reset и веб-консоль провайдера.