SSD Nodes Learn Hosting plans →
Руководства Matt ConnorАвтор: Matt Connor

Ошибка SSH Too many authentication failures: решение

Ошибка Too many authentication failures возникает при превышении лимита MaxAuthTries. Узнайте, как исправить проблему через настройку IdentitiesOnly в ssh_config.

Что означает ошибка "Too many authentication failures"

Ошибка "Too many authentication failures" означает, что ваш SSH-клиент предложил серверу больше ключей, чем тот готов проверить, и сервер закрыл соединение до того, как был использован нужный ключ. Это почти всегда проблема на стороне клиента. Ключ находится на вашем диске, сервер содержит его в authorized_keys, но это не помогает, так как соединение разрывается слишком рано.

Цепочка событий выглядит так. ssh-agent хранит все закрытые ключи, которые вы в него загрузили. Клиент предлагает эти ключи серверу по очереди, так как он не знает, какой из них подходит для данной учетной записи. Сервер отклоняет каждый ключ, которого нет в authorized_keys, и засчитывает каждый отказ как неудачную попытку аутентификации. Параметр MaxAuthTries в sshd_config ограничивает количество допустимых сбоев для одного соединения. По умолчанию это значение равно 6. Если в вашем агенте десять ключей, а нужный стоит восьмым в очереди, сервер разорвет соединение раньше, чем дойдет до него.

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

Что учитывает сервер и как работает MaxAuthTries

Аутентификация по открытому ключу начинается как процесс перебора. Клиент отправляет открытый ключ и запрашивает, примет ли сервер подпись, созданную с его помощью. Сервер отвечает «да» или «нет». Ответ «нет» считается неудачной попыткой, точно так же, как и неверный пароль.

Страница руководства sshd_config(5) описывает это ограничение: «Указывает максимальное количество попыток аутентификации, разрешенных для одного соединения. Как только количество неудач достигает половины этого значения, дополнительные ошибки записываются в журнал. Значение по умолчанию — 6».

Шести попыток достаточно для человека, вводящего пароль. Этого мало для агента, хранящего десять ключей. Как только счетчик неудач достигает предела, sshd разрывает соединение и записывает в системный журнал строку следующего вида:

error: maximum authentication attempts exceeded for deploy from 203.0.113.10 port 51292 ssh2

Ваш клиент выводит вторую часть того же события:

Received disconnect from 203.0.113.10 port 22:2: Too many authentication failures
Disconnected from 203.0.113.10 port 22

Это не та ошибка, что возникает при ошибке SSH permission denied (publickey). В том случае сервер проверил все предложенные вами ключи и не принял ни один из них. Здесь же сервер просто прекратил проверку. Если перепутать эти две ситуации, можно потратить весь день на повторное копирование ключа, который изначально был верным.

Почему один и тот же ключ работает с ноутбука коллеги

В ключе и на сервере нет никаких различий. В их агенте хранятся два ключа, а в вашем — двенадцать. Предложение, которое для них приходит первым, для вас оказывается девятым, и к этому моменту соединение уже завершено.

Количество ключей растет незаметно. AddKeysToAgent yes в ~/.ssh/config добавляет каждый используемый вами ключ в агент и оставляет его там. Агенты связок ключей в графической оболочке, такие как GNOME Keyring в Linux или login keychain в macOS, загружают ключи при входе в систему без запроса. Добавьте ключ клиента, ключ хоста git и ключ лабораторного сервера в течение года, и однажды сервер, который всегда работал, начнет вам отказывать. На сервере ничего не изменилось. Ваш агент просто стал переполнен.

Как просмотреть предлагаемые ключи с помощью ssh -v

Запустите проблемное соединение с флагом -v и изучите трассировку.

ssh -v deploy@203.0.113.10

Важны два типа строк. Will attempt key: перечисляет идентификаторы, которые собрал клиент, в порядке их использования. Offering public key: появляется один раз для каждого ключа, фактически отправленного на сервер.

