Парольный вход по SSH — самая большая открытая поверхность обычного сервера. Против него бессильны и Fail2ban, и любые пороги: тысяча адресов по одной попытке в час не наберёт лимита никогда, а перебирать они будут ровно до тех пор, пока подбор в принципе возможен. Ключи убирают саму возможность, и это единственная настройка из всего списка «хардынга», которая меняет положение дел качественно.
Пугает здесь одно: отключить пароль и остаться снаружи. Ниже порядок, при котором это исключено.
Ключ
Генерируется на своей машине, не на сервере:
ssh-keygen -t ed25519 -C "рабочий ноутбук"
ed25519 вместо RSA — короче, быстрее и без вопросов о длине. RSA нужен, только если предстоит ходить на что-то очень старое; тогда -t rsa -b 4096.
Пароль на ключ (passphrase) ставить стоит: файл ключа могут украсть с ноутбука, и без пароля он сразу же работает. Вводить его каждый раз не придётся — этим занимается ssh-agent, а в macOS и большинстве десктопных Linux он уже запущен.
Копирование на сервер — одной командой, пока пароль ещё работает:
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@203.0.113.25
Если ssh-copy-id недоступен, содержимое .pub-файла дописывается строкой в ~/.ssh/authorized_keys на сервере. Права важны: каталог .ssh — 700, файл — 600, владелец — сам пользователь. При других правах sshd молча откажется читать файл, и это самая частая причина «ключ не работает».
Проверка, которая всё решает
Прежде чем что-либо отключать, откройте второе соединение, не закрывая первое:
ssh -o PasswordAuthentication=no user@203.0.113.25
Опция запрещает клиенту откатываться на пароль — то есть если вход состоялся, он состоялся именно по ключу. Пока эта команда не отработает, к следующему шагу переходить нельзя. И первое соединение до самого конца не закрываем: через него чинится всё, что можно сломать.
Отключение пароля и один неочевидный подвох
Настройки кладём отдельным файлом, чтобы обновление пакета их не затёрло. Но имя файла имеет значение:
sudo tee /etc/ssh/sshd_config.d/10-hardening.conf <<'EOF'
PasswordAuthentication no
PermitRootLogin no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
MaxAuthTries 3
LogLevel VERBOSE
EOF
Дело в том, что OpenSSH использует первое встреченное значение параметра, а не последнее, как почти везде. Файлы из sshd_config.d читаются по алфавиту, и облачные образы Ubuntu кладут туда 50-cloud-init.conf, в котором нередко стоит PasswordAuthentication yes. Ваш файл с номером 90 в такой ситуации не сделает ничего: настройка вроде бы прописана, а пароль продолжает работать. Отсюда номер 10 — он читается раньше.
Проверить, что именно получилось в итоге, можно не гадая:
sudo sshd -T | grep -Ei 'passwordauth|permitrootlogin|pubkeyauth'
Эта команда печатает действующую конфигурацию после всех включений. Ей и верьте, а не содержимому файлов.
Дальше — проверка синтаксиса и мягкая перезагрузка службы:
sudo sshd -t && sudo systemctl reload ssh
sshd -t обязателен: опечатка в конфиге при restart оставит службу лежать, а вас — снаружи. reload к тому же не рвёт открытые сессии.
Ubuntu 24.04: порт меняется не там
Отдельная ловушка свежих Ubuntu: sshd там запускается через сокет systemd. Строка Port в sshd_config в этом режиме не делает ничего — слушает сокет, а не демон. Если вы меняете порт, править надо его:
sudo systemctl edit ssh.socket
и указывать ListenStream= (пустое значение сбрасывает прежнее) с новым портом. Симптом, по которому это узнаётся: конфиг изменён, служба перезапущена, а сервер по-прежнему отвечает на 22.
Кстати, о смене порта: как защита она не работает — сканеры находят службу на любом порту за минуты. Единственный её эффект — в логах становится тише, потому что массовый перебор идёт только по 22. Это удобно, но с безопасностью не путайте.
Кто вообще может входить
Полезное дополнение — явный список:
AllowUsers deploy admin
Всё, что не перечислено, отсекается ещё до проверки ключа. Это заодно закрывает случай, когда какой-нибудь пакет заводит системного пользователя с оболочкой и домашним каталогом.
Запасной вход
Один ключ на одном ноутбуке — единственная точка отказа. Диск умирает, ноутбук теряется, и сервер становится недоступен навсегда. Разумный минимум:
- второй ключ с другого устройства в
authorized_keys; - копия приватного ключа в менеджере паролей или на зашифрованной флешке;
- проверенный доступ к консоли у хостера — VNC или serial. Проверенный означает, что вы туда хотя бы раз входили, а не «где-то в панели есть кнопка».
Заодно посмотрите, что уже лежит в authorized_keys — и у своего пользователя, и у root. Чужой ключ там переживает любую смену пароля и остаётся рабочим доступом.
После
Перебор паролей никуда не денется, просто он теперь бесполезен: в логах останутся тысячи Failed password, ни одна из которых не может закончиться успехом. А вот на что смотреть теперь стоит — это на успешные входы: с какого адреса, под каким пользователем, в какое время. Успешный вход по ключу с незнакомого адреса — событие куда более важное, чем миллион неудачных попыток, и заметить его в общем потоке гораздо труднее. Именно эту картину показывает страница демо ниже.