/posts/complete-firewall-setup-for-vps

$ cat post.md

practice

Как настроить firewall на VPS и не отрезать себе доступ

Практический разбор настройки firewall на Linux-сервере: какие порты открывать, как работать с ufw, как не заблокировать SSH и как думать о сетевой защите без лишнего пафоса.

Когда люди впервые доходят до настройки firewall на VPS, они часто думают о нём как о какой-то отдельной “безопасной штуке”, которую надо просто однажды включить. На практике firewall полезен не потому, что делает сервер магически защищённым, а потому, что уменьшает поверхность атаки и делает сетевое поведение сервера понятным.

Если у тебя на сервере реально нужны только 22, 80 и 443, то идея открыть всё подряд “на всякий случай” уже выглядит как плохая дисциплина.

Что firewall вообще решает

На маленьком VPS firewall обычно решает очень приземлённые задачи:

  • закрывает все лишние входящие порты;
  • оставляет только нужные сервисы;
  • уменьшает количество мусорного трафика;
  • делает сетевую конфигурацию сервера предсказуемой;
  • создаёт ещё один слой защиты поверх SSH hardening, fail2ban и обновлений.

Важно понимать границы:

  • firewall не заменяет fail2ban;
  • firewall не исправляет слабые пароли;
  • firewall не спасает от уязвимого приложения, если нужный порт уже открыт;
  • firewall не заменяет нормальную настройку nginx, Docker и SSH.

Он просто решает свою часть задачи: кто вообще может достучаться до чего по сети.

Почему новичок часто ломает сервер именно на firewall

Потому что самая частая ошибка выглядит очень просто:

  1. человек заходит на сервер по SSH;
  2. включает firewall;
  3. забывает заранее разрешить 22;
  4. закрывает собственную сессию;
  5. больше не может подключиться.

Вторая типичная ошибка: открыть firewall “широко”, а потом считать, что безопасность уже настроена.

Например:

  • открыть весь диапазон портов;
  • пробросить наружу сервисы, которые должны быть локальными;
  • забыть, что контейнер или база теперь доступны снаружи.

Как я бы думал о firewall на обычном VPS

Если сервер держит сайт вроде блога, то нормальная базовая модель такая:

  • 22/tcp — SSH;
  • 80/tcp — HTTP;
  • 443/tcp — HTTPS;
  • всё остальное закрыто.

Если приложение слушает 127.0.0.1:8080, а наружу его публикует только nginx, то порт 8080 вообще не должен быть открыт в интернет.

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

Почему я бы выбрал ufw

На Ubuntu для небольшого проекта я бы почти всегда начал с ufw.

Не потому, что это “самый мощный firewall”, а потому что он:

  • достаточно простой;
  • хорошо подходит для VPS;
  • закрывает типовые задачи без ручного копания в iptables/nftables;
  • делает правила понятными даже через месяц.

Если ты только входишь в Linux и сетевую часть, ufw — это хороший способ научиться базовой дисциплине, а не сразу тонуть в низкоуровневых правилах.

Установка и базовая проверка

На Ubuntu:

sudo apt update
sudo apt install -y ufw

Проверить текущий статус:

sudo ufw status verbose

Если firewall ещё не включён, ты увидишь что-то вроде:

Status: inactive

Это нормально. Сначала задаём правила, потом включаем.

Базовая безопасная настройка для веб-сервера

Самый практичный стартовый набор:

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

Что здесь происходит:

  • default deny incoming — по умолчанию всё входящее запрещено;
  • default allow outgoing — серверу разрешено ходить наружу;
  • allow OpenSSH — не отрезаем себе SSH;
  • allow 80/tcp — разрешаем HTTP;
  • allow 443/tcp — разрешаем HTTPS.

После этого можно включать firewall:

sudo ufw enable

И снова проверить:

sudo ufw status verbose

Ожидаемая картина будет примерно такой:

Status: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
80/tcp                     ALLOW       Anywhere
443/tcp                    ALLOW       Anywhere
OpenSSH (v6)               ALLOW       Anywhere (v6)
80/tcp (v6)                ALLOW       Anywhere (v6)
443/tcp (v6)               ALLOW       Anywhere (v6)

Как проверить, что не сломал себе доступ

Вот здесь многие совершают ошибку: смотрят на ufw status, успокаиваются и считают работу законченной.

Правильная проверка такая:

  1. не закрывая текущую SSH-сессию, открыть новую;
  2. убедиться, что вход по SSH по-прежнему работает;
  3. проверить сайт снаружи;
  4. проверить, что лишние порты не торчат.

Практически:

ssh deploy@your-server-ip
curl -I http://your-domain.com
curl -I https://your-domain.com
ss -tulpn