debug1: Will attempt key: /home/you/.ssh/id_ed25519 ED25519 SHA256:AAAA... agent
debug1: Will attempt key: /home/you/.ssh/id_rsa RSA SHA256:BBBB... agent
debug1: Offering public key: /home/you/.ssh/id_ed25519 ED25519 SHA256:AAAA... agent
debug1: Authentications that can continue: publickey,password
debug1: Offering public key: /home/you/.ssh/id_rsa RSA SHA256:BBBB... agent

Ваши пути, типы ключей и отпечатки будут отличаться. Вам нужно посчитать количество строк Offering public key: до момента разрыва соединения. Если список предложений проходит, а сессия завершается без появления нужного вам ключа, диагноз ясен. Слово agent в конце строки означает, что идентификатор был получен из ssh-agent. Слово explicit означает, что он был получен из строки IdentityFile или из -i в командной строке.

Затем проверьте, какие ключи хранятся в агенте:

ssh-add -l

Каждая строка вывода соответствует одному загруженному ключу. Если выводится The agent has no identities., значит, проблема не в агенте, и вам следует изучить строки IdentityFile в ~/.ssh/config. Если выводится Could not open a connection to your authentication agent., значит, агент не запущен, а предлагаемые ключи берутся из файлов ключей по умолчанию.

Решение 1: IdentitiesOnly с одним ключом на хост

IdentitiesOnly yes указывает ssh предлагать только те идентификаторы, которые вы настроили, и игнорировать остальные, которые предлагает агент. Используйте это вместе со строкой IdentityFile, чтобы клиент отправлял только одно предложение.

Host vps
  HostName 203.0.113.10
  User deploy
  IdentityFile ~/.ssh/id_ed25519_vps
  IdentitiesOnly yes

Сохраните это в ~/.ssh/config, затем выполните chmod 600 ~/.ssh/config. Если файл доступен для записи группе или всем пользователям, ssh откажется работать и выдаст Bad owner or permissions on /home/you/.ssh/config. Теперь ssh vps предложит один ключ, а ssh -v vps должен показать ровно одну строку Offering public key:.

Два нюанса часто вызывают удивление.

  • IdentitiesOnly yes сам по себе не означает «один ключ». Без строки IdentityFile файлы идентификаторов по умолчанию считаются настроенными, поэтому ssh всё равно пробует ~/.ssh/id_ed25519, ~/.ssh/id_rsa и другие стандартные ключи. Вам также нужна строка IdentityFile: как только она установлена, ssh перестаёт добавлять ключи по умолчанию.
  • Агент по-прежнему выполняет подпись. IdentitiesOnly управляет тем, какие ключи предлагаются, а не тем, кто их подписывает. Если закрытый ключ, указанный в IdentityFile, загружен в агент, агент создаст подпись, и парольная фраза не потребуется. Вы даже можете указать IdentityFile на соответствующий файл .pub; это делается, когда закрытый ключ хранится только в агенте или на аппаратном токене.

Одна ловушка в ~/.ssh/config может незаметно отменить это решение. Большинство параметров принимают первое найденное значение, поэтому специфические блоки Host должны располагаться выше Host *. IdentityFile не следует этому правилу. В руководстве сказано: «В конфигурационных файлах можно указать несколько файлов идентификаторов; все эти идентификаторы будут перебираться последовательно». IdentityFile в разделе Host * добавляется к вашему значению для конкретного хоста, а не заменяет его, поэтому забытая глобальная строка добавляет лишнее предложение в каждое соединение.

Если вам нужна глобальная страховка, установите только флаг в конце файла:

Host *
  IdentitiesOnly yes

Тогда для каждого хоста потребуется свой IdentityFile, что и является желаемым результатом. Использование одного ключа на сервер позволяет отозвать доступ к одной машине, не перевыпуская всё остальное. Эту привычку стоит выработать как можно раньше: см. как управлять SSH-ключами для каждой машины.

Исправление 2: очистка или перезапуск агента

Если вы пока не можете отредактировать конфигурацию, очистите агент и загрузите только необходимые данные.

