SSH 登录前要卡 30 秒:一次 sshd 反向 DNS 排查复盘

ssh 登录新服务器,回车后要卡将近 30 秒密码提示符才出现,登录进去操作却飞快。排查梳理:只卡登录那一下、进去就快基本能排除网络通道慢,是 sshd 在你输密码前做的预处理卡住了;sshd 默认开着 UseDNS 会对客户端 IP 做反向 DNS 查询,DNS 不通就干等超时,sshd_config 里 UseDNS 那行被注释掉默认值仍是 yes;GSSAPIAuthentication 默认也开着没 Kerberos 环境会拖慢登录;用 time ssh 确认慢在握手、ssh -v 看卡在哪一步;改 sshd_config 先 sshd -t 校验语法再 reload、重启不踢已有会话但要留旧会话另开窗口验证,以及一套 SSH 登录排查纪律。

2024 年,公司上了一批新服务器,我去逐台做初始化。第一台 ssh 上去,我敲完 ssh root@新机器 IP 回车,屏幕就停在那里——光标一闪一闪,什么都没有。我以为是网络抽风,正想 Ctrl+C 重来,大概卡了快半分钟,密码提示符 password: 才慢悠悠地冒出来。输完密码,登录进去,机器里面快得飞起,lstop 毫无延迟。我换了台机器,一模一样:登录前先卡将近 30 秒,登录后顺滑无比。我第一反应是网络问题,换了家里的网、换了手机热点、又换了另一个机房的跳板机,卡顿分毫不差,稳定地卡 30 秒。这就怪了:如果是网络慢,登录进去之后也该慢;可它偏偏只在"登录那一下"卡,进去就好。一个只在登录瞬间出现、登录后就消失的卡顿,到底卡在哪?我盯着这个现象想了很久,最后意识到我把问题方向想反了——我一直以为是"我连不上去"的网络问题,可真相是,在我输密码之前,服务器上的 sshd 正背着我,偷偷做一件又慢又没必要的事。这件事逼着我把 SSH 登录的握手过程、sshd 的反向 DNS 查询、GSSAPI 认证这一整套彻底理清了。本文复盘这次实战。

问题背景

环境:一批新装的 CentOS 7 云服务器
事故现象:
- ssh 登录,回车后要卡将近 30 秒,密码提示符才出现
- ★ 登录进去之后,机器操作飞快,毫无延迟
- 换网络、换客户端,卡顿稳定复现,都是 30 秒左右

现场排查:
# 1. 卡的是"出密码提示符之前"这一段
$ time ssh root@新机器 'echo ok'
(这里卡了 ~28 秒)
ok
real    0m28.6s                          # ★ 实际操作 echo 一瞬间,慢在握手

# 2. ★ 用 ssh -v 看握手到底卡在哪一步
$ ssh -v root@新机器
...
debug1: SSH2_MSG_SERVICE_ACCEPT received
(★ 卡在这里 ~28 秒)
debug1: Authentications that can continue: publickey,password

# 3. ★ 卡顿期间,去服务器上看 sshd 在干嘛(从另一条已登录会话)
$ 在服务器上:看 sshd 进程
# sshd 在等一个 DNS 查询返回 —— 反向解析客户端 IP

# 4. ★ 看 sshd 配置
$ grep -Ei 'usedns|gssapi' /etc/ssh/sshd_config
#UseDNS yes                              # ★ 注释着,但默认值就是 yes
GSSAPIAuthentication yes                 # ★ 也开着

根因(后来想清楚的):
1. ★ ssh 登录卡顿,卡的不是"网络通不通",是
   sshd 在【正式让你输密码之前】,做的一些预处理动作。
2. sshd 默认开着 UseDNS:你一连上来,它会拿你的
   客户端 IP,去做一次【反向 DNS 查询】(IP -> 域名)。
3. ★ 这批新服务器的 DNS 配置有问题 / DNS 不通,
   这个反向查询【查不到、也不报错,就一直等超时】——
   超时大概就是那 ~28 秒。
4. GSSAPIAuthentication 也开着,某些环境下它也会
   引入额外的握手延迟。
5. ★ 这两件事都发生在"输密码之前",所以卡的是登录;
   一旦登录成功,这些预处理早做完了,操作自然飞快。
登录卡顿别只怪网络,先怀疑 sshd 登录前的 DNS 反查。

修复 1:登录卡顿不是网络慢——是 sshd 登录前的预处理

