Сообщения об ошибках SSH намеренно скупы — протокол не станет объяснять незнакомцу, почему ему отказали. Это хорошая безопасность и плохая эргономика: сообщение, которое вы видите, часто на два шага отстоит от настоящей проблемы. Это полевой справочник по тринадцати ошибкам, с которыми вы действительно столкнётесь: что каждая на самом деле значит и какой путь к исправлению самый быстрый.
Один инструмент на старте: ssh -v user@host (можно до -vvv — как читать этот вывод (на английском)). Почти любая загадка ниже перестаёт быть загадкой, как только вы увидите, на каком шаге рукопожатия всё падает.
Ошибки вкратце
| Ошибка | Что означает | Первый шаг |
|---|---|---|
Connection refused | Хост ответил; на этом порту ничего не слушает | Проверьте, что sshd запущен и на том порту, куда вы стучались |
Connection timed out | Пакеты пропали по пути | Проверьте облачный файрвол / security group |
Permission denied (publickey) | Ни один предложенный ключ не принят | Проверьте пользователя, затем ключ, затем authorized_keys |
Permission denied (без запроса) | Парольная аутентификация выключена; нужен ключ | Используйте ключ или зайдите через консоль провайдера |
Host key verification failed | Ключ сервера изменился с тех пор, как вы ему доверились | Проверьте по другому каналу, затем ssh-keygen -R |
Too many authentication failures | Агент предложил слишком много ключей | -o IdentitiesOnly=yes вместе с -i |
UNPROTECTED PRIVATE KEY FILE | Файл ключа доступен для чтения другим | chmod 600 на приватный ключ |
Broken pipe | Простаивающее соединение сбросили | Добавьте ServerAliveInterval |
no matching key exchange method | Устаревший сервер, современный клиент | Включите один алгоритм только для этого хоста |
Connection reset by peer | TCP захлопнулся до приветствия SSH | Проверьте fail2ban / MaxStartups |
Bad configuration option | Ваш клиент слишком стар для строки конфигурации | Обновите ssh или защитите эту строку |
did not receive identification string | Кто-то подключился, но не прислал баннер | Обычно сканер; игнорируйте на стороне сервера |
Unspecified GSS failure | Попытка Kerberos не удалась, затем откат | Игнорируйте, если вход всё же проходит |
1. Connection refused
Машина достижима, но на порту, в который вы постучались, ничего не слушает. Эта ошибка почти никогда не про вас:
- sshd не запущен —
systemctl status sshdиз консоли (у VPS-провайдеров есть веб-консоль как раз на такой случай); - он слушает на нестандартном порту — попробуйте
ssh -p 2222или проверьтеPortв/etc/ssh/sshd_config; - файрвол активно отклоняет (а не отбрасывает) порт.
Если вы только что пересобрали сервер — дело в файрволе. Если вчера работало — упал sshd или сменился порт.
Полное решение: connection refused против timed out, разобрано.
2. Connection timed out
Отличается от refused: ваши пакеты пропадают. Хост лежит, IP неверный или — чаще всего на облачных машинах — security group / сетевой ACL молча отбрасывает порт 22. Сначала проверьте правила файрвола провайдера, затем — не находитесь ли вы в сети, которая блокирует исходящий 22 (гостевой Wi-Fi в отелях и офисах это обожает; чтобы убедиться, попробуйте доступ через порт 443 или другую сеть).
Полное решение: в том же разборе refused против timed out ветка timed out расписана по шагам.
3. Permission denied (publickey)
Чемпион всех времён. Сервер принимает только аутентификацию по ключу и не принял ни один из предложенных вами. В порядке вероятности:
- Не тот пользователь.
ubuntuв образах Ubuntu,ec2-userв Amazon Linux,rootна большинстве «голых» VPS. Тот же ключ с неправильным именем пользователя даёт ровно эту ошибку — облачные образы каждый выбирает свой логин, и это половина статьи первый вход на EC2/VPS (на английском). - Ваш ключ не был предложен.
ssh -vпоказывает каждый перепробованный ключ. Если вашего ключа в списке нет, укажите на него явно:ssh -i ~/.ssh/id_ed25519 user@host. - Ключа нет на сервере. Его публичная половина должна быть одной строкой в
~user/.ssh/authorized_keys— для того самого пользователя, а не root. - Права на стороне сервера. sshd откажется учитывать
authorized_keys, если домашний каталог,~/.ssh(700) или сам файл (600) доступен на запись группе. Это классическое «я скопировал ключ, а он всё равно не работает».
Полное решение: Permission denied (publickey): быстрое системное исправление (на английском) проходит каждого виновника по порядку.
4. Permission denied, когда вы ждали запрос пароля
Если вы хотели парольную аутентификацию, но вас так и не спросили, значит на сервере PasswordAuthentication no — большинство облачных образов идут именно так, и это правильное значение по умолчанию. Зайдите через консоль провайдера или уже имеющийся ключ, а затем добавьте новый ключ как положено, вместо того чтобы снова включать пароли.
5. Host key verification failed / REMOTE HOST IDENTIFICATION HAS CHANGED
Страшный баннер с энергетикой ASCII-черепа. Сервер предъявил ключ, отличный от того, которому вы доверились раньше. Два объяснения: машину законно пересобрали/переустановили (в подавляющем большинстве случаев) или что-то между вами и сервером выдаёт себя за него (случай, ради которого предупреждение и существует).
Если — и только если — вы знаете, что сервер пересобрали: ssh-keygen -R hostname удаляет устаревшую запись, а следующее подключение доверяет заново. Не вшивайте это удаление в свой рабочий процесс вслепую: тот единственный раз, когда предупреждение настоящее, — это единственное предупреждение, которое вам достанется.
Полное решение: Host key verification failed и как исправить это правильно (на английском).
6. Too many authentication failures
Ваш агент с энтузиазмом предложил шесть ключей, а серверный MaxAuthTries сказал «хватит». Велите клиенту предлагать только тот ключ, который вы имеете в виду:
ssh -o IdentitiesOnly=yes -i ~/.ssh/the_right_key user@host
…или закрепите это в ~/.ssh/config для каждого хоста. Если вы носите много ключей, IdentitiesOnly yes под Host * избавит вас от этой ошибки навсегда.
7. WARNING: UNPROTECTED PRIVATE KEY FILE
Ваш приватный ключ доступен для чтения другим, и клиент отказывается его использовать. chmod 600 ~/.ssh/id_ed25519. В Windows это появляется после копирования ключей между машинами или из облачного диска — исправьте через свойства файла «Безопасность» или вовсе держите ключи вне синхронизируемых папок.
8. client_loop: send disconnect: Broken pipe (сессия, которая умирает, стоит отвернуться)
Простаивающие соединения сбрасывает NAT-роутер или агрессивный файрвол между вами и сервером. Keepalive-пакеты лечат это на стороне клиента:
Host *
ServerAliveInterval 30
ServerAliveCountMax 4
Две минуты тишины допустимы, пакеты каждые 30 секунд, чтобы таблица NAT никогда о вас не забывала. Если сессии умирают под нагрузкой, а не на простое, — это другой зверь: смотрите на MTU (особенно у VPN), а не на keepalive.
9. no matching key exchange method found / no matching cipher
Вы разговариваете с чем-то старым — роутером, свитчом, устройством, застрявшим на устаревшей криптографии. Современный OpenSSH убрал эти алгоритмы не просто так. Включайте их обратно только для этого одного хоста, никогда глобально:
Host ancient-switch
KexAlgorithms +diffie-hellman-group14-sha1
Ciphers +aes256-cbc
Сообщение об ошибке называет алгоритмы, которые предложил сервер; добавьте наименее плохой из перечисленных.
10. ssh_exchange_identification: read: Connection reset by peer
TCP-соединение открылось и тут же захлопнулось, ещё до того, как SSH успел поздороваться. Обычные подозреваемые: fail2ban или DenyHosts забанил ваш IP (проверьте /etc/hosts.deny и джейл fail2ban из консоли), sshd перегружен (MaxStartups исчерпан сканером, долбящим по порту) или проверка здоровья балансировщика съедает соединения. Если это fail2ban и сервер ваш, решение — вход через консоль и fail2ban-client unban <your-ip>, а затем увести SSH с радаров сканеров или ужесточить джейл, чтобы на следующей неделе не оказаться сопутствующими потерями.
11. Bad configuration option: pubkeyacceptedalgorithms
Это не проблема сервера — ваш локальный ssh слишком стар для вашего файла конфигурации. PubkeyAcceptedAlgorithms появился в OpenSSH 8.5 (он заменил PubkeyAcceptedKeyTypes); подсуньте эту строку клиенту постарше — штатному ssh в macOS определённого возраста, старому дистрибутиву, минимальному образу контейнера — и он вовсе откажется разбирать файл. Три выхода: обновить клиент (ssh -V подскажет, где вы находитесь); использовать старое написание PubkeyAcceptedKeyTypes, которое новые версии всё ещё принимают как псевдоним; или защитить строку, чтобы её читали только способные клиенты:
Match all
# only OpenSSH >= 8.5 gets here via Include ordering
— на практике самая простая защита — держать чувствительные к версии опции в отдельном файле, подключаемом через Include, чтобы старый клиент на тех же dotfiles просто его пропускал. Любая ошибка такой формы (Bad configuration option: <something>) всегда означает одно и то же: это слово неизвестно этому бинарнику — сначала проверьте написание опции, затем версию бинарника.
12. did not receive identification string / invalid ssh identification string
Обе живут на самом первом шаге SSH — обмене баннерами, до всякой криптографии. did not receive identification string from <ip> sshd пишет на стороне сервера, когда что-то открыло TCP-соединение к порту 22, но так и не прислало строку SSH-2.0-...: сканер портов, проверка здоровья балансировщика, зонд мониторинга или сдавшийся клиент. В логах вашего сервера это почти всегда фоновый шум, а не сбой — если только это не ваш клиент не может подключиться, и тогда что-то на пути (прокси, TCP wrapper, IDS) съедает баннер.
kex_exchange_identification: ... invalid ssh identification string — зеркальное отражение: что-то ответило, но не-SSH-данными. Обычные причины, по порядку: вы направили ssh не на тот порт — HTTP-сервер, базу данных, captive-портал, отдающий HTML; middlebox на пути перехватывает соединение и отвечает вместо сервера; или ошибка в ProxyCommand/ProxyJump заворачивает в клиент что-то, что не является SSH-потоком — страница ошибки прокси приходит туда, где должен быть баннер. Убедитесь, что вы действительно разговариваете с sshd: nc <host> 22 должен сразу напечатать баннер SSH-2.0-OpenSSH.... Если печатает HTML или ничего, то неверен порт (или хост, или прокси-прыжок), а не ваш ключ.
13. Unspecified GSS failure / debug1: unspecified GSS failure. Minor code may provide more information
Шум от Kerberos. OpenSSH по умолчанию пробует аутентификацию GSSAPI (Kerberos) перед вашим ключом, и если вы не в области Kerberos — а это большинство — она не удаётся, пишет это на уровне debug, затем откатывается к аутентификации по ключу и подключается нормально. Если соединение в итоге удаётся, эта строка безвредна; игнорируйте её. Она важна, только если вы действительно полагаетесь на Kerberos SSO и аутентификация не проходит — тогда это настоящая проблема с билетом/областью (проверьте klist, рассинхрон часов и SPN хоста в DNS). Чтобы убрать шум в не-Kerberos-окружении, добавьте в конфигурацию GSSAPIAuthentication no.
Сделайте исправления постоянными
Половина из этого — разовые исправления; другая половина заслуживает строки в ~/.ssh/config, чтобы больше не возвращаться — keepalive, IdentitiesOnly, порты и ключи для каждого хоста. Конфиг лучше памяти.
Ещё одна вещь, которая лучше памяти, — это клиент, который хранит состояние за вас. Termalin хранит настройки для каждого хоста — порт, пользователя, ключ, keepalive — вместе с самим хостом, проверяет серверы при первом подключении и громко предупреждает, когда меняется отпечаток, а его панель статистики показывает жизненные показатели машины в реальном времени, так что «а машина-то вообще жива?» перестаёт быть шагом диагностики. У тарифа Free нет ограничений на число хостов — заберите его и навсегда выведите из обихода несколько этих ошибок.