Команда ss -tulpn не показывает firewall rules. Она показывает, что вообще слушает порты на сервере. А дальше уже ты сравниваешь:

  • что слушает процесс;
  • что разрешает firewall;
  • что реально должно быть доступно снаружи.

Как мыслить про открытые порты

Очень полезно разделять три разных вопроса:

  1. какой процесс слушает порт;
  2. на каком интерфейсе он слушает;
  3. разрешён ли вход к нему firewall’ом.

Например:

  • приложение слушает 127.0.0.1:8080;
  • nginx слушает 0.0.0.0:80 и 0.0.0.0:443;
  • firewall разрешает только 22, 80, 443.

Это хорошая модель.

Плохая модель:

  • приложение слушает 0.0.0.0:8080;
  • база слушает наружу;
  • firewall “временно” разрешает всё;
  • никто уже не помнит, что из этого реально нужно.

Что делать с Docker

Это важный момент. Когда на сервере появляется Docker, люди часто думают, что firewall уже всё контролирует. Но Docker умеет добавлять свои сетевые правила, и это может вести себя не так, как ожидает новичок.

Практически важно помнить:

  • если сервис опубликован Docker наружу, он может стать доступным помимо той картины, которую ты у себя в голове нарисовал;
  • особенно внимательно надо смотреть на ports: в docker-compose.yml;
  • хороший паттерн для маленького продового сервера — публиковать приложение только на 127.0.0.1, а наружу отдавать его через host nginx.

Например так:

ports:
  - "127.0.0.1:8080:80"

Это намного спокойнее, чем:

ports:
  - "8080:80"

Во втором случае порт торчит наружу на всех интерфейсах.

Как посмотреть текущие правила

Полезные команды:

sudo ufw status numbered
sudo ufw status verbose
sudo ufw show added

status numbered особенно удобен, когда нужно удалить правило по номеру.

Например:

sudo ufw delete 3

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

Как открыть доступ не для всех

Иногда не хочется просто “разрешить порт”, а нужно ограничить доступ по IP.

Например, ты хочешь оставить SSH только для своего адреса:

sudo ufw allow from 203.0.113.10 to any port 22 proto tcp

Это уже более строгий вариант, чем просто:

sudo ufw allow OpenSSH

Но у такого подхода есть цена:

  • если IP у тебя меняется;
  • если заходишь из разных мест;
  • если работаешь из мобильного интернета;

то можно случайно закрыть себе доступ.

Для личного VPS это не всегда удобно. Поэтому я бы делал такую настройку только если понимаешь, как будешь с этим жить дальше.

Что ещё стоит проверить после включения firewall

Я бы не ограничивался только ufw status.

Хороший короткий чеклист:

  • sudo ufw status verbose
  • ss -tulpn
  • curl -I http://your-domain.com
  • curl -I https://your-domain.com
  • sudo systemctl status nginx --no-pager
  • docker ps, если сайт в контейнере

И отдельно полезно посмотреть:

sudo journalctl -u ufw -n 50 --no-pager

Или хотя бы общие системные логи, если что-то пошло не так.

Что я бы не делал

Вот несколько вещей, которые выглядят как “быстрая настройка”, но на деле создают плохую эксплуатацию:

  • не открывал бы порт приложения наружу, если можно ограничиться 127.0.0.1;
  • не включал бы firewall до разрешения SSH;
  • не держал бы временные правила неделями;
  • не считал бы firewall полной заменой остальной безопасности;
  • не копировал бы длинные наборы правил без понимания, зачем они нужны.

Очень часто хорошая сетевая конфигурация — это не большое количество правил, а маленькое количество правильных правил.

Минимальная рабочая схема для небольшого блога или pet-проекта

Если свести всё к практическому минимуму, то на типичном VPS под сайт я бы хотел видеть именно это:

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable

Плюс:

  • SSH по ключу;
  • PermitRootLogin no;
  • PasswordAuthentication no;
  • fail2ban;
  • приложение, опубликованное только локально;
  • внешний nginx, который работает как reverse proxy.

Это не “максимальная защита”, но уже очень хороший и взрослый baseline для небольшого проекта.

Вывод

Настройка firewall не требует драматизации. Для маленького продового сервера это не про десятки хитрых правил, а про дисциплину:

  • явно определить, какие порты реально нужны;
  • закрыть всё остальное;
  • не торчать лишними сервисами наружу;
  • проверять результат не по ощущениям, а командами.

Если коротко, то хороший firewall на VPS — это не “сложная безопасность”, а аккуратная привычка держать сетевую поверхность как можно уже.

$ cat /etc/motd

infraTales

Личный блог о DevOps, инфраструктуре, инструментах и инженерной практике.