# === ★ 先纠正方向:卡顿分两种,位置完全不同 ===

# === 卡法 A:网络本身慢 ===
# 如果是网络通道慢(丢包、带宽小、绕路),
#   那【登录前和登录后】应该【一样慢】——
#   你 ls 一下、敲个命令,都该有延迟。

# === ★ 卡法 B:只卡"登录那一下",进去就好 ===
# 这正是我这次的情况:卡 30 秒在密码提示符之前,
#   进去之后操作毫无延迟。
# ★ 这种"只卡登录瞬间"的模式,几乎可以排除网络通道问题——
#   网络慢不会"只慢一下下就恢复"。
# 真凶,是 sshd 在【让你输密码之前】做的某些预处理动作。

# === sshd 在你输密码前,到底做了哪些事 ===
# 你 ssh 连上来,在弹出 password: 之前,sshd 会:
#  1. 完成 SSH 协议握手、密钥交换
#  2. ★ 拿你的客户端 IP 做反向 DNS 查询(UseDNS)
#  3. ★ 尝试 GSSAPI 等认证方式的协商
#  4. 读取 /etc/hosts.allow、/etc/hosts.deny 等
# ★ 这里面第 2、3 步,都【可能因为外部依赖不通而卡住】。

# === ★ 用 time 量一下,卡顿到底在不在握手阶段 ===
$ time ssh root@主机 'echo ok'
# echo ok 本身是一瞬间的事。
# ★ 如果 real 时间很长(几十秒),而命令本身极快,
#   那这几十秒,全花在了"连接 + 握手 + 预处理"上,
#   而不是花在执行命令、也不是网络传输上。

# === 一句话抓住本质 ===
# 登录后也慢 -> 查网络通道。
# ★ 只有登录那一下慢 -> 查 sshd 登录前的预处理(DNS / GSSAPI)。

修复 2:UseDNS——sshd 对你的 IP 做反向 DNS 查询

# === ★ 头号嫌疑:sshd 的 UseDNS ===

# === UseDNS 是什么 ===
# sshd 有个选项叫 UseDNS。开启时(老版本默认就是开的),
#   每当有客户端连上来,sshd 会:
#  1. 拿客户端的 IP,做一次【反向 DNS 查询】:IP -> 主机名
#  2. 再拿查到的主机名,做一次【正向查询】:主机名 -> IP
#  3. 核对正反查到的 IP 是否一致(一种校验)。
# ★ 这一切,都发生在你看到 password: 提示符【之前】。

# === ★ 为什么它会卡 30 秒 ===
# 如果这台服务器的 DNS 是【不通的 / 配错的】:
#  - 那个反向查询发出去,【没有响应】
#  - sshd 不会立刻放弃,它会【傻等,直到 DNS 查询超时】
#  - DNS 解析的超时,叠加重试,往往就是几十秒
# ★ 这几十秒的"干等 DNS 超时",就是登录卡顿的真身。

# === 看 sshd 当前 UseDNS 是什么 ===
$ grep -i usedns /etc/ssh/sshd_config
#UseDNS yes
# ★ 注意:就算这行是注释掉的,很多版本的 sshd
#   【默认值仍然是 yes】—— 不写 = 开着。别被注释骗了。

# === ★ 关掉 UseDNS ===
$ vi /etc/ssh/sshd_config
UseDNS no                                # ★ 明确写一行 no
# 关掉后,sshd 不再对客户端 IP 做反向解析,
#   直接进入认证环节 —— 登录前那几十秒的干等就没了。

# === UseDNS 关掉有什么代价吗 ===
# 影响很小。UseDNS 主要用于:
#  - 在日志里把客户端记成主机名而不是 IP
#  - hosts.allow/deny 里用主机名做规则匹配
# ★ 绝大多数服务器,日志记 IP 完全够用,
#   关掉 UseDNS 是运维界很常见的标准优化。

# === 验证服务器的 DNS 到底通不通(顺带确认根因)===
$ cat /etc/resolv.conf                   # 看配的 DNS 服务器
$ time nslookup www.baidu.com            # ★ 解析慢/失败 = DNS 真有问题
# ★ 如果 nslookup 也卡很久,就实锤了:DNS 不通,
#   UseDNS 正是被它拖死的。

修复 3:用 ssh -v 看握手卡在哪一步

# === ★ 不靠猜:ssh -v 把握手过程一步步打出来 ===

