Настройка firewall в Ubuntu – один из четырёх шагов базовой защиты вместе с входом по SSH-ключу вместо пароля, автоматическими обновлениями безопасности и fail2ban. На свежей машине весь набор ставится за четверть часа. К каждому шагу здесь есть команда проверки – файл конфигурации показывает намерение, а что реально работает, видно только по выводу команды.
Сколько попыток входа получает обычный сервер
За 33 месяца 221 ловушка в 55 странах собрала 546 млн SSH-сессий – это данные Attacks Come to Those Who Wait с конференции IMC '25, авторы из Max Planck Institute for Informatics и TU Delft. Больше половины сессий (258 млн) – это попытки войти, которые не удались, а часть входов вообще прошла без единой команды: бот просто отмечает цель для следующей волны атаки.
Цифры по хост-дню – пересчёт для этой статьи, сами суммарные показатели взяты из исследования: если поделить на 221 хост и 1004 дня наблюдений, выходит порядка 2400-2500 сессий в сутки на один адрес, из них около 1150 с неудавшимся входом.
Самый частый пароль всего набора – 3245gs5662d34: более 24 млн сессий со 125 тысячами адресов, причём после успешного входа бот не выполняет ни одной команды. Тишина в логах после такого входа не означает, что ничего не произошло: часть кампаний просто размечает доступные цели на будущее.
Шаг 1. Вход по ключу вместо пароля
Перед правкой конфигурации полезно посмотреть, что вообще слушает сервер снаружи:
ss -tlnp
Если в списке есть что-то, кроме SSH и веб-сервера, который вы сами разворачивали, – это повод разобраться отдельно, до того как переходить к firewall.
На своей машине генерируем ключ и копируем его на сервер:
ssh-keygen -t ed25519 -C "vps"
ssh-copy-id user@SERVER_IP
Проверка до правки конфигурации сервера – вход должен пройти без запроса пароля:
ssh -o PasswordAuthentication=no user@SERVER_IP
Только после успешной проверки правим /etc/ssh/sshd_config:
PermitRootLogin no
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
AllowUsers user
Заодно стоит посмотреть, кто ещё может зайти на сервер: getent group sudo покажет пользователей с правами администратора, а awk -F: '$3 >= 1000 {print $1}' /etc/passwd – всех, у кого вообще есть обычный шелл. Лишние учётки на свежем сервере остаются от образа хостера или от прошлого администратора.
Здесь легко упустить одну деталь: KbdInteractiveAuthentication по умолчанию включён отдельно от PasswordAuthentication, и если выключить только вторую директиву, на части сборок пароль всё равно проходит вторым методом – гасить нужно обе. С root ситуация обратная: по умолчанию PermitRootLogin уже стоит в prohibit-password, то есть по паролю root и так не войдёт, а по ключу – войдёт, и именно это перекрывает строка PermitRootLogin no.
Проверка синтаксиса до перезапуска и проверка того, что реально применилось:
sudo sshd -t
sudo sshd -T | grep -Ei 'permitrootlogin|passwordauthentication|pubkeyauthentication|kbdinteractive|allowusers'
![]()
Почему правка sshd_config не срабатывает
«Сделал всё по инструкции, а пароль всё равно принимается» – жалоба ровно на этот случай. Облачные образы Ubuntu кладут в начало /etc/ssh/sshd_config строку:
Include /etc/ssh/sshd_config.d/*.conf
В этой папке лежит файл 50-cloud-init.conf, а в нём – PasswordAuthentication yes. В конфигурации sshd выигрывает первое встреченное значение директивы, так что правка в основном файле, стоящая ниже по тексту, проигрывает подключённому файлу, который читается раньше.
Убрать строку из файла, который положил cloud-init, можно так:
sudo sed -i 's/^PasswordAuthentication yes/#&/' /etc/ssh/sshd_config.d/50-cloud-init.conf
Более надёжный путь – положить рядом свой файл с именем, которое сортируется раньше остальных, потому что каталог подключается по алфавиту:
printf 'PasswordAuthentication no\nKbdInteractiveAuthentication no\nPermitRootLogin no\n' | sudo tee /etc/ssh/sshd_config.d/00-hardening.conf
sudo sshd -t && sudo systemctl reload ssh
После этой правки у SSH уже два файла с настройками – основной и подключённый. sshd -T сворачивает их в одно итоговое значение, которое реально применяется.
Шаг 2. Настройка firewall в Ubuntu через ufw
ufw стоит в системе изначально, но выключен. Разрешить SSH нужно раньше, чем включать сам firewall, – иначе разрыв соединения обрубит и правку, и доступ к серверу одним действием:
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow OpenSSH
sudo ufw enable
Проверка изнутри:
sudo ufw status verbose
И снаружи, с другой машины, где установлен nmap:
nmap -Pn -p 22,80,443 SERVER_IP
Классическая авария – включить firewall с политикой «запретить входящие» до того, как открыт SSH. Держите вторую SSH-сессию открытой всё время настройки и проверяйте вход в третьем окне, пока первая жива. Плюс у Timeweb в панели есть консоль сервера, серийная и VNC, и она работает независимо от сети и настроек SSH – то есть остаётся доступной даже при закрытом наглухо firewall. Проверьте вход в неё до того, как трогать правила.
Полезная мелочь: sudo ufw --dry-run allow http показывает, что получится, ничего не применяя.
Шаг 3. Автоматические обновления безопасности
Пакет unattended-upgrades входит в базовую поставку, и обновления безопасности включаются сразу после установки. В списке источников по умолчанию активны только security-репозитории, обычный -updates закомментирован – приезжают только заплатки безопасности, остальные обновления ставите сами. А вот перезагрузка после обновления ядра сама не происходит: пока вы явно не разрешите её в конфигурации и не зададите время, сервер может месяцами работать на старом ядре с уже установленным новым.
Включение и проверки:
sudo dpkg-reconfigure --priority=low unattended-upgrades
sudo unattended-upgrade -v --dry-run
systemctl status apt-daily-upgrade.timer
Логи лежат в /var/log/unattended-upgrades/.
Шаг 4. Что на самом деле делает fail2ban
Ключи ставят раньше fail2ban – иначе программа будет банить те же попытки подбора пароля, которые вы сами совершаете, пока не перешли на ключ. Дальше fail2ban режет скорость перебора и чистит логи, а саму возможность подбора убирает только отключённый пароль.
sudo apt install fail2ban
sudo fail2ban-client status sshd
Апстримные значения – блокировка на 10 минут после 5 попыток за 10 минут, они заданы в jail.conf дистрибутива fail2ban. Сборка может переопределить их в /etc/fail2ban/jail.d/, поэтому смотрите на своей машине:
sudo fail2ban-client get sshd bantime
Разбанить себя, если увлеклись проверками:
sudo fail2ban-client set sshd unbanip YOUR_IP
Тем, кто уже перешёл на ключи, стоит знать про поведение штатного фильтра sshd: неудачные попытки с чужим публичным ключом он по умолчанию не банит, хотя вход с несуществующим логином ловит нормально. Так сделан дефолт publickey = nofail: он защищает от блокировки своих, когда клиент перебирает несколько ключей подряд. Фильтрация включается значением publickey = any или режимом mode = aggressive в jail. Пока дефолт не тронут, администратор видит работающий fail2ban, который по этому классу попыток молчит.
Какие советы по защите сервера уже не работают
- Смена порта SSH. Чистит логи, защиты не даёт. Массовые сканеры ходят по 22 порту, и после переезда журнал заметно тихеет – точных измерений на этот счёт нет, а цифры вроде «минус 99%» гуляют по блогам без исходных данных. Направленное сканирование обходит все 65535 портов за секунды, а порт выше 1024 может занять непривилегированный процесс.
- Отключение ping. Совет из нулевых, сегодня скорее вредный. Сервер всё равно виден по открытым 80 и 443, а блокировка ICMP ломает определение размера пакета: соединения устанавливаются, но виснут на больших ответах. Такую «чёрную дыру» потом ищут неделями. Заодно перестают работать мониторинг и traceroute.
- fail2ban вместо ключей. При включённом пароле он снижает скорость перебора, при входе по ключу его польза падает по причине выше. Ключи – защита, fail2ban – гигиена.
- Ограничение частоты подключений. Команда ufw limit режет адрес, сделавший шесть и более соединений за 30 секунд, порог через командную строку не меняется. Против одного назойливого источника работает, против распределённого перебора со 125 тысяч адресов – нет: каждый делает пару попыток и уходит.
Итоговая проверка: пять команд вместо взгляда на конфиг
На новой машине имеет смысл прогнать эти пять команд одним заходом, сразу после того как прошли все четыре шага:
sudo sshd -T | grep -Ei 'permitrootlogin|passwordauthentication|kbdinteractive'
sudo ufw status verbose
ss -tlnp
sudo fail2ban-client status sshd
sudo unattended-upgrade -v --dry-run
Первая говорит, что реально применилось в SSH – не то, что записано в файле, а то, с чем демон стартовал. Вторая – какие порты открыты для внешнего мира по политике firewall. Третья – что физически слушает сервер прямо сейчас, независимо от firewall: если тут всплыл процесс, которого вы не разворачивали, разбираться нужно раньше, чем закрывать порты. Четвёртая подтверждает, что jail для SSH не просто установлен, а активен. Пятая показывает, какие обновления приедут при следующем прогоне таймера, без реальной установки.
Частые вопросы
Обязательно ли отключать пароль, если он сложный? Перебор идёт круглосуточно и стоит атакующему копейки. Ключ снимает саму возможность подбора, сложность пароля лишь отодвигает срок.
Что делать, если закрыл себе SSH? Зайти через консоль в панели хостинга и поправить правила. Именно поэтому её стоит проверить до начала настройки.
Нужен ли fail2ban, если вход только по ключу? Полезен для других сервисов и для чистоты логов, но по SSH его вклад в этом режиме невелик.
Стоит ли менять порт SSH? Только ради тишины в журналах. Как замена ключам не годится.
Что делать, если на сервере уже стоит своя панель управления или Docker с открытыми портами? ufw не видит правила, которые Docker добавляет напрямую в iptables, и может показывать порт закрытым, пока контейнер держит его открытым в обход. После ufw enable стоит перепроверить доступность контейнерных портов снаружи тем же nmap: вывод ufw status в этом случае ничего не гарантирует.
Что с IPv6? ufw по умолчанию защищает и IPv6, если он включён на сервере – правило IPV6=yes уже стоит в /etc/default/ufw, отдельно дублировать команды под IPv6 не нужно. sudo ufw status verbose покажет правила сразу для обеих версий протокола.
Как проверить, что настройки применились? sshd -T для SSH, ufw status verbose изнутри и сканирование портов снаружи, fail2ban-client status sshd для блокировок – весь набор собран в разделе «Итоговая проверка» выше.
Что ставят на взломанные серверы? По квартальным отчётам AhnLab по атакам на Linux-серверы за первую половину 2025 года на Linux-ловушках доминировали два семейства – червь P2PInfect и Tsunami, вместе больше 80% установок.
Достаточно ли этих четырёх шагов? Для типового веб-проекта это разумный минимум. Дальше идут разделение прав между несколькими учётками вместо одной общей, резервные копии с проверкой восстановления и мониторинг – но без базовых четырёх любая из следующих мер держится на честном слове.
Значения по умолчанию сверены по manpage sshd_config(5), jail.conf fail2ban и документации Ubuntu для 24.04 (noble), сентябрь 2026 года. Файл говорит, что должно быть настроено. sshd -T и ufw status говорят, что настроено на самом деле – и только второму стоит верить.
Комментарии