为什么我的SSH连接这么慢?五个立竿见影的延迟修复方法
诊断并消除Secure Shell(SSH)连接中令人沮丧的延迟。本指南详细介绍了五种即时配置修复方法——包括禁用DNS查找和GSSAPI认证——以恢复快速的终端响应时间。学习优化加密算法和利用连接复用的实用步骤,提升远程工作效率。
为什么我的SSH连接这么慢?五个立竿见影的延迟修复方法
SSH缓慢并非单一问题。有时延迟发生在你甚至看到提示符之前。有时登录很快,但每次按键都感觉粘滞。有时SSH被归咎于缓慢的shell启动脚本、阻塞的DNS查找,或者网络路径在你的笔记本电脑和地球另一端云区域之间丢包。
在更改设置之前,先运行一个简单测试:
time ssh -vvv [email protected] exit
time输出告诉你整个连接是否缓慢。-vvv输出告诉你客户端在哪里花费时间。寻找重复的密钥尝试、GSSAPI消息、DNS相关的暂停,或认证开始前的长时间间隔。如果ssh user@host exit很快但交互式登录很慢,问题可能出在远程shell启动文件中,而不是SSH本身。
有三种常见模式:
- 认证前缓慢: 通常是DNS、GSSAPI、主机密钥查找或缓慢的认证后端。
- 认证后但提示符前缓慢: 通常是
.bashrc、.profile、.zshrc、网络挂载的家目录或shell插件。 - 打字或使用全屏工具时缓慢: 通常是真实网络延迟、丢包、端点过载、压缩开销或终端渲染。
下面的修复方法按解决实际SSH延迟投诉的频率排序。
1. 在服务器上禁用反向DNS查找
反向DNS是内部网络上SSH登录缓慢的经典原因。服务器接受你的TCP连接,然后尝试将连接客户端的IP地址解析回主机名。如果反向DNS缺失、配置错误或由慢速解析器处理,登录可能会暂停几秒钟。
这是一个服务器端设置。在/etc/ssh/sshd_config中添加或更新此行:
UseDNS no
然后测试并重新加载SSH:
sudo sshd -t
sudo systemctl reload sshd
某些发行版使用ssh作为服务名称:
sudo systemctl reload ssh
在测试新登录时保持现有会话打开。如果新登录很快,你就找到了延迟原因。如果没有变化,如果设置符合你的环境,就保留它,但继续排查。
2. 在不使用Kerberos时禁用GSSAPI
GSSAPI在Kerberos支持的环境中很有用。在这些环境之外,它可能会增加一次不必要的认证尝试。症状通常是在连接建立期间出现暂停,然后才继续公钥认证。
在你的本地~/.ssh/config中设置:
Host *
GSSAPIAuthentication no
如果你只在某个服务器上看到延迟,将该设置限定到该主机:
Host legacy-admin
HostName legacy-admin.example.com
User admin
GSSAPIAuthentication no
运行ssh -vvv legacy-admin并比较前后结果。你应该看到客户端跳过GSSAPI,直接进入公钥或密码认证。
3. 停止提供错误的密钥
如果你的SSH代理保存了一堆密钥,你的客户端可能会提供多个身份,直到它到达服务器接受的那个。这比需要的要慢,而且一些服务器在太多失败尝试后会拒绝登录。
详细输出使这一点很明显:
debug1: Offering public key: /Users/me/.ssh/id_personal
debug1: Authentications that can continue: publickey
debug1: Offering public key: /Users/me/.ssh/id_old_vendor
debug1: Authentications that can continue: publickey
debug1: Offering public key: /Users/me/.ssh/id_prod
固定正确的身份:
Host prod-api
HostName 203.0.113.20
User deploy
IdentityFile ~/.ssh/id_ed25519_prod
IdentitiesOnly yes
IdentitiesOnly yes很重要。没有它,客户端可能仍然会在配置的文件之前或同时提供代理密钥。
你也可以检查代理加载了什么:
ssh-add -l
如果列表很乱,从代理中删除旧密钥,只添加当前工作需要的密钥:
ssh-add -D
ssh-add ~/.ssh/id_ed25519_prod
4. 仅在有用时使用压缩
压缩不是通用的速度开关。当链路带宽受限且数据可压缩时,例如通过慢速VPN传输长文本日志,它可能有帮助。在快速网络上它可能有害,因为双方都要花费CPU压缩和解压缩本可以快速通过线路传输的数据。
窄范围使用它:
Host distant-bastion
HostName bastion.example.net
User ops
Compression yes
除非你测量过它对你的日常连接有帮助,否则不要全局启用它。对于普通的云到笔记本电脑SSH,默认设置通常更好。
如果打字慢,压缩很少是首选修复方法。测试网络路径:
ping server.example.com
mtr server.example.com
如果你看到高延迟或丢包,SSH配置只能做这么多。通过更近的堡垒机移动,修复VPN路径,或使用离操作员更近的区域。
5. 使用多路复用重用连接
如果第一次SSH连接需要几秒钟,但每个新的终端标签页都重复这个成本,连接多路复用是一个干净的修复方法。SSH保持一个控制连接打开,并为后续到同一用户、主机和端口的会话重用。
添加到~/.ssh/config:
Host *
ControlMaster auto
ControlPath ~/.ssh/controlmasters/%r@%h:%p
ControlPersist 10m
创建套接字目录:
mkdir -p ~/.ssh/controlmasters
chmod 700 ~/.ssh/controlmasters
第一次连接仍然支付正常的握手和认证成本。下一次应该感觉几乎是即时的。
如果多路复用连接在网络更改后卡住,关闭主套接字:
ssh -O exit [email protected]
或者从~/.ssh/controlmasters中删除匹配的套接字。
在责怪SSH之前检查Shell启动
这一点很容易被忽略。SSH可能快速认证,然后你的shell启动文件在提示符出现前消耗几秒钟。
比较这些:
time ssh [email protected] true
time ssh [email protected] 'bash --noprofile --norc -i -c exit'
然后检查.bashrc、.bash_profile、.profile、.zshrc以及它们引用的任何文件。常见的减速包括:在大型目录中运行Git命令的提示主题、查询远程API的kubectl或云CLI补全、包管理器初始化、阻塞的NFS家目录,以及登录时调用内部服务的脚本。
最快的SSH修复是与你实际看到的暂停相匹配的那个。使用-vvv,一次更改一个设置,并从第二个终端测试,同时保持当前会话打开。