Jedes Mal, wenn ich PuTTY verwende, um mich per SSH an einem entfernten Linux-System zur Verwaltung anzumelden, ist der Remote-Anmeldevorgang sehr langsam – nach Eingabe des Benutzernamens muss ich etwa 30 Sekunden warten, bevor die Passwortaufforderung erscheint. Wenn ich tatsächlich Probleme bearbeite, insbesondere wenn eine schnelle Reaktion erforderlich ist, ist dieser Zustand wirklich unerträglich.

Doch später, nachdem ich es gezielt getestet hatte, stellte ich fest, dass dies kein allgemeines Problem in jedem System ist. Die betroffenen Maschinen konzentrieren sich hauptsächlich auf CentOS. Beim gleichen Debian-System ist der Remote-Verbindungsprozess schnell wie im Flug, ohne Zögern oder Verzögerung. Könnte das ein CentOS-Problem sein?

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

Aus Neugier sah ich mir die Unterschiede zwischen den beiden Systemen bei der Verwendung von SSH an

CentOS:

ssh -v ssh_test@192.168.128.137

Die bei der SSH-Remote-Anmeldung angezeigten Informationen lauten wie folgt:

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

Und das Ergebnis der Ausführung desselben Befehlstests auf Debian ist:

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

Aus dem Obigen ist ersichtlich, dass das System unter CentOS publickey, gssapi-keyex, gssapi-with-mic und password zur Authentifizierung verwendet (die farbige Zeile oben, Zeile 23), während Debian nur Publickey und password verwendet. Beim Verbinden mit CentOS wird an Zeile 23 beträchtlich viel Zeit verbraucht. Wenn wir von dort aus nach unten schauen, können wir die folgenden Informationen deutlich sehen:

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

Gibt es außer dieser noch andere Methoden? Natürlich gibt es sie. CentOS bietet uns tatsächlich bereits eine Lösung – deaktivieren Sie die GSSAPI-Authentifizierung bei der SSH-Remote-Anmeldung. Natürlich gibt es noch ein weiteres Problem, das beachtet werden muss. Wenn UseDNS auf Ihrem Rechner aktiviert ist, müssen Sie es ebenfalls deaktivieren. Einzelheiten finden Sie in der abschließenden Erklärung.

Aus dem Fehler ist ersichtlich, dass es mit der Host-Domain zusammenhängen sollte – wahrscheinlich kann die der IP entsprechende Domain nicht bestätigt werden, daher tritt dieses Problem auf. GSSAPI basiert hauptsächlich auf Kerberos, um dieses Problem zu lösen, müsste das System also Kerberos konfiguriert haben. Für diejenigen, die kein Kerberos haben, scheint es keine kluge Entscheidung zu sein, Kerberos nur zur Lösung eines Anmeldeverzögerungsproblems zu konfigurieren – besonders in einer Produktionsumgebung! Konfiguration zu minimieren, um Anforderungen zu erfüllen, ist der richtige Ansatz.

Zunächst stellen wir die Methode zur Behandlung von GSSAPI vor

Es gibt zwei Möglichkeiten, die GSSAPI-Authentifizierung zu deaktivieren: clientseitig und serverseitig

1. Auf dem Client deaktivieren

Es ist relativ einfach und betrifft nur einen einzelnen Client-Benutzer. Es kann mit der folgenden Methode umgesetzt werden:

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

Durch die Verwendung der obigen Methode zur Remote-Anmeldung kann GSSAPIAuthentication deaktiviert werden.

Wenn Sie es lästig finden, können Sie direkt Ihre ssh-Clientdatei /etc/ssh/ssh_config konfigurieren, um dieses Problem dauerhaft zu lösen:

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

Diese Änderung betrifft alle Benutzer auf dieser Maschine. Wenn Sie nicht möchten, dass die Auswirkung so weitreichend ist, und GSSAPIAuthentication nur für einen bestimmten Benutzer deaktivieren möchten, können Sie das Verzeichnis .ssh im Home-Verzeichnis dieses Benutzers finden, dort eine Konfigurationsdatei hinzufügen und die obige Zeile in die Datei einfügen. Wenn diese Datei nicht existiert, können Sie es auch direkt so machen:

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

Verwenden Sie cat, um die Eingabe direkt in die Datei zu schreiben. An diesem Punkt wird GSSAPI-Authentifizierung nicht mehr verwendet, wenn Sie ssh verwenden, um eine Verbindung zum entfernten Zielhost herzustellen.

Die oben genannten Dateien befinden sich auf der Client-Seite, nicht auf der Server-Seite. Das heißt, um diese Datei zu ändern, muss Ihr Client ebenfalls Linux sein.

