Каждый раз, поднимая новый сервер, я правлю конфиг руками. В итоге набор строк устоялся, и он короче, чем кажется по статьям в интернете.

Клиентская часть: ~/.ssh/config

Host *
  ServerAliveInterval 30
  ServerAliveCountMax 3
  HashKnownHosts yes

Host prod
  HostName 203.0.113.10
  User deploy
  IdentityFile ~/.ssh/id_ed25519_prod
  IdentitiesOnly yes

ServerAliveInterval — чтобы соединение не рвалось на «простаивающем» NAT. IdentitiesOnly yes — чтобы клиент не перебирал все ключи по очереди: при десяти ключах это и задержка, и отказ аутентификации на серверах с MaxAuthTries 3.

Серверная часть: /etc/ssh/sshd_config.d/99-hardening.conf

PasswordAuthentication no
KbdInteractiveAuthentication no
PermitRootLogin prohibit-password
MaxAuthTries 3
AllowUsers deploy

Порядок применения: файлы из sshd_config.d/ подключаются директивой Include в начале sshd_config, и для каждого параметра действует первое найденное значение. Поэтому дублирующий PermitRootLogin yes ниже по файлу ни на что не влияет — но проверять надо именно sshd -T, а не глазами:

sshd -T | grep -E 'passwordauthentication|permitrootlogin|maxauthtries'

sshd -T показывает эффективную конфигурацию после всех включений. Это единственный способ убедиться, что вы запретили пароли, а не думаете, что запретили.

Что я перестал настраивать

  • Смену порта. От перебора не спасает (сканируют всё), а в конфигах и документации создаёт мусор. Вход по ключу с MaxAuthTries 3 решает ту же задачу честнее.
  • fail2ban при выключенных паролях. Банить нечего: подобрать ключ перебором нельзя, а логи забиваются шумом ботов, которые всё равно отсекаются на этапе аутентификации.

Одна вещь, которую стоит сделать сразу

Положить второй ключ (резервный, в другом месте) в authorized_keys до того, как выключите пароли. Звучит банально, но именно потеря единственного ключа — самая частая причина, по которой люди возвращают вход по паролю и через месяц теряют сервер.