ssh-add -l                    # list what is loaded
ssh-add -d ~/.ssh/id_rsa      # remove one key
ssh-add -D                    # remove every key
ssh-add ~/.ssh/id_ed25519_vps # load the one you need

Если соединение заработало сразу после ssh-add -D, значит, проблема была в агенте. Рассматривайте это как тест, а не как исправление. Агент связки ключей (keyring agent) рабочего стола перезагружает ключи при следующем входе в систему, поэтому завтра проблема вернется. Строка IdentitiesOnly в ~/.ssh/config сохраняется после перезагрузки. Пустой агент — нет.

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

ssh-add -t 1800 ~/.ssh/id_ed25519_vps

Ключ будет удален через 1800 секунд после добавления. Перезапуск агента также помогает; способ зависит от того, как он был запущен. Процесс ssh-agent, который вы запустили вручную, останавливается командой ssh-agent -k. Если вы используете собственный пользовательский юнит systemd, перезапустите его с помощью systemctl --user restart <unit>. Агент связки ключей перезапускается вместе с сеансом рабочего стола.

Способ 3: разовая команда для сервера, к которому вы обращаетесь один раз

Для хоста, который вы не будете добавлять в свою конфигурацию, укажите те же параметры в командной строке:

ssh -o IdentitiesOnly=yes -i ~/.ssh/id_ed25519_vps deploy@203.0.113.10

Использование -i само по себе — самая частая ошибка. Команда -i добавляет ключ в список идентификаторов. Она не удаляет ключи агента из этого списка, поэтому все остальные ключи по-прежнему предлагаются первыми, и соединение разрывается при достижении лимита. Запустите ssh -v -i ~/.ssh/id_ed25519_vps deploy@203.0.113.10 без IdentitiesOnly, и вы увидите, что ключи агента предлагаются первыми. Для -i требуется -o IdentitiesOnly=yes рядом.

Чтобы полностью исключить агента из процесса для одного соединения:

ssh -o IdentityAgent=none -i ~/.ssh/id_ed25519_vps deploy@203.0.113.10

В этом случае ssh считывает закрытый ключ с диска и запрашивает парольную фразу, если она установлена.

Инструменты, построенные на базе ssh, принимают ту же опцию:

scp -o IdentitiesOnly=yes -i ~/.ssh/id_ed25519_vps report.tar.gz deploy@203.0.113.10:/tmp/
rsync -av -e "ssh -o IdentitiesOnly=yes -i ~/.ssh/id_ed25519_vps" ./site/ deploy@203.0.113.10:/srv/site/
GIT_SSH_COMMAND="ssh -o IdentitiesOnly=yes -i ~/.ssh/id_ed25519_vps" git clone git@example.com:team/repo.git

Почему ошибка возникает на втором этапе соединения

При ForwardAgent yes сокет агента становится доступен на сервере, к которому вы подключаетесь. Команда ssh, запущенная на этом сервере, использует ваш локальный агент со всеми вашими ключами через перенаправленный сокет. Именно поэтому ошибка может появиться при переходе с jump-хоста на конечный сервер, хотя первый этап прошел успешно. Выполните echo $SSH_AUTH_SOCK на промежуточной машине: пустой вывод означает, что агент недоступен. Путь к сокету означает, что какой-то агент есть, но не обязательно ваш, так как агент, запущенный на этой машине, устанавливает ту же переменную. Запустите там же ssh-add -l: если в списке есть ключи с вашей локальной машины, значит, перенаправление активно.

Перенаправление агента несет и вторую угрозу. Любой пользователь с правами root на промежуточной машине может использовать ваш агент для аутентификации от вашего имени, пока ваша сессия открыта. ProxyJump позволяет избежать обеих проблем:

ssh -J deploy@jump.example.com deploy@10.0.0.5

ProxyJump открывает соединение через jump-хост и аутентифицируется на конечном сервере прямо с вашей машины, поэтому ваши локальные настройки ~/.ssh/config применяются на каждом этапе, включая IdentitiesOnly. Отключение ForwardAgent — стандартный шаг при укреплении безопасности SSH на VPS.