# === ssh -v:打开客户端的调试日志 ===
$ ssh -v root@主机
# -v 会把 SSH 握手的每一步都打印出来。
# ★ 你盯着看,日志【停在哪一行不动】,卡顿就在那一步之后。
# -vv / -vvv 更详细,一般 -v 就够定位。

# === 典型:卡在 DNS 反查时,日志会停在这附近 ===
$ ssh -v root@主机
debug1: SSH2_MSG_KEXINIT sent
debug1: SSH2_MSG_KEXINIT received
debug1: SSH2_MSG_NEWKEYS sent
debug1: SSH2_MSG_SERVICE_ACCEPT received
(★ 长时间卡在这里 —— 服务端在做 DNS 反查 / GSSAPI)
debug1: Authentications that can continue: publickey,password
# ★ 看清楚:从 SERVICE_ACCEPT 到列出认证方式之间,
#   出现长时间停顿 = 服务端预处理卡住了。

# === ★ 一个快速验证法:直接对比 ===
$ time ssh -o UseDNS=no ... 主机          # 客户端无法强制服务端 UseDNS
# 注:UseDNS 是【服务端】选项,客户端没法直接关。
# ★ 真正能从客户端侧快速验证的,是下面这个 GSSAPI:
$ time ssh -o GSSAPIAuthentication=no root@主机 'echo ok'
# 如果加了这个就快了 -> 卡在 GSSAPI;
# 还是慢 -> 那就是服务端 UseDNS / 别的预处理。

# === 服务端视角:看 sshd 的日志 ===
$ journalctl -u sshd --since "10 min ago"
$ tail -f /var/log/secure                # CentOS 上 sshd 日志在这
# ★ 登录卡顿期间盯着这个日志,能看到 sshd
#   卡在认证的哪个阶段、有没有 DNS 相关的报错。

# === 临时提高 sshd 日志级别,看更细的过程 ===
$ vi /etc/ssh/sshd_config
LogLevel VERBOSE                         # 默认 INFO,调成 VERBOSE 更详细
# ★ 排查完记得调回 INFO,VERBOSE 日志量很大。

修复 4:GSSAPI 认证——另一个潜在的拖慢点

# === ★ 二号嫌疑:GSSAPIAuthentication ===

# === GSSAPI 是什么 ===
# GSSAPI 是一种认证框架,主要给 Kerberos 这类
#   企业级单点登录环境用。
# ★ 绝大多数普通服务器,根本没有 Kerberos 环境,
#   压根用不到 GSSAPI。

# === 为什么它也会拖慢登录 ===
# sshd 默认开着 GSSAPIAuthentication。
# 登录时,客户端和服务端会【尝试协商 GSSAPI 认证】——
#   在没有 Kerberos 的环境里,这个协商过程
#   ★ 有时会去做 DNS 查询、或等某个超时,
#   同样可能引入几秒到几十秒的延迟。

# === 看当前配置 ===
$ grep -i gssapi /etc/ssh/sshd_config
GSSAPIAuthentication yes
GSSAPICleanupCredentials yes

# === ★ 没有 Kerberos 环境,就关掉它 ===
$ vi /etc/ssh/sshd_config
GSSAPIAuthentication no
# 关掉后,登录时不再尝试 GSSAPI 协商,少一个潜在卡点。

# === ★ 客户端侧也可以关(影响所有出站连接)===
$ vi ~/.ssh/config
Host *
    GSSAPIAuthentication no
# 在客户端的 ~/.ssh/config 里写上,你从这台机器
#   ssh 出去时,就都不尝试 GSSAPI 了。

# === 顺手提一个真·登录优化:复用连接 ===
$ vi ~/.ssh/config
Host *
    ControlMaster auto
    ControlPath ~/.ssh/cm-%r@%h:%p
    ControlPersist 10m
# ★ ControlMaster 让对同一台机器的多次 ssh 复用
#   一条底层连接 —— 第一次握手后,后续 ssh 几乎瞬连。
# 它解决的是"反复连同一台机器"的累计耗时。

修复 5:改 sshd_config 的正确姿势与生效

# === ★ 改 sshd 配置,有几个必须守住的安全动作 ===

# === 这次要改的几行,汇总 ===
$ vi /etc/ssh/sshd_config
UseDNS no                    # 不对客户端 IP 做反向 DNS 反查
GSSAPIAuthentication no      # 没有 Kerberos 环境,关掉 GSSAPI

