Cada vez que uso PuTTY para iniciar sesión vía SSH en un Linux remoto para administrarlo, el proceso de inicio de sesión remoto es muy lento: después de ingresar el nombre de usuario, hay que esperar unos 30 segundos para que aparezca el indicador de contraseña. Al abordar problemas reales, especialmente cuando se necesita una respuesta rápida, esta situación resulta realmente insoportable.

Pero luego hice pruebas concretas y descubrí que esto no es un problema común en todos los sistemas. Las máquinas con problemas se concentran principalmente en CentOS. En el mismo sistema Debian, el proceso de conexión remota es rápido como el viento, sin la más mínima sensación de retraso o titubeo. ¿Será un problema de CentOS?

诊断并解决 SSH 连接慢的方法

Por curiosidad, revisé las diferencias entre los dos sistemas al usar SSH.

CentOS:

ssh -v ssh_test@192.168.128.137

La información que se muestra al iniciar sesión remota por SSH es la siguiente:

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

Mientras que el resultado de probar con el mismo comando en Debian es:

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

De lo anterior se puede ver que en CentOS el sistema utiliza publickey, gssapi-keyex, gssapi-with-mic y password para la autenticación (la línea marcada en color, línea 23), mientras que Debian usa solo Publickey y password. Al conectar a CentOS, se gasta bastante tiempo en la línea 23. Si empezamos a mirar hacia abajo desde ahí, podemos ver claramente la siguiente información:

#下面使用的是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

¿Existen otros métodos además de este? Por supuesto que los hay. CentOS ya nos ofrece una solución: deshabilitar la autenticación GSSAPI al usar SSH para el inicio de sesión remoto. Eso sí, hay otro problema que no se puede ignorar: si en tu máquina está habilitado UseDNS, también debes desactivarlo; para más detalles, consulta la explicación al final.

A partir del error se puede ver que es un problema relacionado con el dominio del host: probablemente no se puede confirmar el dominio correspondiente a la IP, y por eso aparece este problema. GSSAPI se basa principalmente en Kerberos, por lo que resolver este problema requeriría tener Kerberos configurado en el sistema. Para aquellos que no tienen Kerberos, configurar Kerberos solo para resolver un problema de retraso en el inicio de sesión no parece una decisión sensata, especialmente en entornos de producción. ¡Satisfacer las necesidades con la mínima configuración es lo primordial!

A continuación, primero presento el método para manejar GSSAPI.

Hay dos formas de deshabilitar la autenticación GSSAPI: en el cliente y en el servidor.

1. Deshabilitar en el cliente

Es relativamente simple y solo afecta a un único cliente; se puede implementar con el siguiente método:

ssh -o GSSAPIAuthentication=no your-server-username@serverIP

Con el método anterior para iniciar sesión remota, se puede lograr deshabilitar GSSAPIAuthentication.

Si te parece engorroso, configura directamente el archivo /etc/ssh/ssh_config de tu cliente SSH para resolver este problema de forma permanente:

vi /etc/ssh/ssh_config
### 找到ssh_config文件里面的GSSAPIAuthentication yes这行
### 修改为GSSAPIAuthentication no
### 保存ssh_config文件并退出

Este método de modificación afecta a todos los usuarios de esta máquina. Si no quieres que el impacto sea tan amplio y solo deseas deshabilitar GSSAPIAuthentication para un usuario específico, puedes ir al directorio de ese usuario, buscar el directorio .ssh, añadir un archivo config debajo y agregar la línea anterior en el archivo. Si el archivo no existe, también puedes hacerlo directamente:

cat >>~/.ssh/config<<EOF
GSSAPIAuthentication no
EOF

Usa cat para exportar la entrada directamente al archivo. En ese momento, cuando uses SSH para conectarte al host remoto, ya no usarás la autenticación GSSAPI.

Los archivos anteriores están en el cliente, no en el servidor. Es decir, para modificar este archivo, tu cliente también debe ser Linux.

Si estás en Windows y usas herramientas de cliente como PuTTY, no uses el método anterior. En PuTTY puedes intentar configurarlo antes de la conexión:

