UFW придумали, щоб брандмауер налаштовувався трьома командами, і з цим він справляється. Проблема в іншому: ufw status показує наміри, а не результати. Правило може бути в списку й не закривати геть нічого — з трьох різних причин, і всі вони регулярно трапляються на реальних серверах.
Початок, який не замикає вас зовні
Порядок команд має значення. Спершу дозвольте SSH, потім вмикайте:
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow OpenSSH
sudo ufw enable
ufw enable до дозволу SSH відрізає вашу ж сесію, і далі лишається тільки консоль провайдера. Якщо сервер уже налаштований, а ви не впевнені, тримайте друге з’єднання відкритим — воно переживе невдалу правку.
Дивіться докладний статус; короткий приховує типову політику:
sudo ufw status verbose
Помилка перша: правило є, а порт відкрито світові
Найчастіший рядок у чужих конфігураціях:
sudo ufw allow 3306
Так відкривають MySQL, «щоб підключатися з дому», — і відкривають усьому інтернету. Правильних варіантів два, і обидва кращі:
sudo ufw allow from 203.0.113.25 to any port 3306
або, надійніше, взагалі не випускати службу назовні: bind-address = 127.0.0.1 у конфігурації MySQL, а зовнішній доступ — через SSH-тунель. Брандмауер — друга лінія; перша полягає в тому, що служба не слухає на публічній адресі. Правило в UFW можна видалити помилково, а bind-address сам собою не змінюється.
Помилка друга: IPv6
Правило на кшталт ufw allow from 203.0.113.25 стосується лише IPv4. Якщо в сервера є адреса IPv6 — а в більшості VPS вона є й увімкнена — служба лишається доступною через неї. Провайдер видав адресу, ви її не пам’ятаєте, а сканер пам’ятає.
Перевірте, чи ввімкнено фільтрацію v6 взагалі (IPV6=yes у /etc/default/ufw) і чи не слухає служба на :: без потреби:
ss -tulpn | grep ':::'
Правила, що явно називають адресу, доводиться писати окремо для кожної версії протоколу.
Помилка третя: Docker
Найприкріша. Docker публікує порти, додаючи власні правила в ланцюжки iptables перед тими, що пише UFW. У результаті контейнер, запущений з -p 5432:5432, доступний з інтернету, хоча UFW рапортує Status: active і політику deny incoming. Брандмауер не зламаний — до нього просто не доходить черга.
Лікування не в UFW, а в тому, як публікується порт:
ports:
- "127.0.0.1:5432:5432"
Прив’язка до локальної адреси — найпростіше й найнадійніше рішення. Назовні має дивитися лише те, що справді обслуговує відвідувачів: зазвичай порти 80 і 443 зворотного проксі.
Порядок правил
UFW застосовує перше правило, що збіглося, і на цьому зупиняється. Тому заборона, додана після дозволу, не спрацює: до неї просто не дійде черга. Подивіться нумерацію і вставте там, де потрібно:
sudo ufw status numbered
sudo ufw insert 1 deny from 198.51.100.0/24
sudo ufw delete 7
Правила видаляються за номером, але номери зсуваються після кожного видалення — видаляйте по одному й перечитуйте список.
Перевірка ззовні
Локальні команди показують, що налаштовано. Що вийшло насправді, видно лише з іншої машини:
nmap -Pn -p- 203.0.113.25
nc -zv 203.0.113.25 3306
Підійде будь-який інший сервер або ваш домашній комп’ютер. Це єдина перевірка, яка не бреше, і запускати її варто після кожної помітної переналаштування — особливо після встановлення чогось, що «саме налаштовує мережу»: Docker, панелі керування, VPN.
Журнали
Типово UFW майже нічого не пише. Вмикається це так:
sudo ufw logging low
Записи йдуть у /var/log/ufw.log — але лише якщо в системі є rsyslog. На Debian 12 і Ubuntu 24.04 його може не бути, і тоді все йде в журнал systemd:
sudo journalctl -k | grep -i '\[UFW'
Порожній /var/log/ufw.log сам собою не означає нічого — спершу подивіться в журнал.
Чого чекати від брандмауера
UFW закриває те, що не має бути доступним. Він не перевіряє вміст запитів до того, що відкрито: порт 443 відкритий усім, і що б не прийшло на сайт, воно приходить безперешкодно. Це робота інших інструментів — WAF на рівні застосунку, IDS на рівні трафіку. Завдання брандмауера скромніше й важливіше: щоб список відкритих портів збігався з тим, у що ви щодо нього вірите. Який вигляд цей список має разом з активними правилами на одній сторінці, показує демо нижче.