# === ★ 第一步:改完先校验语法,别直接重启 ===
$ sshd -t
# sshd -t 检查 sshd_config 语法对不对。
# ★ 没有任何输出 = 语法 OK;有报错就按提示改。
# 这步极其重要 —— 配置写错了就重启 sshd,
#   sshd 可能起不来,你又是远程登录,等于把自己锁在门外。

# === ★ 第二步:重启 / 重载 sshd ===
$ systemctl reload sshd          # 优先 reload —— 不影响已有连接
# 或:
$ systemctl restart sshd
# ★ 重点:重启 sshd【不会踢掉你当前这条已登录的会话】。
#   已建立的 ssh 连接,由独立的子进程维持,
#   重启的是负责"接新连接"的主进程。所以放心重启。

# === ★ 第三步:务必【保留当前会话】,另开一个窗口测试 ===
# 千万不要重启完就退出当前会话!
# ★ 保持现在这条 ssh 不退,【再新开一个终端】去 ssh 登录:
$ ssh root@主机
# 新会话能正常登录 -> 配置没问题,这才能安心退出旧会话。
# 新会话登不上 -> 你还有旧会话在,可以马上改回去补救。

# === 验证效果 ===
$ time ssh root@主机 'echo ok'
ok
real    0m0.6s                  # ★ 从 28 秒降到 1 秒以内
# ★ UseDNS / GSSAPI 一关,登录前的干等消失,瞬间登录。

# === 看 sshd 实际生效的配置(而不是文件里写的)===
$ sshd -T | grep -Ei 'usedns|gssapi'
usedns no
gssapiauthentication no
# ★ sshd -T 打印的是 sshd 真正在用的最终配置,
#   用它确认改动真的生效了。

修复 6:SSH 登录排查纪律

# === 这次事故暴露的认知盲区,定几条纪律 ===

# === 1. ★ 只卡登录、进去就快 -> 不是网络,是 sshd 预处理 ===
$ time ssh 主机 'echo ok'   # real 很长但命令极快 = 卡在握手

# === 2. ★ 头号嫌疑:UseDNS 反向 DNS 查询卡超时 ===
$ grep -i usedns /etc/ssh/sshd_config   # 注释掉默认也是 yes
# 改成 UseDNS no

# === 3. 二号嫌疑:GSSAPIAuthentication,没 Kerberos 就关 ===
$ grep -i gssapi /etc/ssh/sshd_config
# 改成 GSSAPIAuthentication no

# === 4. ★ 用 ssh -v 定位握手卡在哪一步 ===
$ ssh -v 主机   # 看日志停在哪行不动

# === 5. ★ 改完先 sshd -t 校验语法,再 reload ===
$ sshd -t && systemctl reload sshd

# === 6. ★ 重启 sshd 后,保留旧会话,另开窗口验证 ===
# 别一改完就退出,把自己锁在门外。

# === 7. 用 sshd -T 确认配置真的生效 ===
$ sshd -T | grep -Ei 'usedns|gssapi'

# === 8. 排查 SSH 登录慢的命令链 ===
$ time ssh 主机 'echo ok'                   # ① 确认慢在握手
$ ssh -v 主机                               # ② 看卡在哪一步
$ time nslookup 任意域名                     # ③ 服务端 DNS 通不通
$ grep -Ei 'usedns|gssapi' /etc/ssh/sshd_config  # ④ 看可疑配置
$ sshd -t && systemctl reload sshd          # ⑤ 改完校验并重载
# 按这个顺序,登录慢的问题基本能定位。

命令速查

需求                        命令
=============================================================
量登录慢在不在握手          time ssh 主机 'echo ok'
看握手卡在哪一步            ssh -v 主机
看 UseDNS 配置              grep -i usedns /etc/ssh/sshd_config
看 GSSAPI 配置              grep -i gssapi /etc/ssh/sshd_config
校验 sshd 配置语法          sshd -t
看 sshd 实际生效的配置      sshd -T | grep -i usedns
重载 sshd(不断已有连接)   systemctl reload sshd
看 sshd 登录日志            tail -f /var/log/secure
测服务端 DNS 通不通         time nslookup 任意域名
客户端关 GSSAPI 验证        ssh -o GSSAPIAuthentication=no 主机

口诀:只卡登录进去就快,别怪网络,查 sshd 的 UseDNS 和 GSSAPI
      改 sshd_config 先 sshd -t 校验,reload 后留旧会话另开窗口验证