Стоит ли увеличивать MaxAuthTries на сервере?

Обычно нет. Сначала проверьте текущее значение:

sudo sshd -T | grep -i maxauthtries

sshd -T выводит эффективную конфигурацию, включая значения по умолчанию, поэтому команда показывает реальный параметр, даже если в sshd_config ничего не указано. Добавьте -C user=deploy,host=example.com,addr=203.0.113.10, если вы используете блоки Match, так как они вычисляются для каждого соединения и в противном случае пропускаются.

Увеличение лимита работает в узком смысле: большее число попыток дает некорректно работающему клиенту больше пространства для маневра:

MaxAuthTries 20

Проверьте файл конфигурации и перезагрузите сервис. Во время выполнения этих действий держите открытой вторую сессию:

sudo sshd -t
sudo systemctl reload ssh      # Debian and Ubuntu
sudo systemctl reload sshd     # RHEL family

Если systemctl is-enabled ssh.socket сообщает enabled в Ubuntu 24.04, значит, sshd активируется через сокет. ssh.socket в Ubuntu не запускает новый демон для каждого соединения: он запускает ssh.service при поступлении первого подключения, и этот сервис продолжает работать, обрабатывая последующие запросы. Указанная выше перезагрузка по-прежнему применяет изменения. Если ssh.service еще не активен, перезагружать нечего, и следующее соединение запустит его уже с новым файлом конфигурации.

Теперь оцените результат изменений. Клиент предлагает ключи, которые этот сервер никогда не примет. Увеличение лимита заставляет сервер обрабатывать двадцать отклоненных предложений за соединение вместо шести — для каждого подключающегося клиента и для каждого переборщика паролей в сети. Каждое предложение требует от сервера поиска в authorized_keys. Ваш собственный вход в систему останется медленным, так как нужный ключ по-прежнему находится в конце очереди. Добавьте тринадцатый ключ в свой агент, и вы вернетесь к исходной точке, снова нуждаясь в увеличении лимита.

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

Почему fail2ban может заблокировать вас за это

sshd не логирует каждый отклоненный ключ. При значении LogLevel INFO по умолчанию, отклоненный ключ для существующей учетной записи записывается в лог только после того, как количество неудачных попыток соединения достигает половины MaxAuthTries. Именно это подразумевается в руководстве фразой: «Как только количество сбоев достигает половины этого значения, дополнительные сбои записываются в лог». При значении по умолчанию, равном 6, первые три отклоненных предложения ключа не записываются в лог. Последние три появляются в виде строк, подобных этой, за которыми следует строка maximum authentication attempts exceeded:

Failed publickey for deploy from 203.0.113.10 port 51292 ssh2: ED25519 SHA256:AAAA...

Эти строки выглядят как череда сбоев, но фильтр sshd в fail2ban не учитывает их. Его стандартный параметр publickey = nofail считывает строку Failed publickey для корректного пользователя только для того, чтобы извлечь адрес и имя пользователя. Учитывается только строка maximum authentication attempts exceeded, поэтому одно соединение, достигшее лимита, добавляет один сбой, а не несколько. Jail блокирует исходный адрес, как только maxretry сбоев происходят в течение findtime, а собственные параметры jail.conf в fail2ban устанавливают эти значения на 5 и 10 минут. Около пяти неудачных соединений за десять минут достаточно, чтобы заблокировать ваш собственный адрес, а скрипт или инструмент, который повторяет попытки в цикле, достигает этого лимита быстро.

Затем симптом меняется, и именно это сбивает людей с толку. Вы перестаете видеть сообщение "Too many authentication failures" и не видите вообще ничего: соединение зависает и в конечном итоге прерывается по таймауту, потому что файрвол теперь отбрасывает ваши пакеты, вместо того чтобы отвечать на них. Таймаут там, где раньше вы получали сообщение об ошибке, — это сигнал, и это различие описано в SSH connection refused versus connection timed out.

Через консоль вашего провайдера или с другого адреса проверьте jail и снимите блокировку:

