Часть 05. sslh и Fail2ban — швейцарский нож и сторожевой пёс
Часть 05. sslh и Fail2ban — швейцарский нож и сторожевой пёс
«Одного замка на двери мало. Мало даже двух. Злоумышленник должен пройти через три двери, пока поймёт, что за первой — ничего нет.» — Воланд
Глава 1. Что такое sslh
sslh (SSL/SSH multiplexer) — это демон, который слушает один порт (обычно 80), смотрит на тип входящего трафика и направляет его в нужное место.
Как это работает:
- Подключаетесь по SSH на порт 80 → sslh видит SSH-рукопожатие → перенаправляет на 127.0.0.1:22022
- Браузер запрашивает HTTP на порт 80 → sslh видит HTTP-заголовок → перенаправляет на 127.0.0.1:8080 (будущий Nginx)
Зачем это нужно. Порт 80 (HTTP) открыт всегда — любой сайт должен быть доступен. Если вы идёте по SSH через порт 80, это выглядит как обычный веб-трафик. Порт 22022 при этом остаётся прямым входом для админа, а порт 80 — запасным.
Бегемот, настраивая монокль:
«Представьте парадный вход в дом. Швейцар смотрит на гостя: если с ноутбуком и в тапочках — отправляет в библиотеку. Если в бабочке и с коньяком — в гостиную. Одна дверь, два назначения. Элегантно.»
Глава 2. Установка sslh
sslh есть в стандартных репозиториях Ubuntu:
sudo apt update && sudo apt install -y sslh
Ожидаемый вывод (в конце):
Setting up sslh (2.0.1-1) ...
Проверяем версию:
sslh -V
Ожидаемый вывод:
sslh 2.0.1
Глава 3. Настройка sslh
Конфигурационный файл sslh находится в /etc/default/sslh. Редактируем его:
sudo nano /etc/default/sslh
Приводим содержимое к следующему виду:
# Default options for sslh initscript
# sourced by /etc/init.d/sslh
# binary to use: forked (sslh) or single-thread (sslh-select) version
# systemd users: don't forget to modify /lib/systemd/system/sslh.service
DAEMON=/usr/sbin/sslh
DAEMON_OPTS="--user sslh --listen 0.0.0.0:80 --ssh 127.0.0.1:22022 --http 127.0.0.1:8080"
Пояснение параметров:
DAEMON=/usr/sbin/sslh— используем forked-версию (создаёт отдельный процесс на каждое соединение)--user sslh— демон работает от имени одноимённого системного пользователя--listen 0.0.0.0:80— слушаем порт 80 на всех интерфейсах--ssh 127.0.0.1:22022— SSH-трафик направляем на локальный SSH-сервер--http 127.0.0.1:8080— HTTP-трафик направляем на будущий Nginx (пока не установлен — соединения будут отклоняться, это нормально)
Перезапускаем сервис и добавляем в автозагрузку:
sudo systemctl restart sslh && sudo systemctl enable sslh
Ожидаемый вывод:
Synchronizing state of sslh.service with SysV service script with /lib/systemd/systemd-sysv-install.
Executing: /lib/systemd/systemd-sysv-install enable sslh
Проверяем, что sslh слушает порт 80:
sudo ss -tlnp | grep 80
Ожидаемый вывод:
LISTEN 0 10 0.0.0.0:80 0.0.0.0:* users:(("sslh-select",pid=1234,fd=3))
LISTEN 0 10 [::]:80 [::]:* users:(("sslh-select",pid=1234,fd=4))
Глава 4. Проверка sslh на клиенте
На вашем локальном компьютере (не на сервере!) добавляем в ~/.ssh/config второй хост для подключения через порт 80:
# Подключение к srv02-Helsinki
Host srv02
HostName XX.XX.XX.XX
Port 22022
User user01
IdentityFile ~/.ssh/id_ed25519_srv02
# Подключение через sslh (порт 80)
Host srv02-web
HostName XX.XX.XX.XX
Port 80
User user01
IdentityFile ~/.ssh/id_ed25519_srv02
Проверяем подключение через sslh:
ssh srv02-web
Если подключение успешно — sslh работает. Выходим (exit) и продолжаем использовать штатный хост srv02 (порт 22022) для повседневной работы.
Коровьев, разглядывая лог:
«Вошли через парадную дверь. Швейцар узнал своего, пропустил без очереди. А со стороны — обычный пакет на 80-й порт. Поди разбери, кто там: админ или браузер.»
Глава 5. Что такое Fail2ban
Fail2ban — это демон, который следит за логами сервисов (SSH, Nginx, и т.д.) и блокирует IP-адреса, с которых приходит слишком много неудачных попыток подключения.
Блокировка происходит на уровне фаервола — UFW получает правило deny для заблокированного IP. Через 30 минут блокировка снимается автоматически.
Типичная атака на SSH: бот перебирает пароли со скоростью 3-5 попыток в секунду. Fail2ban засекает 5 неудачных попыток за 10 минут — и IP уходит в бан.
Бегемот, потягиваясь:
«Сторожевой пёс не лает на каждую проходящую кошку. Но если кто-то слишком долго скребётся в замочную скважину — пёс встаёт и кладёт лапу на дверь.»
Глава 6. Установка Fail2ban
sudo apt install -y fail2ban
Ожидаемый вывод (в конце):
Setting up fail2ban (1.0.2-2) ...
Проверяем версию:
fail2ban-server --version
Ожидаемый вывод:
Fail2Ban v1.0.2
Глава 7. Настройка Fail2ban для SSH
Fail2ban использует два типа файлов конфигурации:
/etc/fail2ban/jail.conf— стандартный, не редактируется (перезаписывается при обновлении)/etc/fail2ban/jail.local— ваш файл с собственными настройками (имеет приоритет)
Создаём jail.local:
sudo nano /etc/fail2ban/jail.local
Содержимое:
[sshd]
enabled = true
port = 22022
logpath = %(sshd_log)s
maxretry = 3
bantime = 86400
findtime = 600
Пояснение параметров:
enabled = true— включаем тюрьму для SSHport = 22022— нестандартный порт SSH; Fail2ban передаёт его в правило UFW, чтобы блокировать атакующий IP только на этом портуlogpath = %(sshd_log)s— ссылка на переменную изjail.conf, где прописан/var/log/auth.logmaxretry = 3— три неудачные попытки → банbantime = 86400— время блокировки: 86 400 секунд = 24 часа. Сутки — вполне разумный срок: бот уходит к другой жертве и уже не возвращаетсяfindtime = 600— окно подсчёта попыток: 600 секунд = 10 минут
Перезапускаем Fail2ban:
sudo systemctl restart fail2ban && sudo systemctl enable fail2ban
Ожидаемый вывод:
Synchronizing state of fail2ban.service with SysV service script with /lib/systemd/systemd-sysv-install.
Executing: /lib/systemd/systemd-sysv-install enable fail2ban
Глава 8. Проверка работы Fail2ban
Проверяем статус SSH-защиты:
sudo fail2ban-client status sshd
Ожидаемый вывод:
Status for the jail: sshd
|- Filter
| |- Currently failed: 0
| |- Total failed: 0
| `- File list: /var/log/auth.log
`- Actions
|- Currently banned: 0
|- Total banned: 0
`- Banned IP list:
Пока никто не забанен — сервер новый. Через пару дней список Total banned покажет, сколько ботов пыталось пробиться.
Проверяем, что Fail2ban видит логи SSH:
sudo tail -5 /var/log/fail2ban.log
Ожидаемый вывод (пример):
2026-07-26 18:00:00,123 fail2ban.server [1234]: INFO Ready for action
2026-07-26 18:00:01,456 fail2ban.filter [1234]: INFO Added logfile: /var/log/auth.log (pos = 12345, hash = abcdef...)
2026-07-26 18:00:01,789 fail2ban.jail [1234]: INFO Jail 'sshd' started
Если строка Jail 'sshd' started есть — всё работает.
Воланд, перебирая забаненные IP:
«Три неудачных попытки за десять минут — и гости с таким адресом отправляются в сад. На сутки. Бот вернётся завтра, сделает ещё три попытки — и сядет снова. Бесконечный ад для железа.»
Глава 9. Дополнительная тюрьма: админка блога
На сервере уже настроена вторая тюрьма — для защиты панели управления блогом:
sudo nano /etc/fail2ban/jail.local
Дописываем в конец файла:
[psj-admin-login]
enabled = true
port = http,https
logpath = /var/log/nginx/access.log
maxretry = 3
bantime = 86400
findtime = 300
Пояснение:
port = http,https— блокировка на портах 80 и 443; какой именно порт — неважно, атакующий IP будет заблокирован на обоихlogpath = /var/log/nginx/access.log— Fail2ban будет сканировать лог Nginx на предмет неудачных попыток входа в админкуfindtime = 300— окно подсчёта: 5 минут
Эта тюрьма заработает в полную силу после установки Nginx и движка блога. Fail2ban уже настроен и ждёт.
Перезапускаем Fail2ban, чтобы применить изменения:
sudo systemctl restart fail2ban
Глава 10. Обновление UFW (ещё раз)
Порт 80 у нас уже открыт (добавлен в части 04). Проверяем актуальные правила:
sudo ufw status verbose
Ожидаемый вывод:
Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing)
New profiles: skip
To Action From
-- ------ ----
22022/tcp LIMIT Anywhere
80/tcp ALLOW Anywhere
443/tcp ALLOW Anywhere
22022/tcp (v6) LIMIT Anywhere (v6)
80/tcp (v6) ALLOW Anywhere (v6)
443/tcp (v6) ALLOW Anywhere (v6)
Порт 80 открыт — sslh может работать. Порт 443 пока не используется (откроемся позже, когда поставим Nginx с SSL).
Финал части: Резюме Воланда
| Параметр | Статус |
|---|---|
| sslh установлен и слушает порт 80 | ✅ |
| SSH доступен через порт 80 (sslh) | ✅ |
| SSH доступен через прямой порт 22022 | ✅ |
| HTTP-трафик перенаправляется на 8080 | ✅ |
| Fail2ban установлен | ✅ |
| Защита SSH: 3 попытки за 10 мин → бан на сутки | ✅ |
| Защита админки блога (psj-admin-login) | ✅ |
| UFW: порты 80, 443, 22022 открыты | ✅ |
Воланд подводит итог пятой части:
«Парадная дверь прикрыта sslh — швейцар разбирает гостей. Чёрный ход (22022) стережёт Fail2ban — три попытки, и на сутки в сад. Админка блога пока спит — пёс уже поставлен на пост. Пора ставить веб-сервер!»
Комментарии
Комментарии пока не подключены.