Брандмауэр на VPS: UFW для Ubuntu и Debian, firewalld для AlmaLinux
Закрываем всё, кроме нужных портов, разрешаем SSH только со своего IP и разбираемся, почему Docker обходит UFW.

Брандмауэр решает, какие входящие соединения сервер примет, а какие молча отбросит. Снаружи должны быть видны только те сервисы, которыми вы действительно пользуетесь. Обычно это:
- SSH — порт 22 или ваш, если меняли;
- сайт — 80 и 443;
- VPN или прокси — порты конкретной программы.
Всё остальное — базы данных, панели, Redis, служебные порты приложений — наружу торчать не должно.
Сначала разрешите SSH, потом включайте брандмауэр. Если включить с пустым списком правил, текущая сессия, скорее всего, выживет, а следующая уже не подключится. Выполняйте команды строго по порядку.
Ubuntu и Debian: UFW
sudo apt update
sudo apt install -y ufw
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status verbose

На вопрос о возможном обрыве SSH при включении отвечайте y: порт 22 уже разрешён.
Полезные команды:
sudo ufw status numbered # правила с номерами
sudo ufw delete 3 # удалить правило №3
sudo ufw allow 8080/tcp # открыть ещё порт
sudo ufw limit 22/tcp # не больше 6 подключений за 30 с с одного IP
sudo ufw disable # выключить (правила сохраняются)
ufw limit — простейшая защита от перебора без fail2ban: после шести попыток за полминуты IP временно блокируется.
AlmaLinux, Rocky, CentOS: firewalld
sudo dnf install -y firewalld
sudo systemctl enable --now firewalld
sudo firewall-cmd --list-all
SSH в зоне public обычно разрешён по умолчанию, убедитесь в этом по выводу. Добавьте веб:
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload
Произвольный порт:
sudo firewall-cmd --permanent --add-port=8080/tcp
sudo firewall-cmd --reload
Без --permanent правило живёт до перезагрузки; без --reload постоянное правило не применяется сразу. Нужны оба.
SSH только с вашего IP
Самая сильная мера: порт 22 не виден никому, кроме вас. Свой адрес узнайте любым сервисом вроде «мой IP».
Только при постоянном IP. У домашних и мобильных провайдеров адрес меняется, и однажды вы окажетесь снаружи. Если не уверены — пропустите этот раздел и ограничьтесь
ufw limitи fail2ban.
UFW:
sudo ufw allow from ВАШ_IP to any port 22 proto tcp
sudo ufw delete allow 22/tcp
sudo ufw status
firewalld:
sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="ВАШ_IP" port port="22" protocol="tcp" accept'
sudo firewall-cmd --permanent --remove-service=ssh
sudo firewall-cmd --reload
Docker обходит UFW
Важная ловушка. Когда контейнер публикует порт через -p 8080:80 или ports: в Compose, Docker добавляет собственные правила iptables, и они срабатывают раньше UFW. Порт будет открыт на весь интернет, хотя в ufw status его нет.
Правило простое: всё, что не должно быть публичным, публикуйте только на локальный интерфейс:
docker run -d -p 127.0.0.1:8080:80 nginx
В Compose — "127.0.0.1:8080:80". Наружу выходят только 80 и 443 обратного прокси. Базы данных (MySQL, PostgreSQL, Redis) внутри одного Compose-проекта вообще не нуждаются в публикации портов: контейнеры видят друг друга по именам сервисов.
Проверить, что реально слушает сервер:
sudo ss -tlnp

Строки с 0.0.0.0:ПОРТ и [::]:ПОРТ открыты миру, 127.0.0.1:ПОРТ — только локально.
Если отрезали себе доступ
Зайдите через консоль в кабинете tanaka.host и временно выключите брандмауэр:
sudo ufw disable # UFW
sudo systemctl stop firewalld # firewalld
Поправьте правила и включите обратно. Следующий шаг — автообновления и fail2ban.