sudo fail2ban-client status sshd
sudo fail2ban-client set sshd unbanip 203.0.113.10

Добавьте свой адрес в ignoreip в jail.local, пока вы разбираетесь с клиентом, а затем удалите его, когда закончите. Сам jail настраивается в the fail2ban guide for Ubuntu 24.04.

Что сделать один раз, чтобы проблема не повторялась

Назначьте каждому серверу собственный блок Host в файле ~/.ssh/config, указав HostName, User, IdentityFile и IdentitiesOnly yes. После этого команда ssh vps станет короткой, она будет предлагать ровно один ключ и не вызовет срабатывание MaxAuthTries, независимо от того, насколько переполнен ваш агент. Это также позволит сохранить вывод ssh -v достаточно кратким, чтобы его можно было прочитать в день, когда произойдет какой-либо другой сбой.

FAQ

Как прямо сейчас исправить ошибку "Too many authentication failures"?

Предлагайте только один ключ вместо всех имеющихся. Для немедленного подключения выполните ssh -o IdentitiesOnly=yes -i ~/.ssh/your_key user@host. Для постоянного решения добавьте блок в ~/.ssh/config с параметрами HostName, User, IdentityFile, указывающими на нужный ключ, а также IdentitiesOnly yes и chmod 600 ~/.ssh/config. Проверьте результат с помощью ssh -v: вы должны увидеть одну строку Offering public key: для этого хоста.

Почему ssh -i всё равно предлагает другие мои ключи?

Потому что -i добавляет идентификатор в список, а не ограничивает его. Ключи, загруженные в ssh-agent, остаются в списке и по-прежнему предлагаются, часто раньше вашего, поэтому сервер может достичь лимита MaxAuthTries до того, как дойдет очередь до вашего ключа. -o IdentitiesOnly=yes — это опция, которая ограничивает ssh только указанными вами идентификаторами. Используйте -i и -o IdentitiesOnly=yes вместе или -o IdentityAgent=none, чтобы полностью игнорировать агент для конкретного подключения.

Стоит ли увеличивать MaxAuthTries на сервере, чтобы исправить это?

Нет, почти во всех случаях. Клиент отправляет ключи, которые сервер никогда не примет, а увеличение лимита лишь заставляет сервер обрабатывать больше отклоненных предложений для каждого подключения, для каждого клиента и для каждой попытки перебора паролей. Кроме того, проблема вернется, как только в ваш агент добавится еще один ключ. Проверьте текущее значение с помощью sudo sshd -T | grep -i maxauthtries, если вам интересно, а затем исправьте настройки клиента с помощью IdentitiesOnly.

Почему это началось на сервере, который отлично работал в прошлом месяце?

Ваш агент стал содержать больше ключей. AddKeysToAgent yes в ~/.ssh/config сохраняет каждый используемый вами ключ, а агенты связок ключей в графических оболочках загружают ключи при входе в систему автоматически. Как только количество загруженных ключей превышает значение MaxAuthTries на сервере, любое подключение к серверу, чей ключ находится в конце списка предложений, начинает завершаться ошибкой. Выполните ssh-add -l и сравните количество ключей с лимитом на сервере.

Может ли это привести к блокировке моего IP-адреса через fail2ban?

Да, хотя и медленнее, чем можно предположить по логам сервера. Стандартный фильтр sshd в fail2ban не учитывает строки Failed publickey для корректного пользователя. Он считает строку maximum authentication attempts exceeded, поэтому каждое подключение, достигающее лимита, засчитывается как одна ошибка. При стандартных настройках maxretry = 5 и findtime = 10m примерно пять таких подключений за десять минут приведут к блокировке вашего адреса. Признаком блокировки является то, что ошибка сменяется зависанием, а затем таймаутом, так как пакеты начинают отбрасываться, а не отклоняться. Снимите блокировку через консоль с помощью sudo fail2ban-client set sshd unbanip <your address> и исправьте настройки клиента перед повторным подключением.

#ssh#ssh-agent#openssh#ssh-config#troubleshooting