避坑清单

  1. 只卡登录那一下、进去操作就飞快,基本能排除网络通道慢,是 sshd 预处理卡
  2. 用 time ssh 主机 echo ok,命令极快但 real 很长,说明慢在连接和握手阶段
  3. sshd 默认开着 UseDNS,会对客户端 IP 做反向 DNS 查询,DNS 不通就干等超时
  4. sshd_config 里 UseDNS 那行就算被注释掉,很多版本默认值仍是 yes,别被骗
  5. GSSAPIAuthentication 默认也开着,没有 Kerberos 环境时它也可能拖慢登录
  6. 用 ssh -v 看握手日志停在哪行不动,就能定位卡顿发生在哪一步
  7. 改 sshd_config 后务必先 sshd -t 校验语法,语法错了重启 sshd 会起不来
  8. 重启 sshd 不会踢掉当前已登录会话,已有连接由独立子进程维持
  9. 改完 sshd 配置一定保留旧会话,另开窗口验证能登录,再退出旧会话
  10. 用 sshd -T 看 sshd 真正生效的最终配置,确认 UseDNS no 等改动确实生效

总结

这次"SSH 登录前雷打不动卡 30 秒"的事故,纠正了我一个排查网络问题时几乎是条件反射的思维定式——只要是"连接慢""登录慢"这类字眼,我的大脑会立刻、毫不犹豫地把它归类为"网络问题",然后一头扎进网络这条赛道:是不是丢包?是不是带宽不够?是不是路由绕远了?是不是中间哪个防火墙在作怪?我这次也正是这么干的,我换了家里的宽带,换了手机热点,换了不同机房的跳板机,把"网络"这条路上能想到的变量挨个换了个遍。可那 30 秒,纹丝不动,稳定得像一个钟。现在回头看,真正点醒我的,恰恰是这份"稳定"——还有一个我一开始完全没在意的细节:这卡顿,只发生在登录的那一瞬间,我一旦进到机器里面,所有操作都快得不像话。如果真是网络通道慢,这个"慢"应该是均匀地、持续地铺满我和服务器之间的每一次数据往返,我登录后敲的每一个命令都该拖泥带水才对。可它没有。它只在"登录"这一个点上,精准地、孤立地卡了 30 秒,然后就彻底消失了。这个"只卡一下"的特征,本身就在尖叫着告诉我:问题不在"连接通道"上,而在"登录"这个动作本身里面。复盘到根上,我才真正理解了一件以前从没细想过的事:从我敲下回车,到屏幕弹出 password: 让我输密码,这中间并不是"零成本"的一瞬间。在那短短的、我以为什么都没发生的间隙里,服务器上的 sshd 其实正背着我,默默地做着一连串的准备工作。其中有一件,叫反向 DNS 查询:它拿到我的客户端 IP,会顺手去问一句"这个 IP 对应的主机名是什么"。在一个 DNS 健康的环境里,这一问一答快得无法察觉。可这批新服务器的 DNS 根本就是不通的——于是 sshd 这一问,问出去就石沉大海,而它又不肯立刻放弃,它会固执地、忠诚地等下去,一直等到那个 DNS 查询自己超时。那声漫长的、近 30 秒的"干等",就是我每次登录时盯着的那个空屏幕。它从来不是"我连不上服务器",而是"服务器在替我做一件我根本不需要、又偏偏卡住了的事"。这次最大的收获,是我学会了不再被问题表面的"标签"牵着走。"登录慢"这三个字,天然地把我往"网络"上引,可它真正的病根,却藏在一个和网络速度毫无关系的地方——藏在服务端那个我从不关心的、登录前的预处理逻辑里。一个现象该归到哪一类,不该由它的名字决定,而该由它的行为特征决定:它是持续的还是一次性的?它在哪个阶段出现、又在哪个阶段消失?把这些特征一条条看清楚,问题往往就自己把方向指给你了。遇到"慢",先别急着冲进那条最显眼的赛道;先退一步,问问这个"慢",到底慢在哪一段。

—— 别看了 · 2026
声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理 邮箱1846861578@qq.com。
Linux教程

改完配置重启服务却没生效:一次 systemd daemon-reload 排查复盘

2026-5-20 20:29:00

Linux教程

服务报 Too many open files:一次 Linux 文件描述符耗尽排查复盘

2026-5-20 20:35:30

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索