PuTTY Configuration -> Connection -> SSH -> Auth -> GSSAPI -> (desmarcar)Attempt GSSAPI authentication(SSH-2 only)

Si no has deshabilitado GSSAPIAuthentication en PuTTY, puedes hacer clic derecho en la ventana de conexión (o Ctrl + clic derecho) para ver el registro. Podrás encontrar registros en los que PuTTY intenta automáticamente una conexión 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

Bueno, lo anterior básicamente enumera los métodos para deshabilitar GSSAPIAuthentication en el cliente.

Nota: los métodos anteriores son bastante generales.

2. Si ya has configurado Kerberos

Entonces también puedes probar el siguiente método para resolver este problema en el cliente:

Agrega el nombre de host del host remoto al archivo hosts de tu máquina local (en Linux es /etc/hosts, en Windows es disco del sistema:/Windows/System32/drivers/etc/hosts). Tanto en Linux como en Windows puedes agregar la siguiente línea.

### 注意:下面这样的IP-Addr要替换成你的远程机器的IP地址,HostName,自然是主机名
IP-Addr HostName

Después de añadirlo, guarda y sal.

Si no has configurado Kerberos, solo configurar el archivo hosts tampoco resolverá el problema. Al usar SSH para iniciar sesión, verás que el registro de errores es similar al siguiente:

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

Este error yo también lo cometí al principio; hay que tener cuidado.

3. Deshabilitar GSSAPIAuthentication en el servidor.

Ve directamente a /etc/ssh/sshd_config y cambia GSSAPIAuthentication yes a no. También ten en cuenta que quizás debas cambiar UseDNS a UseDNS no (ojo, el valor predeterminado varía según el sistema; aquí se usa CentOS 6 como ejemplo):

sudo vi /etc/ssh/sshd_config
### 普通用户权限不够,需要root权限
### 找到GSSAPIAuthentication yes,修改为
### GSSAPIAuthentication no
### 注意,这里你也需要将UseDNS修改为no,CentOS默认是yes,即使这行已被注释,你也需要加上
### UseDNS no
### 有看到人说UseDNS yes不需要修改为UseDNS no,Mitchell测试下来是需要的。
### 保存文件,退出

Una vez deshabilitado, debemos reiniciar el servicio SSH para garantizar que el nuevo archivo de configuración se aplique correctamente:

service sshd restart

En este momento, al usar SSH para iniciar sesión nuevamente en este host, ¿no sientes que es rapidísimo?

Uf... ¡Por fin terminé este artículo largo! Fue bastante difícil escribir este texto mientras trasteaba. Sin embargo, con esto ya he resuelto bastante el problema. Espero que quien lea el artículo pueda entenderlo. Bienvenidos a debatir.

Descripción

1. GSSAPI: Generic Security Services Application Program Interface. GSSAPI en sí es un conjunto de APIs, estandarizado por la IETF. Su implementación más importante y famosa se basa en Kerberos. Generalmente, cuando se menciona GSSAPI, se hace referencia implícita a la implementación de Kerberos.

2. UseDNS: es una opción de búsqueda DNS en el servidor OpenSSH, y está activada por defecto. Cuando está activada, cada vez que un cliente intenta conectarse al servidor OpenSSH, el servidor realiza automáticamente una búsqueda inversa PTR de DNS según la IP del cliente (solo habrá registro si se ha hecho la resolución inversa de IP), obtiene el Hostname correspondiente a la IP y luego realiza una búsqueda directa de registro A de DNS según el Hostname del cliente. Mediante esta consulta, verifica si la IP coincide con la IP del cliente conectado. Pero en la gran mayoría de nuestros equipos la IP se obtiene dinámicamente, es decir, esta opción no sirve en absoluto para este caso. Incluso para servidores con IP estática normal, mientras no se haya realizado la resolución inversa de IP, difícilmente es aplicable. Si cumples estas condiciones, se recomienda desactivar UseDNS para aumentar la velocidad de autenticación al iniciar sesión remota por SSH.

Fuente: http://blog.useasp.net/archive/2014/05/19/solved-the-problem-of-ssh-client-such-as-putty-remote-login-linux-very-slowly.aspx