SSH 连不上是运维最常遇到的紧急情况之一,也是最容易被误操作放大的场景:一着急就去改配置文件、重启服务,结果把唯一能登录的通道也弄坏了。实际上 SSH 失败的原因高度集中在几个位置,按固定顺序排查,绝大多数问题在十分钟内就能定位。
这篇文章按"从近到远、从外到内"的顺序组织:先看本地与网络连通,再看端口与安全组、防火墙,然后是服务端的 sshd 状态与配置,接着是密钥权限、认证失败封禁,最后是 DNS、路由、MTU 和磁盘资源这些容易被忽略的原因。文中会给出 ssh -vvv 调试输出的逐段解读方法,帮你从报错信息直接定位到故障层。
排查前先做两件保命的事
第一,不要关闭当前已经连上的会话。 如果你手上还有一个能用的 SSH 连接,务必保持它开着,所有的验证都用新开的窗口做。修改 sshd 配置时,先在测试窗口用新端口或新配置验证成功,再断开旧连接。这条规则适用于所有涉及 SSH、防火墙、网络的变更。
第二,确认你有带外通道。 主流云厂商的控制台都提供 VNC 或串口终端登录方式,它不依赖 SSH 和网络,是最后的安全网。排查之前先确认这个通道可用、密码还记得。物理机则准备显示器或 IPMI。没有带外通道时,任何对 SSH 的修改都要加倍谨慎。
另外,先记录当前配置与状态,方便回滚:
sudo cp -a /etc/ssh/sshd_config /etc/ssh/sshd_config.bak.$(date +%F-%H%M)
sudo sshd -t && echo "配置语法正常"
systemctl status sshd --no-pager # RHEL、Rocky、CentOS
systemctl status ssh --no-pager # Debian、Ubuntu
注意服务名的差异:RHEL 系是 sshd,Debian、Ubuntu 是 ssh,包名分别是 openssh-server。
第一步:确认网络是否可达
先用最基本的命令确认目标主机是否在线:
ping -c 4 10.0.0.10
ping -c 4 -s 1472 10.0.0.10 # 用大包测试,可发现 MTU 问题
能 ping 通不代表 SSH 能用,因为 ICMP 和 TCP 走的是不同策略;但 ping 不通基本说明网络层有问题。注意有些机器会禁 ICMP,此时 ping 不通也不能直接下结论。
接着测端口。不要再用 telnet,很多新系统默认没装,优先用 nc:
nc -vz -w 3 10.0.0.10 22
nc -vz -w 3 10.0.0.10 2222
# 没有 nc 时
timeout 3 bash -c 'cat < /dev/null > /dev/tcp/10.0.0.10/22' && echo "端口开放" || echo "端口不通"
结果判断很关键:
| 现象 | 含义 | 下一步 |
|---|---|---|
succeeded 或空白返回 |
TCP 连接建立成功 | 问题在 SSH 协议层或认证层,继续看第三步之后 |
Connection refused |
端口没进程监听 | 服务端 sshd 没跑或端口不对 |
timed out 无响应 |
包被丢弃 | 防火墙、安全组或网络中间设备拦截 |
No route to host |
路由不可达 | 查路由表和网关 |
路径追踪能看出卡在哪一跳:
mtr -n --tcp --port 22 10.0.0.10
traceroute -n -T -p 22 10.0.0.10
mtr 结合 ping 和 traceroute,能显示每一跳的丢包率。如果某一跳之后全部超时,问题通常出在那一跳的设备上。
第二步:安全组与防火墙
云服务器有两层访问控制,缺一不可:云平台的安全组,以及系统内部的防火墙。
安全组在控制台配置,需要确认入方向放行了目标端口和来源 IP。常见错误是只放行了自己当前的公网 IP,换了网络环境就断了;还有的只配了 IPv4 忘了 IPv6。
系统防火墙要分两系查看:
# RHEL、Rocky、CentOS(firewalld)
sudo firewall-cmd --state
sudo firewall-cmd --list-all
sudo firewall-cmd --list-ports
sudo firewall-cmd --permanent --add-service=ssh
sudo firewall-cmd --permanent --add-port=2222/tcp
sudo firewall-cmd --reload
# Debian、Ubuntu(ufw)
sudo ufw status verbose
sudo ufw allow 22/tcp
sudo ufw allow 2222/tcp
sudo ufw reload
还要检查是否有更上层的规则拦截,比如 nftables、iptables 的自定义链,或者被 fail2ban 自动写入的拒绝规则:
sudo iptables -L -n --line-numbers | head -n 30
sudo nft list ruleset 2>/dev/null | head -n 40
sudo fail2ban-client status sshd
风险提示: 修改防火墙时如果只写了临时规则而没有 --permanent(firewalld)或没有保存(iptables),重启后规则会丢失,导致服务不可达。反之,如果只加了永久规则忘记 --reload,也不会立即生效,容易误判为"规则没用"。
第三步:服务端 sshd 状态与配置
带外登录后,先确认服务是否在跑、监听在哪个端口:
sudo systemctl status sshd --no-pager
sudo ss -lntp | grep -E ':(22|2222)\b'
sudo ss -lntp | grep sshd
sudo ps -ef | grep -v grep | grep sshd
Debian、Ubuntu 把上面的 sshd 换成 ssh。如果服务没运行,启动它:
sudo systemctl start sshd
sudo systemctl enable sshd
sudo journalctl -u sshd --since '-30 min' --no-pager
配置语法错误是最常见的服务起不来的原因。每次改完配置都要先校验:
sudo sshd -t
sudo sshd -T | grep -E '^(port|permitrootlogin|passwordauthentication|pubkeyauthentication)'
sshd -t 只检查语法,sshd -T 会输出实际生效的完整配置,后者能验证你的修改是否真的生效,尤其是配置被多处 Include 覆盖的情况。
几个高频配置项:
# /etc/ssh/sshd_config
Port 2222
PermitRootLogin prohibit-password
PasswordAuthentication yes
PubKeyAuthentication yes
AllowUsers ops admin
ListenAddress 0.0.0.0
ListenAddress 配错会让 sshd 只监听某个地址,从其他网卡就进不来。AllowUsers、AllowGroups、DenyUsers 一旦配置,名单外的用户会被直接拒绝,这类问题表现为密码正确却立刻断开。
修改配置后务必用 reload 而不是 restart,reload 不会断开已有连接:
sudo systemctl reload sshd
第四步:密钥与权限
密钥登录失败时,权限问题占了很大比例。SSH 对权限很敏感,任何一项过宽都会被拒绝。
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
chmod 600 ~/.ssh/id_rsa
chmod 644 ~/.ssh/id_rsa.pub
chown -R $USER:$USER ~/.ssh
家目录本身也不能对组和其他人可写:
chmod g-w,o-w ~
ls -ld ~ ~/.ssh ~/.ssh/authorized_keys
authorized_keys 的格式也要检查:必须是一整行一个公钥,不能有多余换行、不能是 Word 粘贴带来的全角字符、不能有复制时混入的换行。密钥类型较老(如 ssh-dss)在新版 OpenSSH 中已被默认禁用,需要换成 ed25519 或 rsa。
ssh-keygen -t ed25519 -C "ops@host"
ssh-copy-id -i ~/.ssh/id_ed25519.pub -p 2222 user@10.0.0.10
服务端日志能给出确切原因:
# RHEL、Rocky、CentOS
sudo tail -n 50 /var/log/secure
# Debian、Ubuntu
sudo tail -n 50 /var/log/auth.log
# 通用
sudo journalctl -u sshd -f --no-pager
典型报错如 Authentication refused: bad ownership or modes for directory /home/user,几乎就是权限问题的直接答案。
第五步:认证失败与 fail2ban 封禁
连续输错密码会触发 fail2ban,把你的 IP 关进小黑屋。这时表现为连接能建立,但立刻断开,或者根本连不上。
sudo fail2ban-client status
sudo fail2ban-client status sshd
sudo iptables -L f2b-sshd -n --line-numbers
解封当前 IP:
sudo fail2ban-client set sshd unbanip 203.0.113.10
临时调整策略(谨慎):
sudo fail2ban-client set sshd delignoreip 203.0.113.10
建议的做法不是关掉 fail2ban,而是把自己的固定出口 IP 加入 ignoreip 白名单,写入 /etc/fail2ban/jail.local:
[DEFAULT]
ignoreip = 127.0.0.1/8 203.0.113.10
bantime = 3600
findtime = 600
maxretry = 5
改完后执行 sudo systemctl restart fail2ban。注意 bantime 设置过长(如 -1 永久封禁)会把自己锁死,需要带外通道才能解。
第六步:DNS、路由与 MTU
这几类问题表现为连接卡住、能连上但极慢、或者大文件传输时断流。
反向 DNS 解析慢会让登录等待十几秒。服务端可以在 sshd 配置里关掉:
# /etc/ssh/sshd_config
UseDNS no
路由问题常见于多网卡机器,回包走了错误的网卡:
ip route
ip route get 203.0.113.10
ip rule list
MTU 不匹配是隐蔽的元凶:TCP 握手能成功,但传输大包时丢包,表现为登录后能敲命令却无法粘贴长文本、scp 传输卡住。测试方法是用不同大小的包 ping:
ping -c 4 -M do -s 1472 10.0.0.10 # 1500 字节 MTU
ping -c 4 -M do -s 1400 10.0.0.10
ping -c 4 -M do -s 1200 10.0.0.10
-M do 表示不允许分片。找到能通过的最大值加上二十八个字节的头部就是可用 MTU。VPN、隧道、某些云网络环境常需要把 MTU 调到一千四百甚至一千三百多。临时修改:
sudo ip link set dev eth0 mtu 1400
风险提示: 改 MTU 会影响所有经过该网卡的连接,务必在业务低峰操作并准备好回滚值。
第七步:资源耗尽导致登录失败
这一层最容易被忽略:SSH 服务正常、端口通、密码也对,但就是登不进去。
磁盘满会导致 PAM 无法写入日志、无法创建会话文件,从而拒绝登录:
df -h
df -hi
sudo journalctl --vacuum-size=500M
inode 耗尽同样会导致失败,检查 df -hi。/tmp 权限异常也会影响登录,确保它是 1777:
ls -ld /tmp
sudo chmod 1777 /tmp
进程数或内存耗尽时,sshd 无法 fork 子进程,表现为连接建立后立即断开:
free -h
ps -eLf | wc -l
cat /proc/sys/kernel/pid_max
ulimit -u
用户自己的资源限制也要检查,nproc 限制过低会让新进程无法创建:
ulimit -a
grep -E 'nofile|nproc' /etc/security/limits.conf /etc/security/limits.d/*.conf
用 ssh -vvv 读懂调试输出
客户端加 -vvv 能看到完整的协商过程,是定位问题的利器:
ssh -vvv -p 2222 user@10.0.0.10 2> /tmp/ssh-debug.log
按输出顺序解读:
第一段:读取配置与解析。
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: Reading configuration data /home/user/.ssh/config
debug1: /home/user/.ssh/config line 3: Applying options for *
这里能看到本地 ~/.ssh/config 是否覆盖了你的参数,很多人改了命令行参数却没生效,就是因为被配置文件里的 Host * 段覆盖。
第二段:建立 TCP 连接。
debug1: Connecting to 10.0.0.10 [10.0.0.10] port 2222.
debug1: connect to address 10.0.0.10 port 2222: Connection refused
停在 Connecting 长时间无响应,说明包被丢弃,是防火墙或安全组;出现 Connection refused 说明端口没进程监听;出现 Network is unreachable 说明本地路由问题。
第三段:协议与主机密钥协商。
debug1: Remote protocol version 2.0, remote software version OpenSSH_8.0
debug1: SSH2_MSG_KEXINIT sent
debug1: kex: algorithm: curve25519-sha256
debug1: Server host key: ssh-ed25519 SHA256:xxxx
到这一步说明 TCP 通了、sshd 在响应。如果这里报 no matching host key type found,说明客户端和服务端算法不匹配,老客户端连新服务端常见。临时方案是命令行指定算法,长期方案是升级客户端:
ssh -oHostKeyAlgorithms=+ssh-rsa -oPubkeyAcceptedAlgorithms=+ssh-rsa user@host
第四段:认证方式尝试。
debug1: Offering public key: /home/user/.ssh/id_ed25519 ED25519 SHA256:xxx
debug1: Authentications that can continue: publickey,password
debug1: Next authentication method: password
Offering public key 后出现 Server refused our key,说明服务端没接受这个公钥,原因通常是 authorized_keys 内容不对、权限过宽或该用户被限制。输出里有 Authentications that can continue: publickey 而没有 password,说明服务端禁止密码登录,必须配好密钥。
第五段:会话建立。
debug1: Authentication succeeded (publickey).
debug1: channel 0: new [client-session]
debug1: Entering interactive session.
认证成功却卡在这里,通常不是 SSH 的问题,而是 shell 初始化脚本(.bashrc、.profile)里有阻塞命令,或者 session 创建失败。可以绕过交互式 shell 测试:
ssh -p 2222 user@10.0.0.10 '/bin/true' && echo "非交互登录正常"
这条命令能快速区分是 SSH 问题还是 shell 环境问题。
常见问题
昨天还能连,今天突然连不上,最可能是什么?
按顺序怀疑:安全组或防火墙规则被改动、IP 被 fail2ban 封禁、磁盘写满、sshd 因配置改动后重启失败、云主机被重启后服务没设开机自启。先验端口通不通,能快速把范围缩小一半。
提示 REMOTE HOST IDENTIFICATION HAS CHANGED 怎么办?
这是主机密钥变更警告,常见于重装系统或换了 IP 指向别的机器。确认变更合理后再删除本地记录,不要盲目接受未知主机的密钥:
ssh-keygen -R 10.0.0.10
ssh-keygen -R '[10.0.0.10]:2222'
Connection reset by peer 是什么原因?
服务端主动断开。可能是 MaxStartups 达到上限、fail2ban 刚封了 IP、PAM 模块因磁盘满而失败,或者 sshd 崩溃重启。看服务端 /var/log/secure 或 auth.log 能直接得到原因。
修改 sshd_config 后服务启动失败,怎么恢复?
保持当前连接不要断开,用 sshd -t 看具体报错行,改回错误项,再 systemctl start sshd。如果已经断开,只能用控制台 VNC 登录修复,这也是为什么一定要先备份配置文件并保留会话。
换了端口还是连不上,但旧端口能连,问题在哪?
大概率是防火墙或 SELinux 没放行新端口,或者改了配置但没重启服务。用 sshd -T | grep port 确认实际监听端口,用 ss -lntp 确认确实在监听,再用 nc 从外部测试。
总结
- 排查顺序固定为:网络连通、端口可达、安全组与防火墙、sshd 服务与配置、密钥权限、认证封禁、DNS 路由 MTU、系统资源。
- 保留现有会话、确认带外通道、备份配置文件,这三件事必须在动手前完成,否则一次误操作就可能彻底失去访问能力。
- 改配置后一定要
sshd -t校验语法,并用sshd -T确认实际生效值,优先用reload而非restart。 ssh -vvv的输出按配置读取、TCP 连接、密钥协商、认证尝试、会话建立五段解读,卡在哪一段就定位到哪一层。- 磁盘满、inode 满、进程数上限这类资源问题同样会表现为 SSH 登录失败,常规排查无果时一定要检查它们。
企业QQ咨询




