Как быстро защитить VPS: SSH-ключи, запрет root и один пользователь
Ситуация знакомая: VPS в интернете, много сервисов, «вроде всё работает», а в логах — нескончаемый поток попыток залогиниться по SSH (root, admin, ubuntu и т.д.).
Цель — за 20–30 минут сделать базовый «каркас безопасности», чтобы:
- по SSH можно было зайти только одним пользователем (
admin) - вход работал только по ключу (без паролей)
- root по SSH был запрещён
- был план восстановления доступа, если ключ потеряется
Если делаете это впервые — держите две SSH-сессии: одну текущую (не закрывать), вторую — для проверки после изменений.
Быстрый аудит
Кто вообще может логиниться
Список пользователей:
cut -d: -f1 /etc/passwdПокажем тех, у кого есть «живой shell» (то есть теоретически можно логиниться):
awk -F: '$7!="/usr/sbin/nologin" && $7!="/bin/false"{printf "%-20s %s\n",$1,$7}' /etc/passwdПример:
root /bin/bash
admin /bin/bash
mysql /usr/sbin/nologin
www-data /usr/sbin/nologinБыстро смотрим, что происходит в SSH-логах
journalctl -u ssh --no-pager -n 200Пример брутфорса:
Mar 06 10:41:02 vps sshd[1298]: Failed password for root from 185.234.217.12 port 51822 ssh2
Mar 06 10:41:06 vps sshd[1298]: Failed password for admin from 91.240.118.172 port 44211 ssh2
Mar 06 10:41:11 vps sshd[1298]: Failed password for root from 45.95.147.22 port 60110 ssh2Если встречается Accepted password for root — значит root реально входил по паролю. Это нужно закрывать в первую очередь.
Настраиваем доступ правильно
Схема
- вход по SSH — только пользователем
adminи только по ключу - привилегии — через
sudo(локально), а не через root-SSH
Проверяем/включаем sudo для admin
Добавляем admin в группу sudo:
sudo usermod -aG sudo adminПереподключаемся и проверяем:
sudo -iЕсли sudo просит пароль и вы его не знаете — задайте пароль Linux-пользователя:
sudo passwd adminЭто пароль Linux-пользователя, а не пароль панели управления хостингом.
Hardening SSH (ключи, запрет root, один пользователь)
Бэкап конфигурации
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.bak.$(date +%F_%H%M%S)Убеждаемся, что включён include-директория
grep -n "Include /etc/ssh/sshd_config.d/\*.conf" /etc/ssh/sshd_config || trueДальше изменения будем класть в /etc/ssh/sshd_config.d/.
Разрешаем вход только admin
Создаём файл:
sudo nano /etc/ssh/sshd_config.d/99-hardening.confСодержимое:
AllowUsers adminОтключаем пароли и запрещаем root (через Match all)
Создаём файл:
sudo nano /etc/ssh/sshd_config.d/99-match-hardening.confСодержимое:
Match all
PasswordAuthentication no
KbdInteractiveAuthentication no
PermitRootLogin no
PubkeyAuthentication yesПрименяем изменения безопасно (с проверкой синтаксиса):
sudo sshd -t && sudo systemctl reload sshПроверка после изменений
Смотрим «эффективную конфигурацию» с контекстом
sshd -T без контекста может путать, поэтому используем -C:
sudo sshd -T -C user=admin,host=localhost,addr=127.0.0.1 | egrep 'permitrootlogin|passwordauthentication|kbdinteractiveauthentication|pubkeyauthentication|allowusers'Ожидаемо:
permitrootlogin no
passwordauthentication no
kbdinteractiveauthentication no
pubkeyauthentication yes
allowusers adminБыстрые тесты с клиента
Вход по ключу:
ssh admin@203.0.113.10Проверка, что пароль по SSH «умер» (отключаем ключи на клиенте):
ssh -o PubkeyAuthentication=no -o PreferredAuthentications=password admin@203.0.113.10Проверка, что root заблокирован:
ssh root@203.0.113.10План восстановления доступа
Вариант 1: резервный SSH-ключ
Генерируем:
ssh-keygen -t ed25519 -f ~/.ssh/id_ed25519_backup -C "backup"Добавляем на сервер:
ssh-copy-id -i ~/.ssh/id_ed25519_backup.pub admin@203.0.113.10Проверяем вход:
ssh -i ~/.ssh/id_ed25519_backup admin@203.0.113.10Вариант 2: консоль провайдера (VNC/Serial/Rescue)
Если ключи потеряны: заходите в консоль через панель провайдера, логинитесь локально и добавляете новый публичный ключ в:
/home/admin/.ssh/authorized_keysИтог
Мы сделали минимальный baseline безопасности:
- отключили вход по паролю
- запретили root по SSH
- ограничили SSH одним пользователем
- настроили
sudo - подготовили план восстановления
Дальше логичный следующий шаг: поставить fail2ban или включить rate-limit на уровне firewall — но это уже отдельная статья.