Безопасность нового VPS: настройка SSH, firewall, Fail2Ban и обновлений сразу после запуска сервера.
Новый VPS привлекает ботов быстрее, чем кажется: безопасность сервера на старте низка. Провайдер берёт на себя изоляцию на уровне гипервизора и сетевую связность. Всё, что выше ОС, остаётся зоной ответственности клиента.
Что провайдер защищает, а что – нет
Хостинг-провайдер отвечает за физическую инфраструктуру, гипервизор и сетевую изоляцию между машинами. Операционная система, открытые порты, учётные записи и конфигурации сервисов остаются зоной ответственности администратора.
После выдачи машины проверьте стартовые настройки доступа: на части образов всё ещё может быть открыт root-доступ по паролю, SSH часто принимает соединения на стандартном порту 22, а пакеты могут требовать обновления. У многих современных провайдеров вход по паролю или под root уже отключён по умолчанию, но это нельзя считать универсальным правилом. Автоматические сканеры добираются до нового сервера в течение нескольких минут после получения публичного IP.
Baseline: минимум для нового VPS
Настройка VPS начинается не с деплоя приложения. Базовый харденинг нового сервера занимает 15–30 минут и снижает риск типовых атак: брутфорса SSH, сканирования открытых портов и эксплуатации устаревших пакетов.
Создайте непривилегированного пользователя с sudo и настройте аутентификацию по SSH-ключу. Root-логин по паролю отключите в /etc/ssh/sshd_config директивой PermitRootLogin no. Смена стандартного порта SSH снижает шум от автоматических сканеров.
Firewall и fail2ban
Настройте ufw или iptables: разрешите только нужные порты, остальное заблокируйте. Утилита fail2ban автоматически банит IP после серии неудачных попыток входа и хорошо дополняет правила firewall.
Автообновления и мониторинг логов
Включите unattended-upgrades для автоматической установки обновлений безопасности. Периодический просмотр /var/log/auth.log и вывода journalctl помогает заметить подозрительную активность до того, как она перерастёт в инцидент.
Чек-лист baseline-настроек
• Создан непривилегированный пользователь с sudo
• Root-логин по паролю отключён
• SSH-аутентификация переведена на ключи
• При необходимости изменён стандартный порт SSH
• ufw или iptables настроен, лишние порты закрыты
• fail2ban установлен и активен
• unattended-upgrades включен
Baseline не заменяет полноценный аудит конфигурации, но снижает риск типовых атак. Примените чек-лист сразу после получения доступа к серверу. В блоге Aeza выходят материалы по серверной безопасности, следите за новыми разборами.
Pеклама. ООО «Аеза Групп», ИНН: 7813654490. erid:2Ranynrk3BH
Fail2Ban запущен, jail sshd есть в списке, а попытки входа всё равно появляются в журнале. С разных адресов они могут приходить и при работающей защите, так как Fail2Ban считает ошибки для каждого адреса отдельно. Сам по себе статус службы не значит, что она блокирует подключения. Программа должна получить запись о неудачном входе, распознать её и передать адрес в сетевой экран. Проверять эту цепочку будем на VPS с Ubuntu 24.04. Установку и базовую настройку мы показывали в первой части, а здесь ищем звено, на котором защита перестала работать.
Перед проверкой оставьте открытым рабочий сеанс SSH. Если у провайдера есть консоль в панели, убедитесь, что вы можете через неё войти. Оба пути понадобятся, если правка настроек или тестовый бан закроют доступ.
Журнал SSH
Начните с самого сервера. На Ubuntu журнал службы SSH можно посмотреть так:
Ищите строки об отказах входа, например с Failed password или Invalid user, и адрес, с которого пришло подключение. Если таких строк за выбранное время нет, работу Fail2Ban по журналу пока не проверить: попыток просто не было. Можно повторить проверку после обычной неудачной попытки входа с другого устройства. Не включайте вход по паролю специально ради теста, если он уже отключён.
Запишите адрес клиента из журнала. Он понадобится позже: Fail2Ban считает ошибки и блокирует адрес, который видит SSH. Если вы подключаетесь через промежуточный сервер или общий офисный шлюз, в журнале может оказаться адрес этого узла.
Источник событий Fail2Ban
Теперь проверьте jail sshd и источник событий, который он читает:
sudo fail2ban-client status sshd
В разделе Filter ищите список файлов или Journal matches. Первый вариант означает чтение файлов журнала, второй указывает на systemd journal. Статус без ошибок ещё не подтверждает, что выбранный источник содержит нужные SSH-события.
Что делать, если jail читает не тот журнал?
Если jail читает файлы, узнайте их имена. Для чтения journal посмотрите условие отбора записей:
sudo fail2ban-client get sshd logpath
sudo fail2ban-client get sshd journalmatch
Сравните результат с тем, где вы увидели отказ входа. Если SSH пишет в journal, а jail следит за отсутствующим или неиспользуемым файлом, в уже существующей секции [sshd] файла /etc/fail2ban/jail.local можно указать:
[sshd]
backend = systemd
Строку backend добавляют в существующую секцию, вторую секцию [sshd] создавать не нужно. После правки проверьте конфигурацию и перезапустите службу:
sudo fail2ban-client -t
sudo systemctl restart fail2ban
Если служба сообщает, что не может использовать backend systemd, проверьте наличие пакета python3-systemd. Для чтения journal Fail2Ban нужна библиотека Python для systemd, и без неё одной правки конфигурации недостаточно.
Проверка фильтра
Даже при правильном источнике событий jail может не засчитывать конкретные строки журнала. Для штатного фильтра SSH проверьте совпадения:
sudo fail2ban-regex systemd-journal sshd
Команда читает записи journal и показывает, сколько строк подошло под фильтр sshd. Для сервера, где jail читает файл /var/log/auth.log, укажите вместо systemd-journal этот путь. Проверять нужно тот источник, которым пользуется работающий jail.
Почему фильтр не находит ошибки входа?
Если совпадений нет, сначала убедитесь, что в выбранном источнике есть свежие отказы SSH. Затем сравните сами строки отказов с тем, что ожидает фильтр: после обновления OpenSSH формат записей может измениться, и тогда понадобится более свежий фильтр. Повышать maxretry здесь бессмысленно. Положительное число совпадений тоже требует внимания: команда может найти старые записи. Оно подтверждает работу фильтра на прочитанном журнале, но само по себе ничего не говорит о новых попытках и блокировке подключений.
Пороги и исключения
Когда фильтр распознаёт ошибки, проверьте пороги и исключения, которые действуют сейчас
sudo fail2ban-client get sshd findtime
sudo fail2ban-client get sshd maxretry
sudo fail2ban-client get sshd ignoreip
Fail2Ban блокирует адрес, если за интервал findtime накопилось maxretry подходящих событий. Пять ошибок от пяти разных адресов не складываются в один бан. Если нужный адрес указан в ignoreip, jail его пропустит. Сверяйте исключения с адресом в журнале SSH, особенно после смены сети или провайдера.
Адрес для ignoreip смотрите в журнале SSH либо узнавайте на устройстве, с которого вы входите. Если отправить запрос к сервису определения IP с самого VPS, он покажет внешний адрес сервера. При часто меняющемся адресе постоянное исключение для администратора может оказаться бесполезным. Тогда главным запасным путём остаётся консоль провайдера.
Текущие счётчики и заблокированные адреса снова видны в статусе jail:
sudo fail2ban-client status sshd
Currently failed показывает, сколько адресов сейчас числится с неудачными попытками: они ещё не набрали порог для бана, а их ошибки не вышли за пределы findtime. Общее число учтённых ошибок видно в строке Total failed. После бана или окончания этого интервала значение может стать нулевым. Поэтому один ноль в статусе не значит, что журнал не читается. Сопоставляйте счётчик со временем ошибок и адресами в журнале
Проверка блокировки
Бан в статусе Fail2Ban показывает только решение программы заблокировать адрес. Применил ли его сетевой экран, видно по отказу нового SSH-подключения. Сначала узнайте, какое действие назначено jail:
sudo fail2ban-client get sshd actions
Действие должно соответствовать сетевому экрану, который работает на VPS. По умолчанию, как правило, указано iptables-multiport. В этом случае Fail2Ban держит свои правила в отдельной цепочке f2b-sshd:
sudo iptables -L f2b-sshd -n
Если в списке стоит действие для nftables, его правила можно посмотреть так:
sudo nft list ruleset
Для других действий проверяйте соответствующий сетевой экран. При этом правила в системе не всегда удобно оценивать на глаз, поэтому практичнее проверить новое соединение с отдельного клиента.
Как проверить бан с другого устройства?
Для контрольной проверки нужен клиент из другой сети, например с мобильным интернетом. Второй ноутбук в том же Wi-Fi обычно выходит в интернет с того же публичного адреса, что и основной. До бана убедитесь, что тестовый клиент входит по SSH, а его IP отсутствует в ignoreip.
Оставьте основной доступ к серверу и консоль провайдера. Узнайте внешний IP на тестовом устройстве, а затем на сервере временно заблокируйте именно его. Ниже указан адрес из диапазона для примеров. Перед выполнением замените его на адрес тестового клиента.
sudo fail2ban-client set sshd banip 198.51.100.25
Проверьте, что адрес появился в статусе sshd, и попробуйте открыть с тестового устройства новое SSH-соединение. Уже открытый сеанс может сохраниться. Если вы заблокировали IPv4-адрес, убедитесь, что клиент не подключается к серверу по IPv6. Сразу после этого снимите бан:
sudo fail2ban-client set sshd unbanip 198.51.100.25
Ручной бан проверяет сетевой экран и путь к SSH, но обходит журнал, фильтр и порог. Если он сработал, а автоматических банов всё ещё нет, возвращайтесь к предыдущим шагам. Если статус показывает бан, но новое соединение с того же адреса проходит, проверьте выбранное действие, адрес клиента и порт SSH. При изменённом порте действие может блокировать только стандартный порт 22.
После проверки
Исправляйте первый сбой в цепочке: сначала запись в журнале SSH, затем источник событий и фильтр, после них пороги и действие блокировки. Так легче понять, почему защиты нет, и не менять сразу несколько параметров наугад. Вход по SSH-ключу оставьте в любом случае: Fail2Ban ограничивает повторяющиеся попытки с адреса, но не спасает от слабого пароля или украденного ключа.
Pеклама. ООО «Аеза Групп», ИНН: 7813654490. erid:2RanynJ6y3y
Многие сисадмины сейчас справедливо заметят: «Зачем изобретать велосипед, если можно просто сменить 22-й порт на нестандартный, повесить Fail2Ban, настроить вход только по ключам или вообще спрятать всё за VPN (WireGuard/OpenVPN)?»
Вы абсолютно правы. Это база. Но даже при входе по ключам постоянный фоновый шум от ботов-сканеров, стучащихся в логи, может раздражать. Сегодня хочу напомнить про старый, немного параноидальный, но очень изящный способ защиты — Port Knocking («стук в дверь»).
В чем суть? Ваш SSH-порт аппаратно закрыт фаерволом для всех без исключения. Он «откроется» (и то только для вашего IP-адреса), если вы предварительно «постучитесь» в правильной последовательности по другим закрытым портам. За всем этим следит неприметный демон knockd. Давайте посмотрим, как это настраивается за 5 минут.
Закрываем SSH в iptables Для начала запрещаем кому-либо инициировать новые подключения к нашему любимому 22 порту:
sudo iptables -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -j DROP
Всё. Теперь никто не может даже начать подключение. Сервер притворяется мертвым.
Устанавливаем и настраиваем knockd Ставим сам демон:
sudo apt install knockd
Обязательно делаем бекап дефолтного конфига:
sudo cp /etc/knockd.conf /etc/knockd.conf.bak
Теперь открываем /etc/knockd.conf.
Важный нюанс: вам нужно указать свой сетевой интерфейс (например, eth0 или enp0s3) и заменить команду добавления правила с -A INPUT (добавить в конец) на -I INPUT 1 (вставить первым правилом), иначе фаервол его проигнорирует из-за предыдущих запретов.
Включаем автозапуск Открываем файл /etc/default/knockd, находим строчку START_KNOCKD=0 и меняем её на 1. Запускаем:
sudo systemctl start knockd
Как теперь заходить на сервер? (Стучим с клиента) На свой рабочий компьютер (клиент) тоже ставим утилиту:
sudo apt install knock
Теперь, когда нам нужен доступ к серверу (допустим, его IP 192.168.1.6), мы сначала «стучим» правильную комбинацию:
knock 192.168.1.6 7000 8000 9000
Порт открылся для нашего IP. Спокойно заходим:
ssh admin@192.168.1.6.
После завершения работы закрываем за собой дверь обратной комбинацией:
knock 192.168.1.6 9000 8000 7000
Итог Метод не заменяет SSH-ключи, но работает как отличный дополнительный слой безопасности. SSH полностью скрыт от сканеров портов, логи чистые, а злоумышленники не могут даже начать перебор.
Надеюсь, кому-то эта шпаргалка сэкономит время. Я собираю подобные полезные сниппеты, команды и короткие мануалы по Linux и администрированию в свой Telegram-канал [Linux для Админов и DevOps]. Буду рад видеть там коллег по цеху, заходите!
VPS с открытым SSH-портом быстро замечается ботами. На сервере счётчик неудачных входов набирает сотни попыток в сутки, а на давно засвеченных адресах – тысячи. Боты работают автоматически и не делают перерывов. Настройка VPS без базовой защиты от перебора – прямое приглашение для таких сканеров.
Оценить масштаб можно без внешних сервисов: откройте журналы за сутки и посмотрите, сколько раз повторяются одни и те же адреса или подсети. У нового сервера первые попытки нередко появляются через несколько минут после выдачи публичного IP. Поэтому Fail2Ban лучше ставить сразу после настройки доступа, а не когда перебор уже попал в мониторинг.
Fail2Ban не заменяет SSH-ключи, отключение входа по паролю и аккуратный firewall, но хорошо снимает самый частый шум от bruteforce: видит повторяющиеся ошибки входа и отправляет подозрительные IP в бан. Ниже – рабочая настройка для Ubuntu 22.04/24.04, Debian 11/12, AlmaLinux 9 и CentOS Stream 9: установка, jail.local, защита SSH и проверка результата.
Что такое Fail2Ban и как он работает?
Fail2Ban работает довольно просто. Этот инструмент на Python читает лог-файлы или systemd journal и ищет строки, похожие на неудачную аутентификацию. Совпало регулярное выражение – счётчик для IP увеличился. Набралось maxretry ошибок за findtime – адрес уходит в firewall на время bantime. Когда срок заканчивается, блокировка снимается автоматически.
Отдельный сервис поднимать не нужно, Fail2Ban использует системный firewall: iptables, nftables или firewalld. Вся защита от bruteforce держится на понятной связке: лог, фильтр, порог срабатывания и действие блокировки.
В конфигурации чаще всего встречаются два термина:
Jail – правило для конкретного сервиса: какие события читать, какие строки считать нарушением и что делать после превышения лимита.
Filter – набор failregex, то есть регулярных выражений для поиска нужных строк в логе. Для SSH, nginx, postfix и других популярных сервисов такие фильтры уже лежат в пакете.
Подготовка VPS перед установкой
Правильная настройка VPS сервера начинается с доступа. Перед установкой нужно оставить себе путь назад: несколько действий занимают пару минут, зато помогают не попасть в классический сценарий, когда защита сработала, но заблокировала самого администратора.
Обновите систему:
# Ubuntu/Debian
sudo apt update && sudo apt upgrade -y
# AlmaLinux 9 / CentOS Stream 9
sudo dnf update -y
Узнайте свой текущий внешний IP. Его необходимо добавить в белый список:
Проверьте, что на сервере есть пользователь с sudo. Работать от root не рекомендуется: ошибка в конфиге или случайная команда могут повлиять на весь сервер.
Чек-лист перед установкой
• SSH-доступ работает; запасная сессия открыта или есть KVM/VNC-консоль в панели провайдера
• Если используется UFW на Ubuntu/Debian, проверен его статус: sudo ufw status
• На AlmaLinux 9 / CentOS Stream 9 проверен firewalld: sudo systemctl status firewalld
Установка Fail2Ban на Ubuntu/Debian и AlmaLinux/CentOS
На Ubuntu и Debian пакет есть в стандартном репозитории:
sudo apt install fail2ban -y
/var/log/auth.log может отсутствовать при использовании systemd-journald вместо rsyslog. Если auth.log отсутствует или jail [sshd] не считает попытки входа, задайте backend = systemd. При использовании backend = systemd может потребоваться пакет python3-systemd. На минимальных образах он не всегда установлен:
sudo apt install python3-systemd -y
Проблема с backend может выглядеть так: сервис запущен, jail [sshd] активен, но Currently failed остаётся 0 даже после заведомо ошибочных SSH-входов. В таком случае явно укажите backend = systemd и перезапустите инструмент.
В AlmaLinux 9 и CentOS Stream 9 Fail2Ban обычно ставят через EPEL. Для связки с firewalld понадобится дополнительный пакет fail2ban-firewalld:
sudo dnf install epel-release -y
sudo dnf install fail2ban fail2ban-firewalld -y
На современных системах Fail2Ban также может работать через nftables без fail2ban-firewalld, в зависимости от выбранного banaction.
Запуск и добавление в автозагрузку:
sudo systemctl enable --now fail2ban
Проверка статуса:
sudo systemctl status fail2ban
В статусе нужен Active: active (running). Если сервис упал, первым делом посмотрите последние сообщения unit:
journalctl -u fail2ban -n 50
Базовая конфигурация: jail.local без магии
/etc/fail2ban/jail.conf приходит вместе с пакетом и может измениться после обновления. Свои правила лучше держать в /etc/fail2ban/jail.local: он читается поверх jail.conf и обычно не перезаписывается при обновлениях.
Создаём файл:
sudo nano /etc/fail2ban/jail.local
Секция [DEFAULT] задаёт глобальные параметры для всех jail:
[DEFAULT]
# Адреса из этого списка никогда не блокируются
ignoreip = 127.0.0.1/8 ::1 Ваш_IP
# Время блокировки (s – секунды, m – минуты, h – часы, d – дни)
bantime = 1h
# Временное окно для подсчёта неудачных попыток
findtime = 10m
# Количество неудач до блокировки
maxretry = 5
# Бэкенд чтения логов: auto подходит для большинства систем
backend = auto
ignoreip заполните сразу, до тестов. Добавьте свой IP, а при статическом офисном адресе – ещё и офисную подсеть. Иначе одна серия ошибочных входов может закончиться блокировкой администратора.
bantime определяет срок бана. Десять минут часто слишком мало: бот успевает вернуться с тем же или соседним адресом. Для рабочей SSH-защиты обычно начинают с 1h, а затем повышают до 24h, если ложных срабатываний нет.
findtime и maxretry всегда смотрят вместе. При findtime = 10m и maxretry = 5 адрес блокируется после пяти ошибок за десять минут. Для SSH это нормальный старт: пользователь с опечаткой не страдает, а простой перебор быстро отсекается.
backend = auto автоматически выбирает способ чтения логов в зависимости от окружения. В большинстве случаев этого достаточно, но если SSH-события не обнаруживаются, необходимо указать backend = systemd в нужном jail.
Защита SSH: минимально рабочая конфигурация
Добавьте в jail.local секцию [sshd] для защиты входа по SSH. Обычная настройка fail2ban ssh выглядит так:
[sshd]
# Включаем jail
enabled = true
# Порт SSH (измените, если используете нестандартный)
port = ssh
# Фильтр из /etc/fail2ban/filter.d/sshd.conf
filter = sshd
# Переопределяем глобальные значения для SSH
maxretry = 5
bantime = 24h
Если SSH-события в Ubuntu 24.04 читаются через journal, добавьте в [sshd]:
backend = systemd
Для AlmaLinux 9 и CentOS Stream 9 задайте действие блокировки через firewalld в [DEFAULT] или [sshd]:
# На AlmaLinux / CentOS Stream 9 обычно используется firewalld
banaction = firewallcmd-rich-rules
После правок перезапустите сервис:
sudo systemctl restart fail2ban
Дополнительные jail: nginx, postfix, панели управления
Фильтры для nginx, postfix, dovecot и других сервисов лежат в /etc/fail2ban/filter.d/. Например, для basic auth в nginx можно завести отдельный jail:
[nginx-http-auth]
enabled = true
port = http,https
maxretry = 10
Для ISPmanager, cPanel, Plesk и других панелей универсального фильтра обычно нет. Правила лучше брать из документации панели или репозитория Fail2Ban, а затем прогонять у себя.
Проверка работы и мониторинг
Общий статус всех активных jail:
sudo fail2ban-client status
Статус jail [sshd] показывает, сколько раз правило сработало и какие IP сейчас в бане:
sudo fail2ban-client status sshd
Если sshd не появился в списке jail, чаще всего проблема в jail.local. Проверить конфиг можно без перезапуска:
sudo fail2ban-client -t
Разбанить конкретный IP:
sudo fail2ban-client set sshd unbanip 192.168.1.100
Основной лог – /var/log/fail2ban.log. По строкам Ban и Unban видно, кого заблокировали и когда блокировка закончилась:
sudo tail -50 /var/log/fail2ban.log
Если при реальных атаках строк Ban нет, а Currently failed держится на 0, Fail2Ban смотрит не туда. На системах, где SSH пишет в /var/log/auth.log, фильтр можно проверить так:
Самоблокировка при настройке. Две-три ошибки в пароле – и ваш IP уже в бане. Перед тестами держите открытой запасную сессию. Если доступ пропал, зайдите через KVM/VNC в панели провайдера и снимите блокировку:
sudo fail2ban-client set sshd unbanip Ваш_IP
Неверный backend при использовании systemd journal. Если auth.log отсутствует, а backend оставлен auto, jail может не видеть SSH-события. Итог: Currently failed остаётся 0 при реальных неудачных входах. Обычно помогает backend = systemd в [sshd]; на минимальных образах проверьте python3-systemd.
Конфликт с firewalld на AlmaLinux и CentOS. Без fail2ban-firewalld и banaction блокировки через firewalld баны могут появляться в fail2ban.log, но не попадать в реальные правила firewall. Проверьте rich rules:
sudo firewall-cmd --list-rich-rules
Конфликт с UFW на Ubuntu. Если Fail2Ban использует способ блокировки, который не совпадает с активным firewall, правила могут применяться некорректно. Проверьте выбранный banaction и используйте вариант, соответствующий вашему окружению: UFW, iptables, nftables или firewalld.
Слишком низкий maxretry. Значение 1–2 ловит не только ботов, но и людей с одной опечаткой при вводе пароля. Для SSH начинайте с 3–5 попыток; для веб-сервисов с живыми пользователями ставьте порог выше.
Ложные срабатывания. Если под бан попал легитимный пользователь или сервис, чаще всего виноваты слишком строгий maxretry или неподходящий failregex. На системах с /var/log/auth.log проверьте совпадения фильтра:
Если auth.log нет, смотрите SSH-события через journalctl и используйте backend = systemd. Адреса с постоянным административным доступом добавляйте в ignoreip.
Нет ignoreip для офисных адресов. При смене сети или работе из нескольких локаций риск заблокировать себя выше. Если у офиса статический IP, внесите в ignoreip всю офисную подсеть.
Итоговый чек-лист внедрения
1. Сервис стартует вместе с системой, а systemctl status fail2ban показывает active (running)
2. Пользовательские правила лежат в /etc/fail2ban/jail.local, минимум с секциями [DEFAULT] и [sshd]
3. В ignoreip внесены личный IP и административные подсети
4. bantime задан минимум на 1 час
5. Для систем с SSH-логами в systemd journal в [sshd] указан backend = systemd, а python3-systemd установлен или уже пришёл зависимостью
6. Для AlmaLinux 9 / CentOS Stream 9 установлен fail2ban-firewalld, а banaction работает через firewallcmd-rich-rules
7. fail2ban-client status sshd показывает активный jail и реальные счётчики при неудачных входах
Базовая настройка Fail2Ban обычно занимает 15–20 минут. После этого достаточно изредка проверять логи и whitelist, особенно при смене firewall, офиса или сети. Правильная настройка VPS сервера начинается с таких базовых вещей – ещё до деплоя приложения. Боты не ждут, пока вы закончите.
Облачный инстанс создан, SSH-доступ работает, и первое, что хочется сделать, это запустить приложение. Но новый сервер в этот момент уязвим: root-доступ может быть разрешён, часть пакетов требовать обновления, firewall ещё не настроен, мониторинга нет. Автоматические сканеры находят новые IP-адреса за минуты и начинают перебор паролей ещё до того, как вы откроете второй терминал.
Настройка облачных серверов перед нагрузкой – это четыре конкретных блока: сеть, пользователи и доступ, firewall, мониторинг. Каждый занимает от десяти минут до получаса. Пропустить любой – значит получить дыру в безопасности и эксплуатации.
Разберём все четыре блока по порядку на примере Ubuntu 22.04 LTS. Все команды воспроизводимы и проверены. Порядок шагов важен: каждый следующий опирается на предыдущий. Не запускайте приложение до настройки firewall: незащищённый VPS с открытым SSH быстро попадает под автоматический перебор паролей.
С чего начинается настройка облачного сервера?
Терминал Ubuntu 22.04 с обновлением пакетов, проверкой синхронизации времени, запущенных служб и свободного места на диске.
Прежде чем двигаться дальше, нужно привести систему в актуальное состояние. Образы облачных провайдеров зачастую собираются заранее и поставляются с пакетами недельной или месячной давности. Первое же обновление нередко закрывает десятки CVE, включая критические в OpenSSH и ядре. Выполните:
apt update && apt upgrade -y
Если обновление затронуло ядро – перезагрузите сервер. После перезагрузки убедитесь, что соединение восстановилось, и продолжайте.
Следующий шаг – проверить синхронизацию времени. Расхождение системных часов ломает TLS-рукопожатие, сбивает JWT-токены и делает логи бесполезными при сравнении событий с разных хостов. На Ubuntu 22.04 за это отвечает systemd-timesyncd. Проверьте его статус:
timedatectl status
В строке NTP service должно стоять active. Если нет – включите вручную:
systemctl enable --now systemd-timesyncd
Также сразу посмотрите, что уже запущено на сервере, и сколько свободно дискового пространства. На минимальном образе Ubuntu 22.04 запущено около 25–30 системных сервисов. Если их заметно больше, образ уже преднастроен провайдером:
Если корневой раздел занят более чем на 80%, разберитесь с этим до любых дальнейших шагов: нехватка места ломает обновления пакетов, ротацию логов и запись временных файлов.
Настройка сети на облачном сервере
Терминал Ubuntu 22.04 с проверкой сети, настройкой статического IP через Netplan и изменением имени облачного сервера.
Начните с просмотра текущего состояния сетевых интерфейсов. Две команды дают полную картину: какие интерфейсы подняты, какие IP назначены и куда идёт маршрут по умолчанию.
ip a
ip route show
В выводе ip a найдите интерфейс с публичным IP-адресом – обычно это ens3, ens4 или eth0, в зависимости от провайдера. Запомните его имя: оно понадобится в конфигурации netplan.
На Ubuntu 22.04 сетевые настройки управляются через netplan: конфигурационные файлы лежат в /etc/netplan/. Если провайдер использует cloud-init для автоматической конфигурации сети, в /etc/netplan/ уже может быть файл 50-cloud-init.yaml. Его можно редактировать, но изменения могут быть перезаписаны cloud-init при следующей перезагрузке или пересоздании конфигурации. Безопаснее создать отдельный файл с более высоким приоритетом, например 99-custom.yaml: числа в именах файлов определяют порядок применения, большее число применяется последним и переопределяет предыдущее.
Пример конфигурации со статическим IP (замените значения на реальные):
Терминал Ubuntu 22.04 с применением Netplan и проверкой IP-адреса, маршрута, DNS и внешнего соединения.
Директива addresses задаёт статический IP с маской. routes описывает маршрут по умолчанию – шлюз, через который идёт весь трафик. nameservers – DNS-серверы; при необходимости укажите серверы провайдера или вашего корпоративного резолвера.
Перед применением проверьте конфигурацию через netplan try: он применит настройки и автоматически откатит их через 120 секунд, если вы не подтвердите. Это страховка от потери соединения. Если всё в порядке – зафиксируйте:
netplan apply
Последний штрих – задать осмысленное имя хоста. Понятное имя упрощает навигацию в логах и мониторинге, особенно когда серверов несколько:
hostnamectl set-hostname web-prod-01
echo "127.0.1.1 web-prod-01" >> /etc/hosts
Диагностика сетевых проблем
Терминал Ubuntu 22.04 с успешной проверкой подключения, DNS-серверов и открытого SSH-порта.
Если после применения netplan что-то пошло не так, три команды помогут локализовать проблему:
Если ping проходит, а dig не разрешает имена – проблема в DNS. На Ubuntu 22.04 DNS управляется через systemd-resolved. Его состояние:
resolvectl status
Если dig не установлен, установите пакет:
apt install bind9-dnsutils -y
В выводе resolvectl смотрите секцию DNS Servers для каждого интерфейса. Если серверы не отображаются или стоит 127.0.0.53, убедитесь, что в файле netplan прописан раздел nameservers, и заново примените конфигурацию.
Команда ss -tulpn полезна не только при диагностике сети: её стоит запускать после каждого шага настройки, чтобы убедиться – ничего лишнего не появилось на открытых портах.
Управление пользователями и доступом (users)
Постоянно работать от root – плохая практика. Опечатка в пути к файлу под root может уничтожить данные без возможности отмены. Любая уязвимость в запущенном от root приложении даёт атакующему полный контроль над системой. При командной работе аудит затруднён: в логах нет разграничения между разными администраторами.
Создайте пользователя для повседневной работы. В Ubuntu удобнее использовать adduser: команда создаёт домашнюю директорию, настраивает оболочку и интерактивно запрашивает пароль.
adduser <name>
usermod -aG sudo <name>
Команда usermod -aG sudo <name> добавляет пользователя в группу sudo. На Ubuntu эта группа по умолчанию имеет право выполнять любые команды через sudo без изменения файла /etc/sudoers. Проверьте, что всё работает не закрывая текущую сессию root:
su - <name>
sudo whoami # должно вывести: root
Для входа по SSH без пароля сгенерируйте ключ на локальной машине и скопируйте публичную часть на сервер. Тип ed25519 предпочтительнее rsa:
# На локальной машине
ssh-keygen -t ed25519 -C "user@pc_name"
ssh-copy-id <name>@<IP_сервера>
Два терминала: создание пользователя deploy и проверка sudo на Ubuntu-сервере, генерация и копирование SSH-ключа с локального компьютера.
Два терминала: создание пользователя deploy и проверка sudo на Ubuntu-сервере, генерация и копирование SSH-ключа с локального компьютера.
Если нужно добавить публичный ключ вручную – создайте структуру директорий самостоятельно. Разрешения важны: 700 на директорию, 600 на файл:
После настройки ключа войдите в новый сеанс под пользователем через SSH. Убедитесь, что аутентификация по ключу работает, и только после этого переходите к следующему шагу.
Безопасные настройки SSH
Настройка SSH на сервере сводится к нескольким директивам в /etc/ssh/sshd_config. Ключевой принцип: ограничить поверхность атаки. Откройте файл:
nano /etc/ssh/sshd_config
Перед отключением парольного входа не закрывайте текущую root-сессию и убедитесь, что вход по SSH-ключу работает в новом терминале. Если в конфиге или ключах есть ошибка, SSH-доступ можно потерять, и восстанавливать его придётся через консоль провайдера, VNC/KVM или rescue mode.
Внесите следующие изменения:
# Запретить прямой вход под root
PermitRootLogin no
# Только ключи; пароли не принимать
PasswordAuthentication no
PubkeyAuthentication yes
# Разрешить вход только указанному пользователю
AllowUsers deploy
# Сократить время и попытки аутентификации
MaxAuthTries 3
LoginGraceTime 30
PermitRootLogin no закрывает наиболее атакуемый вектор: большинство автоматических сканеров перебирают именно root. PasswordAuthentication no убирает парольный вход полностью после этого единственным способом войти остаются SSH-ключи. AllowUsers deploy добавляет дополнительный слой: даже если на сервере появятся другие пользователи, по SSH они войти не смогут.
Директива AllowUsers особенно полезна при командной работе: она задаёт явный белый список тех, кто может войти по SSH. Новый пользователь, не включённый в список, не получит доступ даже с корректным ключом.
Перед перезапуском проверьте синтаксис конфига, ошибка в директиве заблокирует вас при работающем соединении:
sshd -t # пустой вывод означает: конфиг корректен
systemctl restart ssh
Откройте новый терминал и убедитесь, что вход по ключу работает, прежде чем закрывать текущую сессию. Это самая частая ошибка при настройке SSH: отключают парольный вход до того, как проверяют, что ключ принимается.
Дополнительно: смена стандартного порта 22 на нестандартный снижает количество автоматических сканирований и шум в логах. Если решите сменить, сначала откройте новый порт в UFW, затем измените Port в конфиге и перезапустите sshd, не наоборот.
Настройка firewall: UFW и iptables
UFW – стандартный инструмент управления firewall на Ubuntu. Он даёт простой интерфейс для настройки правил, а конкретный backend зависит от версии Ubuntu и конфигурации системы: это может быть iptables-совместимый слой или nftables. На новом сервере UFW установлен, но часто не активирован.
Настройка облачных серверов без активного firewall оставляет все порты открытыми. Порядок имеет значение: сначала разрешить SSH, потом включать UFW, иначе заблокируете собственное соединение:
ufw default deny incoming # всё входящее – запрещено по умолчанию
Если SSH настроен на нестандартный порт, замените 22 на него. Правило ufw status verbose покажет активные разрешения и политику по умолчанию – полезно сверить сразу после включения.
Для отладки сначала используйте вывод UFW:
ufw status verbose
Если нужно посмотреть низкоуровневые правила, используйте инструмент, который соответствует backend системы:
iptables -L -n --line-numbers
или:
nft list ruleset
На Ubuntu 22.04 UFW может работать через iptables-совместимый backend или nftables. Поэтому не стоит ориентироваться только на одну цепочку INPUT: фактическое расположение правил зависит от backend и конфигурации системы.
Для автоматической блокировки IP-адресов после нескольких неудачных попыток входа установите fail2ban:
apt install fail2ban -y
systemctl enable --now fail2ban
Создайте файл пользовательских настроек /etc/fail2ban/jail.local. Редактировать jail.conf напрямую не стоит – он перезаписывается при обновлении пакета:
[DEFAULT]
bantime = 1h
findtime = 10m
maxretry = 5
[sshd]
enabled = true
При таких настройках IP блокируется на час после пяти неудачных попыток входа за десять минут. Перезапустите сервис и проверьте статус jail:
systemctl restart fail2ban
fail2ban-client status sshd
В выводе Currently banned покажет количество активных блокировок. Разбанить конкретный IP можно командой fail2ban-client set sshd unbanip <IP>. Кроме SSH, fail2ban поддерживает джейлы для nginx, apache2 и postfix. Они конфигурируются аналогично, добавлением отдельных секций в jail.local.
Мониторинг облачного сервера
Мониторинг сервера Linux без агентов начинается со встроенных инструментов. Для быстрой диагностики их вполне хватает:
Для постоянного мониторинга с метриками и алертами нужен агент. Выбор зависит от контекста: если в инфраструктуре уже есть Prometheus, оптимален node_exporter – он экспортирует более 800 метрик ОС с минимальным потреблением ресурсов (около 20–50 MB RAM):
apt install prometheus-node-exporter -y
systemctl enable --now prometheus-node-exporter
Агент слушает на порту 9100 и отдаёт метрики в формате Prometheus по адресу http://<IP>:9100/metrics. Добавьте этот адрес как scrape target в конфигурацию Prometheus, и метрики появятся в Grafana. Не открывайте порт 9100 наружу: ограничьте доступ через security group, UFW или приватную сеть Prometheus.
Если Prometheus ещё нет – Netdata даёт готовый интерактивный дашборд из коробки, без дополнительной инфраструктуры:
apt install netdata -y
systemctl enable --now netdata
Netdata слушает на порту 19999. Настройте SSH-туннель для разового просмотра или nginx с basic auth для постоянного доступа. Netdata потребляет от 100 MB RAM, на VPS с 1 GB это существенная разница по сравнению с node_exporter.
Алерты настраиваются поверх метрик. Для node_exporter используйте Prometheus Alertmanager: правила на PromQL, уведомления в Slack, email или PagerDuty. Для Netdata встроена собственная система уведомлений – настройте её в /etc/netdata/health_alarm_notify.conf. На практике для старта хватает трёх порогов: CPU load выше числа vCPU, диск выше 85%, список упавших сервисов непуст.
Что мониторить в первую очередь
На только что настроенном сервере важны шесть базовых показателей:
CPU load average – если значение устойчиво превышает количество vCPU в течение 5–10 минут, сервер перегружен. htop или uptime показывают три скользящих средних: за 1, 5 и 15 минут.
Память – при использовании свыше 85% система начинает активно использовать swap, что резко увеличивает latency. Для веб-серверов и баз данных это ощутимо. Контролируется через free -h.
Диск – заполненность свыше 80% блокирует запись логов, временных файлов и данных приложений. Дополнительно следите за iostat (из пакета sysstat) – высокий await при умеренной нагрузке указывает на проблемы с хранилищем.
Failed services – systemctl --failed выводит список упавших юнитов. Перед выводом в продакшен этот список должен быть пустым.
Auth log – journalctl -u ssh --since "1 hour ago" покажет активность после настройки fail2ban. Строки Failed password могут продолжать появляться до бана или с других IP-адресов. Важнее проверить, что fail2ban видит попытки входа и добавляет нарушителей в jail; строки Accepted publickey должны соответствовать вашим успешным входам.
Открытые порты – ss -tulpn один раз после каждого изменения конфигурации. Всё, что слушает наружу, должно быть в явном белом списке UFW.
Чек-лист финальной проверки
Пройдитесь по списку перед открытием сервера под рабочий трафик:
• Непривилегированный пользователь создан, добавлен в sudo
• Перед отключением парольного входа проверен вход по SSH-ключу в новом терминале
• PasswordAuthentication no и PermitRootLogin no прописаны в sshd_config
• UFW включён: ufw status verbose показывает только нужные порты
• fail2ban запущен: fail2ban-client status sshd показывает активный jail
• Пакеты обновлены: apt upgrade -y выполнен, при обновлении ядра – перезагрузка
• NTP активен: timedatectl показывает NTP service: active
• Мониторинг-агент запущен и метрики доступны
• Бэкапы настроены через панель провайдера или отдельный инструмент
• systemctl --failed возвращает пустой список
• Имя хоста и /etc/hosts настроены корректно
Четыре блока: сеть, пользователи, firewall, мониторинг – это минимальная конфигурация, без которой облачный сервер не готов к продакшену. Пропуск любого из этих шагов рано или поздно даёт о себе знать: либо взломом, либо аварией без видимой причины, либо часами поиска проблемы в логах.
Сохраните этот гайд и пройдитесь по нему при следующем деплое нового инстанса. В блоге Aeza регулярно выходят материалы по администрированию и безопасности серверов – подпишитесь, чтобы не пропускать NETTOWN5 обновления.
nftables был анонсирован аж в 2008-2009 годах, согласно Вики. Подсистема включена в ядро Linux c 2014 года. На самом деле мы уже примерно 5 лет все используем некоторую "прослойку" - iptables-nft. И до сих пор, даже в свежих мануалах - инструкции по написанию правил на iptables и почти нет альтернативных предложений для чистого nft.
Вы уже перешли на чистый nftables?
Было бы интересно почитать Ваше мнение в комментариях.
На самом деле это кусок 1-й части. Он про настройку файрволла и маршрутизации. Я только сейчас с ужасом обнаружил, что его там не хватает.
Прошу прощения и поехали.
В правой панели WinCSP открываем папку /root. На пустом месте правой панели жмём правую кнопку мыши, выбираем New -> File. В появившемся окошке вместо “New file” пишем “ipt-set” (без кавычек) и жмём ОК. Будет создан файл с именем ipt-set и откроется окно для его редактирования. Вписываем следующее содержимое:
#!/bin/sh
IF_EXT="venet0"
IF_OVPN="tun0"
OVPN_PORT="443"
SQUID_PORT="8080"
IPT="/sbin/iptables"
IPT6="/sbin/ip6tables"
# flush
$IPT --flush
$IPT -t nat --flush
$IPT -t mangle --flush
$IPT -X
$IPT6 --flush
# loopback
$IPT -A INPUT -i lo -j ACCEPT
$IPT -A OUTPUT -o lo -j ACCEPT
# default
$IPT -P INPUT DROP
$IPT -P OUTPUT DROP
$IPT -P FORWARD DROP
$IPT6 -P INPUT DROP
$IPT6 -P OUTPUT DROP
$IPT6 -P FORWARD DROP
# allow forwarding
echo 1 > /proc/sys/net/ipv4/ip_forward
# NAT
# #########################################
# SNAT - local users to out internet
$IPT -t nat -A POSTROUTING -o $IF_EXT -j MASQUERADE
# INPUT chain
# #########################################
$IPT -A INPUT -p tcp ! --syn -m state --state NEW -j DROP
$IPT -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPT -A FORWARD -i $IF_OVPN -o $IF_EXT -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
$IPT -A FORWARD -i $IF_EXT -o $IF_OVPN -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPT -A FORWARD -s 10.8.0.0/24 -d 10.8.0.0/24 -j ACCEPT
# OUTPUT chain
# #########################################
$IPT -A OUTPUT -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
Нужно обратить внимание на следующие моменты:
- сетевой интерфейс называется venet0. Это особенность сборки операционной системы конкретного хостера. Возможно у вас он называется eth0. Узнать, как же правильно в вашем случае можно введя в консоли команду
ip a
В получившемся выводе команды будет список сетевых интерфейсов. Один из них носит название lo , это локальная петля. А вот второй, тот, что вам нужен.
- OVPN_PORT="443" это порт используется для нашего VPN сервера. Почему именно 443? Мы же настроим VPN и для домашнего компьютера/ноутбука, и для смартфона и, возможно, для рабочего компьютера/ноутбука. Вполне возможно, что ваше устройства окажется в сети (например, корпоративный Wi-Fi), где все порты кроме самых базовых запрещены. 443 точно будет разрешен, а VPN серверу без разницы на каком порту «висеть». Да и активность на этом порту не будет подозрительной.
подключения к прокси-серверу мы будем принимать на порт 8080 и только от тех, кто уже подключился к VPN, мамкины кулхацкеры идут лесом.
- $IPT -A FORWARD -s 10.8.0.0/24 -d 10.8.0.0/24 -j ACCEPT
клиенты VPN будут видеть друг друга. Т.е. ваш смартфон будет видеть ваш компьютер если оба они подключились к VPN. Это удобно для расшаривания контента.
Сохраняем получившийся файл. Кликаем на нём правой кнопкой мыши, выбираем Properties и отмечаем галочками все квадратики с буквой X (третий столбик квадратиков). Обратите внимание, в поле Octal получится число 0755. Можно задать свойства файла введя сразу нужное чиасло в это поле, а не выбирая свойства галочками. В дальнейшем мы так и бедуем делать. Я просто буду писать число, которое вам нужно будет вписать в это поле.
Жмём ОК. В консоли PuTTY выполняем команду:
/root/ipt-set
а затем команду:
iptables -L -n
Наши правила применились. Закрываем окно putyy, открываем заново и пробуем подключится. Если подключились, значит вы нигде выше не ошиблись и правила работают. Но работать они будут до перезагрузки сервера. Если что-то не так, ребутим сервер из консоли управления и пробуем заново.
Добавим правила в автозапуск. В правой панели WinCSP переходим к папке /etc/systemd/system/ и создаем файл с именем ipt-settings.service со следующим содержимым:
[Unit]
Description=Iptables Settings Service
After=network.target
[Service]
Type=oneshot
User=root
ExecStart=/root/ipt-set
[Install]
WantedBy=multi-user.target
В свойствах файла (см. выше) указываем права 0644.
Теперь в консоли вводим команду
systemctl enable ipt-settings
В ответ получим:
Created symlink from /etc/systemd/system/multi-user.target.wants/ipt-settings.service to /etc/systemd/system/ipt-settings.service.
Таким образом мы создали службу, которая будет применять наши правила при каждой перезагрузке системы.
Проверим, что всё работает как задумано. Перезагрузим сервер командой reboot, подключимся к нему и введем команду
iptables -L -n
Должны получить то, что было на последнем скриншоте (см. выше).