华为云ECS上SSH登录缓慢排查:从握手延迟、UseDNS到主机名与MOTD
SSH 能连上,但从敲下命令到出现密码提示或进入 shell,经常要等十几秒甚至半分钟,这和“端口不通、直接被拒绝”不是一类问题。后者多半是安全组、系统防火墙或 sshd 没有在监听;前者说明 TCP 已经建立,卡顿发生在协议握手、身份认证或登录后会话初始化。下面以华为云 ECS 上常见的 Linux 镜像(Huawei Cloud EulerOS、CentOS、Ubuntu)为例,按“先分清卡在哪一段,再对症改配置”的顺序排查。文中的地址和主机名都是占位符,请换成实际值。
一、现象与排查边界
典型现象包括:
- 客户端长时间停在“正在连接”,随后才出现密码或口令提示;
- 公钥认证其实已经成功,但要再等很久才出现命令行提示符;
- 同一台 ECS,用弹性公网 IP 访问很慢,在同一 VPC 内用私网 IP 却很快,或正好相反;
- 用云服务器控制台的远程登录(VNC)进系统是正常的,说明机器本身能用,问题出在 SSH 路径上。
先排除几件容易混淆的事:安全组或防火墙把 22 端口丢掉时,通常是超时失败或立即拒绝,而不是“等很久再成功”。负载很高、磁盘打满、sshd 进程异常,也可能让握手变慢,需要一并看一眼,但不要一上来就重启 sshd 或修改一堆参数。
二、先分清延迟发生在哪一段
在自己的电脑上对目标 ECS 做一次带时间戳的详细调试(把用户名和 IP 换成实际值):
ssh -vvv -o ConnectTimeout=15 user@SERVER_IP true 2>&1 | while IFS= read -r line; do
printf '%s %s\n' "$(date '+%H:%M:%S')" "$line"
done
也可以先看总耗时:
time ssh -o ConnectTimeout=15 user@SERVER_IP true
对照调试输出里相邻两行的时间差,把问题归到下面三类之一。
1. 卡在 Connection established 之前
还在解析主机名或建立 TCP。常见原因是客户端把域名解析到了不可达的 IPv6 地址,等超时后再回退到 IPv4。可以先强制走 IPv4 对比:
time ssh -4 -o ConnectTimeout=15 user@SERVER_IP true
如果 -4 明显变快,再检查本机和目标主机名的 A/AAAA 记录,以及客户端 ~/.ssh/config 是否需要加上 AddressFamily inet。不要先改服务器。
2. 已经 Connection established,但迟迟看不到协议版本或认证方法列表
TCP 已通,卡在 sshd 接受连接之后、开始认证之前。这一段最常见的是服务端做客户端地址的反向域名解析(UseDNS),或尝试 GSSAPI/Kerberos 相关处理。后面第三节会展开。
3. 已经出现 Accepted 或 Authentication succeeded,之后才长时间停顿
认证已经完成,慢的是 PAM、登录脚本或 Ubuntu 的动态 MOTD。这类问题和 UseDNS 无关,不要只改 sshd 的 DNS 选项。
在 ECS 上查看 sshd 的有效配置(只读,不会重启服务):
sudo sshd -T | grep -Ei 'usedns|gssapiauthentication|usepam|printmotd|logingracetime|maxstartups'
不同镜像的默认值并不统一:OpenSSH 上游的 UseDNS 早已默认是 no,但部分基于较老发行版的镜像仍可能在配置文件里写成 yes;GSSAPIAuthentication 在部分 RHEL 系默认配置里是 yes。所以不要凭发行版“印象”判断,以 sshd -T 的输出为准。Ubuntu 上服务单元名一般是 ssh,EulerOS / CentOS 上一般是 sshd,配置文件都是 /etc/ssh/sshd_config。
同时看登录时段的服务日志:
# EulerOS / CentOS
sudo journalctl -u sshd --since "1 hour ago"
sudo tail -n 100 /var/log/secure
# Ubuntu
sudo journalctl -u ssh --since "1 hour ago"
sudo tail -n 100 /var/log/auth.log
如果日志里 Connection from 与 Accepted 之间隔了十几秒,优先查 DNS 和 GSSAPI;如果 Accepted 之后很久才有会话建立的记录,再查 PAM 和 MOTD。
三、查 DNS、主机名和 GSSAPI
UseDNS yes 时,sshd 会对客户端 IP 做反向解析,再做一次正向校验。客户端的公网地址往往没有可用的 PTR,或者 ECS 的 DNS 服务器响应很慢,解析就会一直等到超时。表现就是连接已经建立,密码提示却迟迟不出现。
先看解析是否本身就慢。下面两条命令在正常环境里通常会在 1 秒内返回;如果要等 5 秒、10 秒才出结果,SSH 登录也很难快:
hostname
cat /etc/resolv.conf
time getent hosts "$(hostname)"
time getent hosts example.com
常见的两个坑:
/etc/hostname里是实例名(例如ecs-web-01),但/etc/hosts只有127.0.0.1 localhost,没有把主机名指到本机地址。此时getent hosts "$(hostname)"会去问 DNS,DNS 再超时。/etc/resolv.conf里的 nameserver 不可达。有的环境收紧了安全组或网络 ACL 的出站规则,漏放了 DNS 常用的 UDP/TCP 53,所有名称解析都会卡住。华为云安全组默认出站一般是放行的,如果后来改成了细粒度出站,需要确认 53 端口没有被误关。不要编造或写死某个区域的内网 DNS 地址,以 VPC 子网和网卡上实际下发的配置为准。
把主机名写进 /etc/hosts 是成本很低的一步(先备份,再按实际私网 IP 和主机名修改):
sudo cp -a /etc/hosts /etc/hosts.bak
# 示例,请替换为实际私网 IP 与主机名
# 10.0.0.12 ecs-web-01
再用 time getent hosts "$(hostname)" 确认是立刻返回,而不是走超时。
GSSAPI 的判断可以看客户端调试日志里是否长时间停在 gssapi-with-mic 或 gssapi-keyex。如果这台 ECS 并没有接入 Kerberos 或域认证,服务端可以把 GSSAPIAuthentication 设为 no。客户端也可以先临时绕过,用来确认是不是这条路径在耗时:
time ssh -o GSSAPIAuthentication=no -o PreferredAuthentications=publickey,password user@SERVER_IP true
四、认证成功之后仍然很慢:PAM 与 MOTD
Ubuntu 镜像上很常见的情况是:认证很快,进入 shell 却要再等十几秒。原因是登录时执行了 /etc/update-motd.d/ 下的脚本,例如检查软件更新的脚本会访问外部软件源,网络稍差就会把登录拖慢。
ls -l /etc/update-motd.d/
可先观察是哪一条脚本慢(不要先批量删除):
sudo run-parts --lsbsysinit /etc/update-motd.d/
确认某条脚本(例如检查更新的那一条)耗时过长后,再取消它的可执行权限,或在维护窗口按发行版文档调整 MOTD,而不是直接清空整个目录。注意:Ubuntu 的动态 MOTD 由 /etc/pam.d/sshd 中的 pam_motd 模块触发,只把 sshd_config 里的 PrintMotd 设为 no 并不能阻止这些脚本执行;如确需整体关闭,应在备份后注释对应的 pam_motd 行,这只影响登录公告,不影响认证。
EulerOS / CentOS 上如果慢在 Accepted 之后,还要看 /etc/profile、~/.bashrc 以及 PAM 配置里是否调用了会访问网络的模块。改 PAM 前必须备份,配错可能导致无法再 SSH 登录;若已无法登入,可通过 ECS 控制台的远程登录(VNC)进入系统回退。
五、根因归纳与处理原则
把前面的证据对上号,根因通常是下面几类之一,而且可以同时存在:
- 客户端先走不通的 IPv6,再回退 IPv4;
- sshd 开启了
UseDNS,反向解析超时; - GSSAPI 认证开启,但环境里并没有可用的票据或 KDC,只能等到超时;
- 主机名未写入
/etc/hosts,或 ECS 出站 DNS 不通,导致登录过程中的名称解析阻塞; - 登录后的 MOTD、profile 或 PAM 访问了外部网络。
修改 sshd 配置时,先备份,再语法检查,再 reload,避免重启中断已有会话:
sudo cp -a /etc/ssh/sshd_config /etc/ssh/sshd_config.bak.$(date +%F)
# 按需在配置中设置,例如:
# UseDNS no
# GSSAPIAuthentication no
sudo sshd -t && sudo systemctl reload sshd
# Ubuntu 则通常是:sudo systemctl reload ssh
sshd -t 失败时不要 reload。改完后再用原来的 time ssh ... true 对比耗时,并确认仍能用密钥或密码登录,避免只优化了速度却把认证方式改坏。
六、预防建议
- 制作私有镜像或写 cloud-init 时,把主机名和私网 IP 写入
/etc/hosts,并用sshd -T确认UseDNS、GSSAPIAuthentication符合实际用途。没有域环境就不要打开 GSSAPI。 - 收紧安全组出站规则时,为 DNS 预留必要的放行,并在变更后用
getent hosts做一次计时检查。 - 对 Ubuntu 类镜像,提前审视
update-motd.d里会访问外网的脚本,避免把软件源检查放在每次 SSH 登录的关键路径上。 - 在客户端配置里对管理用的 ECS 固定
AddressFamily inet(仅在不需要 IPv6 时)和GSSAPIAuthentication no,减少每台机器上重复踩坑。 - 变更 sshd 或 PAM 前保留控制台 VNC 登录手段,并先在测试实例验证。
七、总结
SSH 登录慢,优先用带时间戳的 ssh -vvv 把延迟切成“连上之前、认证之前、认证之后”三段,再分别查 IPv6 回退、UseDNS/DNS 超时、GSSAPI,以及 MOTD 或登录脚本。sshd -T、getent hosts 和 journald / 安全日志能提供直接证据,不必先重启服务或放大一堆参数。处理时坚持备份、语法检查和 reload,并用控制台远程登录留好退路。这样排下来,大多数“明明能连上,却要等十几秒”的问题都可以定位到具体的一条配置或一次超时的解析,而不是停留在“网络不好”这种无法验证的判断上。
- 点赞
- 收藏
- 关注作者
评论(0)