Wenn Sie ein Client-Tool wie PuTTY unter Windows verwenden, verwenden Sie nicht die obige Methode. Mit PuTTY können Sie versuchen, es vor dem Verbinden zu konfigurieren:

PuTTY-Konfiguration -> Verbindung -> SSH -> Auth -> GSSAPI -> (Häkchen entfernen) GSSAPI-Authentifizierung versuchen (nur SSH-2)

Wenn Sie PuTTYs GSSAPIAuthentication nicht deaktiviert haben, können Sie mit der rechten Maustaste auf das Verbindungsfenster klicken (oder: Strg + Rechtsklick), um das Protokoll anzuzeigen, und Sie können Protokolleinträge finden, in denen PuTTY automatisch eine GSSAPI-Verbindung versucht:

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

Nun, das Obige listet im Wesentlichen die Methoden zum Deaktivieren von GSSAPIAuthentication auf der Client-Seite auf.

Hinweis: Die oben genannten Methoden sind relativ universell.

2. Wenn Sie Kerberos bereits konfiguriert haben

Dann können Sie auch die folgenden clientseitigen Lösungen ausprobieren, um dieses Problem zu lösen:

Fügen Sie den Hostnamen des entfernten Hosts zur hosts-Datei Ihres lokalen Rechners hinzu (unter Linux /etc/hosts, unter Windows Systemlaufwerk:/Windows/System32/drivers/etc/hosts). Sowohl unter Linux als auch unter Windows können Sie die folgende Zeile hinzufügen.

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

Nachdem Sie sie hinzugefügt haben, speichern und beenden Sie.

Wenn Sie Kerberos nicht konfiguriert haben, wird die alleinige Konfiguration der hosts-Datei das Problem trotzdem nicht lösen. Bei der Anmeldung per ssh sehen Sie ein Fehlerprotokoll ähnlich dem folgenden:

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

Diesen Fehler habe ich am Anfang auch gemacht; darauf sollte man achten.

3. GSSAPIAuthentication auf der Serverseite deaktivieren.

Gehen Sie direkt zu /etc/ssh/sshd_config und ändern Sie GSSAPIAuthentication yes zu no. Beachten Sie außerdem, dass Sie möglicherweise auch UseDNS zu UseDNS no ändern müssen (dies ist zu beachten, da der Standardwert je nach System unterschiedlich ist; hier wird CentOS 6 als Beispiel verwendet):

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

Nach der Deaktivierung müssen wir den SSH-Dienst neu starten, um sicherzustellen, dass die neue Konfigurationsdatei korrekt angewendet wird:

service sshd restart

Wenn Sie sich nun wieder per SSH bei diesem Host anmelden, fühlt es sich nicht schnell an?

Puh~ Endlich ist dieser lange Beitrag fertig. Es ist tatsächlich etwas schwierig, herumzubasteln, während man all diesen Text produziert. Auf diese Weise wurde das Problem jedoch ziemlich gut gelöst. Ich hoffe, Sie können den Artikel verstehen. Diskutieren Sie gerne.

Hinweise

1. GSSAPI: Generic Security Services Application Program Interface. GSSAPI selbst ist eine Reihe von APIs, die von der IETF standardisiert wurden. Die wichtigste und auch bekannteste Implementierung basiert auf Kerberos. Im Allgemeinen ist mit der Erwähnung von GSSAPI die Kerberos-Implementierung gemeint.

2. UseDNS: Dies ist eine DNS-Lookup-Option auf dem OpenSSH-Server und standardmäßig aktiviert. Wenn sie aktiviert ist, führt der Server bei jedem Verbindungsversuch eines Clients mit dem OpenSSH-Server automatisch eine DNS-PTR-Reverse-Lookup anhand der IP des Clients durch (die IP-Reverse-Auflösung wird Einträge haben), ermittelt den der IP entsprechenden Hostnamen und führt dann eine DNS-Forward-A-Record-Abfrage anhand des Hostnamens des Clients durch. Durch diese Abfrage wird überprüft, ob die IP mit der IP des sich verbindenden Clients übereinstimmt. Aber die überwiegende Mehrheit unserer Maschinen bezieht IP-Adressen dynamisch, was bedeutet, dass diese Option für diese Situation nutzlos ist – selbst für gewöhnliche Server mit statischer IP ist sie kaum anwendbar, solange keine IP-Reverse-Auflösung durchgeführt wird. Wenn diese Bedingungen auf Sie zutreffen, wird empfohlen, UseDNS zu deaktivieren, um die Authentifizierung bei der SSH-Remote-Anmeldung zu beschleunigen.

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