Каждый раз, когда я использую PuTTY для входа по SSH на удалённую систему Linux для управления, процесс удалённого входа очень медленный — после ввода имени пользователя мне приходится ждать около 30 секунд, прежде чем появится приглашение для ввода пароля. Когда реально приходится решать проблемы, особенно когда нужна быстрая реакция, эта ситуация поистине невыносима.
Но позже, специально проверив это, я обнаружил, что это не общая проблема в каждой системе. Машины с проблемой в основном сосредоточены на CentOS. В той же системе Debian процесс удалённого подключения проходит очень быстро, без ощущения задержки или торможения. Может, это проблема CentOS?

Из любопытства я посмотрел, в чём различия между двумя системами при использовании SSH
CentOS:
ssh -v ssh_test@192.168.128.137
Информация, отображаемая во время удалённого входа по SSH, выглядит следующим образом:
OpenSSH_6.0p1 Debian-4, OpenSSL 1.0.1e 11 Feb 2013 ...Some sensitive information... debug1: Remote protocol version 2.0, remote software version OpenSSH_5.3 debug1: match: OpenSSH_5.3 pat OpenSSH_5* debug1: Enabling compatibility mode for protocol 2.0 debug1: Local version string SSH-2.0-OpenSSH_6.0p1 Debian-4 debug1: SSH2_MSG_KEXINIT sent debug1: SSH2_MSG_KEXINIT received debug1: kex: server->client aes128-ctr hmac-md5 none debug1: kex: client->server aes128-ctr hmac-md5 none debug1: SSH2_MSG_KEX_DH_GEX_REQUEST(1024<1024<8192) sent debug1: expecting SSH2_MSG_KEX_DH_GEX_GROUP debug1: SSH2_MSG_KEX_DH_GEX_INIT sent debug1: expecting SSH2_MSG_KEX_DH_GEX_REPLY ...Some sensitive information... debug1: ssh_rsa_verify: signature correct debug1: SSH2_MSG_NEWKEYS sent debug1: expecting SSH2_MSG_NEWKEYS debug1: SSH2_MSG_NEWKEYS received debug1: Roaming not allowed by server debug1: SSH2_MSG_SERVICE_REQUEST sent debug1: SSH2_MSG_SERVICE_ACCEPT received debug1: Authentications that can continue: publickey,gssapi-keyex,gssapi-with-mic,password debug1: Next authentication method: gssapi-keyex debug1: No valid Key exchange context debug1: Next authentication method: gssapi-with-mic debug1: Unspecified GSS failure. Minor code may provide more information Cannot determine realm for numeric host address debug1: Unspecified GSS failure. Minor code may provide more information Cannot determine realm for numeric host address debug1: Unspecified GSS failure. Minor code may provide more information debug1: Unspecified GSS failure. Minor code may provide more information Cannot determine realm for numeric host address debug1: Next authentication method: publickey debug1: Trying private key: /home/mitchellchu/.ssh/id_rsa debug1: Trying private key: /home/mitchellchu/.ssh/id_dsa debug1: Trying private key: /home/mitchellchu/.ssh/id_ecdsa debug1: Next authentication method: password
И результат выполнения той же команды test на Debian:
OpenSSH_6.0p1 Debian-4, OpenSSL 1.0.1e 11 Feb 2013 ...Some sensitive information... debug1: Remote protocol version 2.0, remote software version OpenSSH_6.0p1 Debian-4 debug1: match: OpenSSH_6.0p1 Debian-4 pat OpenSSH* debug1: Enabling compatibility mode for protocol 2.0 debug1: Local version string SSH-2.0-OpenSSH_6.0p1 Debian-4 debug1: SSH2_MSG_KEXINIT sent debug1: SSH2_MSG_KEXINIT received debug1: kex: server->client aes128-ctr hmac-md5 none debug1: kex: client->server aes128-ctr hmac-md5 none debug1: sending SSH2_MSG_KEX_ECDH_INIT debug1: expecting SSH2_MSG_KEX_ECDH_REPLY ...Some sensitive information... debug1: ssh_ecdsa_verify: signature correct debug1: SSH2_MSG_NEWKEYS sent debug1: expecting SSH2_MSG_NEWKEYS debug1: SSH2_MSG_NEWKEYS received debug1: Roaming not allowed by server debug1: SSH2_MSG_SERVICE_REQUEST sent debug1: SSH2_MSG_SERVICE_ACCEPT received debug1: Authentications that can continue: publickey,password debug1: Next authentication method: publickey debug1: Trying private key: /home/mitchellchu/.ssh/id_rsa debug1: Trying private key: /home/mitchellchu/.ssh/id_dsa debug1: Trying private key: /home/mitchellchu/.ssh/id_ecdsa debug1: Next authentication method: password
Из вышесказанного видно, что в CentOS система использует publickey, gssapi-keyex, gssapi-with-mic и password для аутентификации (цветная строка выше, строка 23), тогда как в Debian используются только Publickey и password. При подключении к CentOS значительное количество времени тратится на строке 23. Если начать смотреть вниз оттуда, мы ясно увидим следующую информацию:
#下面使用的是GSSAPI-KEYEX来进行验证 debug1: Next authentication method: gssapi-keyex #但是报错:没有可用的Key来交换信息 debug1: No valid Key exchange context #系统接着又使用下一个验证方法:GSSAPI-WITH-MIC debug1: Next authentication method: gssapi-with-mic #但遗憾的是,GSSAPI-WITH-MIC方法也失败。 #原因:不能确定数字主机地址的域 debug1: Unspecified GSS failure. Minor code may provide more information Cannot determine realm for numeric host address debug1: Unspecified GSS failure. Minor code may provide more information Cannot determine realm for numeric host address debug1: Unspecified GSS failure. Minor code may provide more information debug1: Unspecified GSS failure. Minor code may provide more information Cannot determine realm for numeric host address # 在尝试几次后,SSH认证终于放弃了这种验证。进入下一个验证:Publickey debug1: Next authentication method: publickey
Есть ли другие методы, кроме этого? Естественно, есть. CentOS на самом деле уже предоставляет нам решение — отключить аутентификацию GSSAPI при использовании удаленного входа по SSH. Конечно, есть еще один вопрос, который необходимо отметить. Если на вашей машине включен UseDNS, его также нужно отключить. Подробности см. в заключительном объяснении.
Из ошибки видно, что это должно быть связано с доменом хоста — вероятно, не удается подтвердить домен, соответствующий IP, поэтому возникает эта проблема. GSSAPI в основном основан на Kerberos, поэтому для решения этой проблемы системе потребовалось бы настроить Kerberos. Для тех, у кого нет Kerberos, настройка Kerberos только для решения проблемы задержки входа не кажется разумным решением — особенно в продакшн-среде! Минимизация конфигурации для удовлетворения потребностей — правильный подход.
Сначала представим метод обработки GSSAPI
Существует два способа отключения аутентификации GSSAPI: на стороне клиента и на стороне сервера
1. Отключение на клиенте
Это относительно просто и влияет только на одного пользователя клиента. Это можно реализовать следующим способом:
ssh -o GSSAPIAuthentication=no your-server-username@serverIP
Использование вышеуказанного способа для удаленного входа позволяет добиться отключения GSSAPIAuthentication.
Если вам это кажется хлопотным, вы можете напрямую настроить файл вашего ssh-клиента /etc/ssh/ssh_config, чтобы навсегда решить эту проблему:
vi /etc/ssh/ssh_config ### 找到ssh_config文件里面的GSSAPIAuthentication yes这行 ### 修改为GSSAPIAuthentication no ### 保存ssh_config文件并退出
Это изменение затрагивает всех пользователей на этой машине. Если вы не хотите, чтобы влияние было настолько широким, и хотите отключить GSSAPIAuthentication только для конкретного пользователя, то можете найти каталог .ssh в домашнем каталоге этого пользователя, добавить туда файл config и добавить указанную выше строку в этот файл. Если этот файл не существует, вы также можете сделать это напрямую так:
cat >>~/.ssh/config<<EOF GSSAPIAuthentication no EOF
Используйте cat, чтобы напрямую записать ввод в файл. После этого, когда вы используете ssh для подключения к удалённому целевому хосту, аутентификация GSSAPI больше не будет использоваться.
Указанные выше файлы находятся на стороне клиента, а не на стороне сервера. То есть, чтобы изменить этот файл, ваш клиент также должен быть Linux.
Если вы используете клиентский инструмент вроде PuTTY под Windows, не используйте описанный выше метод. С PuTTY вы можете попробовать настроить его перед подключением:
PuTTY Configuration -> Connection -> SSH -> Auth -> GSSAPI -> (снимите галочку) Attempt GSSAPI authentication (SSH-2 only)
Если вы не отключили GSSAPIAuthentication в PuTTY, вы можете щёлкнуть правой кнопкой мыши по окну подключения (или: Ctrl + щёлкнуть правой кнопкой), чтобы просмотреть журнал, и сможете найти записи журнала, в которых PuTTY автоматически пытается установить соединение GSSAPI:
2014-05-18 23:46:54 Using SSPI from SECUR32.DLL 2014-05-18 23:46:54 Attempting GSSAPI authentication 2014-05-18 23:46:54 GSSAPI authentication request refused
Что ж, выше в основном перечислены методы отключения GSSAPIAuthentication на стороне клиента.
Примечание: описанные выше методы относительно универсальны.
2. Если вы уже настроили Kerberos
Тогда вы также можете попробовать следующие решения на стороне клиента, чтобы решить эту проблему:
Добавьте имя хоста удалённого узла в файл hosts вашей локальной машины (в Linux — /etc/hosts, в Windows — системный диск:/Windows/System32/drivers/etc/hosts). Как в Linux, так и в Windows можно добавить следующую строку.
### 注意:下面这样的IP-Addr要替换成你的远程机器的IP地址,HostName,自然是主机名 IP-Addr HostName
После добавления сохраните и выйдите.
Если вы не настроили Kerberos, настройка только файла hosts всё равно не решит проблему. При входе по ssh вы можете увидеть журнал ошибок, похожий на следующий:
debug1: Authentications that can continue: publickey,gssapi-keyex,gssapi-with-mi debug1: Next authentication method: gssapi-keyex debug1: No valid Key exchange context debug1: Next authentication method: gssapi-with-mic debug1: Unspecified GSS failure. Minor code may provide more information Credentials cache file '/tmp/krb5cc_0' not found debug1: Unspecified GSS failure. Minor code may provide more information Credentials cache file '/tmp/krb5cc_0' not found debug1: Unspecified GSS failure. Minor code may provide more information debug1: Unspecified GSS failure. Minor code may provide more information Credentials cache file '/tmp/krb5cc_0' not found debug1: Next authentication method: publickey
Я тоже допустил эту ошибку в начале; на это нужно обратить внимание.
3. Отключите GSSAPIAuthentication на стороне сервера.
Перейдите сразу в /etc/ssh/sshd_config и измените GSSAPIAuthentication yes на no. Также обратите внимание, что, возможно, потребуется изменить UseDNS на UseDNS no (на это нужно обратить внимание, так как значение по умолчанию отличается в зависимости от системы; здесь для примера используется CentOS 6):
sudo vi /etc/ssh/sshd_config ### 普通用户权限不够,需要root权限 ### 找到GSSAPIAuthentication yes,修改为 ### GSSAPIAuthentication no ### 注意,这里你也需要将UseDNS修改为no,CentOS默认是yes,即使这行已被注释,你也需要加上 ### UseDNS no ### 有看到人说UseDNS yes不需要修改为UseDNS no,Mitchell测试下来是需要的。 ### 保存文件,退出
После отключения нам нужно перезапустить службу SSH, чтобы убедиться, что новый конфигурационный файл правильно применён:
service sshd restart
Теперь, когда вы снова входите на этот хост по SSH, разве не чувствуется, что это быстро?
Уф~ Наконец-то закончил этот длинный пост. Действительно, немного сложно возиться со всем этим, пока создаёшь весь этот текст. Однако таким образом проблема была довольно хорошо разобрана. Надеюсь, вы сможете понять статью. Не стесняйтесь обсуждать.
Примечания
1. GSSAPI: Generic Security Services Application Program Interface. Сам GSSAPI — это набор API, стандартизированных IETF. Его наиболее важная и также известная реализация основана на Kerberos. Обычно, когда упоминают GSSAPI, подразумевают реализацию Kerberos.
2. UseDNS: это параметр DNS-поиска на сервере OpenSSH, и он включён по умолчанию. Когда он включён, всякий раз, когда клиент пытается подключиться к серверу OpenSSH, сервер автоматически выполняет обратный DNS-запрос PTR на основе IP клиента (при обратном разрешении IP будут записи), находит имя хоста, соответствующее IP, а затем выполняет прямой DNS-запрос записи A на основе имени хоста клиента. С помощью этого запроса он проверяет, совпадает ли IP с IP подключающегося клиента. Но подавляющее большинство наших машин получают IP-адреса динамически, а значит, этот параметр бесполезен для такой ситуации — даже для обычных серверов со статическим IP, если обратное разрешение IP не настроено, его трудно применить. Если вы попадаете в эти условия, рекомендуется отключить UseDNS, чтобы ускорить аутентификацию при удалённом входе по SSH.
Источник: http://blog.useasp.net/archive/2014/05/19/solved-the-problem-of-ssh-client-such-as-putty-remote-login-linux-very-slowly.aspx