Почему настройки SSH по умолчанию — это проблема
Сразу после установки Ubuntu-сервера к нему начинают ломиться боты. Через несколько часов в логах auth.log будут тысячи попыток подбора пароля. Эта статья — пошаговый план от «дефолтного сервера» к «сложно взломать».
Важно: всегда держите дополнительную консоль открытой при редактировании sshd_config. Одна опечатка — и вы можете потерять доступ к серверу.
Шаг 1: Ключи вместо паролей
Парольная аутентификация — слабое место. Ed25519 ключи надёжнее RSA 2048 и быстрее генерируются.
bash# На локальной машине: генерируем ключ Ed25519
ssh-keygen -t ed25519 -C "user@hostname" -f ~/.ssh/id_ed25519
# Копируем публичный ключ на сервер
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@server
# Или вручную
cat ~/.ssh/id_ed25519.pub | ssh user@server "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"
Шаг 2: Ужесточение sshd_config
После того как убедились, что вход по ключу работает, применяем строгие настройки:
bash# /etc/ssh/sshd_config
# Сменить стандартный порт (затруднит автоматический скан)
Port 2222
# Отключить вход под root
PermitRootLogin no
# Только ключи, никаких паролей
PasswordAuthentication no
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
# Разрешить только конкретных пользователей
AllowUsers deploy backup
# Ограничить протоколы и алгоритмы
Protocol 2
KexAlgorithms curve25519-sha256,diffie-hellman-group16-sha512
Ciphers chacha20-poly1305@openssh.com,aes256-gcm@openssh.com
MACs hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com
# Таймауты
ClientAliveInterval 300
ClientAliveCountMax 2
LoginGraceTime 30
# Дополнительные ограничения
MaxAuthTries 3
MaxSessions 5
X11Forwarding no
AllowAgentForwarding no
AllowTcpForwarding no
bash# Проверяем конфиг на ошибки перед применением
sshd -t
# Применяем
systemctl reload sshd
Шаг 3: fail2ban для защиты от брутфорса
fail2ban мониторит логи и блокирует IP после серии неудачных попыток входа.
bashapt install fail2ban
# /etc/fail2ban/jail.local
[DEFAULT]
bantime = 1h
findtime = 10m
maxretry = 5
banaction = ufw
[sshd]
enabled = true
port = 2222
logpath = %(sshd_log)s
backend = %(sshd_backend)s
maxretry = 3
bantime = 24h
bashsystemctl enable --now fail2ban
# Проверить статус
fail2ban-client status sshd
# Посмотреть заблокированные IP
fail2ban-client status sshd | grep "Banned IP"
Шаг 4: Файрвол UFW
bashufw default deny incoming
ufw default allow outgoing
# Разрешить SSH только с конкретного IP (если он статический)
ufw allow from 212.22.90.11 to any port 2222
# Или со всех (если нет статического IP)
ufw allow 2222/tcp
# Ваши сервисы
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable
ufw status verbose
Шаг 5: Двухфакторная аутентификация (опционально)
Для максимальной безопасности добавьте TOTP через Google Authenticator или аналоги. Вход станет: ключ + одноразовый код.
bashapt install libpam-google-authenticator
# Запустить настройку для каждого пользователя
google-authenticator
# /etc/pam.d/sshd — добавить строку в начало
auth required pam_google_authenticator.so
# /etc/ssh/sshd_config
ChallengeResponseAuthentication yes
AuthenticationMethods publickey,keyboard-interactive
Шаг 6: Мониторинг и аудит
bash# Смотреть попытки входа в реальном времени
journalctl -fu sshd
# Последние успешные входы
last -n 20
# Последние неудачные попытки
lastb -n 20
# Статистика неудачных попыток по IP
grep "Failed password" /var/log/auth.log | \
awk '{print $11}' | sort | uniq -c | sort -rn | head -10
Настройте уведомления о входе на сервер: простой bash-скрипт в /etc/profile.d/ может отправлять Telegram-сообщение при каждом SSH-соединении.
Хочу добавить: смена порта не является security-мерой, но значительно уменьшает шум в логах от ботов. Это не обфускация как защита, а просто гигиена — легче мониторить реальные угрозы.
Для параноиков: можно настроить port knocking — порт SSH открывается только после стука на определённую последовательность портов. Утилита
knockdдля этого.Мы используем Cloudflare Tunnel вместо прямого SSH. Никаких открытых портов вообще. Для небольших команд это удобно, хотя создаёт зависимость от Cloudflare.
Обязательно настройте алёрт, если кто-то залогинился под root (даже если вход запрещён — сам факт попытки интересен). auditd + syslog + Telegram-бот = 5 минут работы.