SSH 服务器完全指南 / 第14章 故障排查
第14章 故障排查
14.1 SSH 调试模式
客户端调试
# 一级调试
ssh -v user@server
# 二级调试(更详细)
ssh -vv user@server
# 三级调试(最详细)
ssh -vvv user@server
调试输出关键阶段
# 1. 连接阶段
debug1: Connecting to server [192.168.1.100] port 22.
debug1: Connection established.
# 2. 密钥协商
debug1: SSH2_MSG_KEXINIT sent
debug1: kex: algorithm: curve25519-sha256
debug1: kex: host key algorithm: ssh-ed25519
# 3. 主机验证
debug1: Host 'server' is known and matches the ED25519 host key.
# 或
debug1: Host 'server' is not in the known_hosts list.
# 4. 认证
debug1: Offering public key: /home/user/.ssh/id_ed25519
debug1: Server accepts key: /home/user/.ssh/id_ed25519
# 或
debug1: Trying private key: /home/user/.ssh/id_ed25519
debug1: No more authentication methods to try.
# 5. 会话建立
debug1: Authentication succeeded (publickey).
debug1: channel 0: new [client-session]
服务端调试
# 不使用 systemd,直接前台启动(调试模式)
sudo /usr/sbin/sshd -d
# 或指定配置文件
sudo /usr/sbin/sshd -d -f /etc/ssh/sshd_config.debug
# 端口调试模式(避免占用 22 端口)
sudo /usr/sbin/sshd -d -p 2222
# 然后从客户端连接
ssh -p 2222 user@server
注意: 服务端
-d模式只处理一个连接然后退出,不会影响正常运行的 sshd 服务。
14.2 常见连接问题
问题一:Connection refused
症状:
ssh: connect to host 192.168.1.100 port 22: Connection refused
排查步骤:
# 1. 检查目标主机 SSH 服务是否运行
ssh user@server "systemctl status sshd"
# 从本机检查端口是否开放
nc -zv 192.168.1.100 22
nmap -p 22 192.168.1.100
# 2. 检查防火墙
sudo ufw status # Ubuntu
sudo firewall-cmd --list-all # RHEL/CentOS
sudo iptables -L -n | grep 22
# 3. 检查 SSH 是否监听
sudo ss -tlnp | grep :22
sudo netstat -tlnp | grep :22
# 4. 检查 sshd 是否运行
sudo systemctl status sshd
sudo ps aux | grep sshd
# 5. 检查配置文件
sudo sshd -t
# 6. 尝试重启服务
sudo systemctl restart sshd
问题二:Connection timed out
症状:
ssh: connect to host 192.168.1.100 port 22: Connection timed out
排查步骤:
# 1. 测试网络连通性
ping 192.168.1.100
traceroute 192.168.1.100
# 2. 测试端口连通性
nc -zv 192.168.1.100 22
telnet 192.168.1.100 22
# 3. 检查防火墙规则
sudo iptables -L -n -v
sudo nft list ruleset
# 4. 检查安全组(云服务器)
# 在云平台控制台检查安全组规则是否允许 22 端口
# 5. 检查路由
ip route get 192.168.1.100
问题三:Permission denied (publickey)
症状:
user@server: Permission denied (publickey).
排查步骤:
# 1. 客户端调试
ssh -vvv user@server 2>&1 | grep -i "permission\|publickey\|offering\|accept"
# 2. 检查服务器端日志
sudo journalctl -u sshd -n 50
# 3. 检查 authorized_keys
ls -la ~/.ssh/authorized_keys
cat ~/.ssh/authorized_keys
# 4. 检查目录权限(服务器端)
ls -la ~/.ssh/
# .ssh 目录应该是 700
# authorized_keys 应该是 600
# 5. 检查私钥权限(客户端)
ls -la ~/.ssh/id_*
# 私钥应该是 600
# 6. 检查 sshd 配置
sudo sshd -T | grep -i "pubkey\|authorized"
# 7. 检查 SELinux
sudo ausearch -m avc -ts recent | grep ssh
sudo setenforce 0 # 临时禁用测试
# 8. 修复权限
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
chmod 600 ~/.ssh/id_*
问题四:Permission denied (password)
症状:
user@server: Permission denied (password).
排查步骤:
# 1. 检查密码是否正确
# 尝试在服务器本地登录
su - user
# 2. 检查密码认证是否启用
sudo sshd -T | grep passwordauthentication
# 3. 检查 PAM 配置
cat /etc/pam.d/sshd
# 4. 检查账户是否被锁定
sudo passwd -S user
sudo faillock --user user
# 5. 检查账户是否过期
sudo chage -l user
# 6. 检查 nologin/nologin shell
grep user /etc/passwd
# 7. 检查 AllowUsers/DenyGroups
sudo sshd -T | grep -i "allow\|deny"
问题五:Host key verification failed
症状:
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Host key verification failed.
解决步骤:
# 1. 确认服务器身份(通过带外渠道)
# 2. 如果确认是服务器重装/密钥更换
ssh-keygen -R 192.168.1.100
# 3. 重新连接并接受新密钥
ssh user@192.168.1.100
# 4. 如果是 known_hosts 中有错误条目
ssh-keygen -R "[192.168.1.100]:2222"
问题六:Connection reset by peer
症状:
Connection reset by 192.168.1.100 port 22
排查步骤:
# 1. 检查服务器日志
sudo journalctl -u sshd -n 50
# 2. 可能原因:
# - MaxStartups 限制(并发未认证连接过多)
# - 防火墙重置连接
# - 服务器资源不足
# - sshd 进程崩溃
# 3. 检查 MaxStartups 设置
sudo sshd -T | grep maxstartups
# 4. 检查服务器资源
free -m
df -h
cat /proc/loadavg
问题七:Broken pipe / Write failed
症状:
Write failed: Broken pipe
解决步骤:
# 客户端配置保活
# ~/.ssh/config
Host *
ServerAliveInterval 60
ServerAliveCountMax 3
TCPKeepAlive yes
# 服务端配置
# /etc/ssh/sshd_config
ClientAliveInterval 60
ClientAliveCountMax 3
TCPKeepAlive yes
# 临时解决方案
# 在当前终端发送保活信号
# 按 Enter 键或 Ctrl+C
14.3 权限问题
常见权限错误
# 错误一:UNPROTECTED PRIVATE KEY FILE
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: UNPROTECTED PRIVATE KEY FILE! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions 0644 for '/home/user/.ssh/id_ed25519' are too open.
# 解决
chmod 600 ~/.ssh/id_ed25519
# 错误二:Authentication refused
Authentication refused: bad ownership or modes for directory /home/user
# 解决
chmod 755 /home/user
chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
# 错误三:bad ownership or modes for file
Authentication refused: bad ownership or modes for file /home/user/.ssh/authorized_keys
# 解决
chmod 600 ~/.ssh/authorized_keys
chown user:user ~/.ssh/authorized_keys
SSH 权限检查脚本
#!/bin/bash
# check-ssh-permissions.sh
echo "=== SSH 权限检查 ==="
# 检查 .ssh 目录
if [ -d ~/.ssh ]; then
PERM=$(stat -c %a ~/.ssh)
if [ "$PERM" = "700" ]; then
echo "✅ ~/.ssh 权限正确 (700)"
else
echo "❌ ~/.ssh 权限错误 ($PERM),应该是 700"
fi
else
echo "❌ ~/.ssh 目录不存在"
fi
# 检查 authorized_keys
if [ -f ~/.ssh/authorized_keys ]; then
PERM=$(stat -c %a ~/.ssh/authorized_keys)
if [ "$PERM" = "600" ]; then
echo "✅ authorized_keys 权限正确 (600)"
else
echo "❌ authorized_keys 权限错误 ($PERM),应该是 600"
fi
else
echo "⚠️ authorized_keys 不存在"
fi
# 检查私钥文件
for key in ~/.ssh/id_*; do
if [[ "$key" == *.pub ]]; then continue; fi
if [ ! -f "$key" ]; then continue; fi
PERM=$(stat -c %a "$key")
if [ "$PERM" = "600" ]; then
echo "✅ $key 权限正确 (600)"
else
echo "❌ $key 权限错误 ($PERM),应该是 600"
fi
done
# 检查 config
if [ -f ~/.ssh/config ]; then
PERM=$(stat -c %a ~/.ssh/config)
if [ "$PERM" = "600" ]; then
echo "✅ config 权限正确 (600)"
else
echo "❌ config 权限错误 ($PERM),应该是 600"
fi
fi
# 检查主目录
HOME_PERM=$(stat -c %a ~)
echo "⚠️ 主目录权限: $HOME_PERM(应该是 755 或更严格)"
echo ""
echo "=== 修复命令 ==="
echo "chmod 700 ~/.ssh"
echo "chmod 600 ~/.ssh/authorized_keys ~/.ssh/config ~/.ssh/id_*"
echo "chmod 644 ~/.ssh/*.pub ~/.ssh/known_hosts"
SELinux 相关问题
# 查看 SELinux 是否阻止 SSH
sudo ausearch -m avc -ts recent | grep ssh
# 查看 SELinux 状态
getenforce
# 临时禁用(仅用于排查)
sudo setenforce 0
# 修复 SELinux 上下文
sudo restorecon -Rv ~/.ssh
# 允许 SSH 访问非标准目录
sudo semanage fcontext -a -t ssh_home_t "/custom/ssh/path(/.*)?"
sudo restorecon -Rv /custom/ssh/path
14.4 配置问题排查
检查配置语法
# 检查语法
sudo sshd -t
# 如果有错误,会显示:
# /etc/ssh/sshd_config: line 88: Bad configuration option: invalidoption
# 查看完整生效配置
sudo sshd -T
# 过滤特定配置
sudo sshd -T | grep -i "password\|permit\|allow\|deny"
Match 块问题
# 常见问题:
# Match 块中的配置对所有后续行生效
# Match 块只能放在配置文件末尾
# 调试 Match 块
ssh -vvv user@server 2>&1 | grep -i "matching"
# 查看哪些规则匹配
sudo sshd -T -C user=admin,host=192.168.1.100,addr=192.168.1.100
Include 文件问题
# 检查 Include 文件是否存在
ls -la /etc/ssh/sshd_config.d/
# 检查 Include 语法
grep -n "Include" /etc/ssh/sshd_config
# 合并查看所有配置
cat /etc/ssh/sshd_config /etc/ssh/sshd_config.d/*.conf | grep -v '^#' | grep -v '^$'
14.5 认证问题排查
密钥认证调试
# 客户端调试(查看密钥认证过程)
ssh -vvv user@server 2>&1 | grep -A5 -B5 "publickey\|Offering\|accepts\|denied"
# 服务端日志
sudo journalctl -u sshd -n 100 | grep -i "publickey\|key\|denied"
# 检查密钥是否在 authorized_keys 中
ssh-keygen -lf ~/.ssh/id_ed25519.pub # 获取指纹
grep "$(ssh-keygen -lf ~/.ssh/id_ed25519.pub | awk '{print $2}')" ~/.ssh/authorized_keys
密码认证调试
# 服务端日志
sudo journalctl -u sshd | grep -i "password\|pam\|failed"
# 检查 PAM 配置
cat /etc/pam.d/sshd
# 手动测试 PAM
sudo pamtester sshd user authenticate
证书认证调试
# 查看证书内容
ssh-keygen -Lf ~/.ssh/id_ed25519-cert.pub
# 检查信任的 CA
sudo cat /etc/ssh/ca_user_key.pub
# 检查证书有效期
ssh-keygen -Lf ~/.ssh/id_ed25519-cert.pub | grep -i "valid\|expires"
14.6 网络问题排查
端口检查
# 检查端口是否开放
nc -zv 192.168.1.100 22
nmap -p 22 192.168.1.100
# 检查本机监听
ss -tlnp | grep :22
ss -tlnp | grep sshd
# 检查连接数
ss -tnp | grep :22 | wc -l
防火墙检查
# iptables
sudo iptables -L -n -v | grep 22
# firewalld
sudo firewall-cmd --list-all
# nftables
sudo nft list ruleset | grep 22
# UFW
sudo ufw status verbose
DNS 问题
# 正向解析
nslookup server.example.com
dig server.example.com
# 反向解析
nslookup 192.168.1.100
dig -x 192.168.1.100
# 禁用 DNS 反向解析(加速登录)
# /etc/ssh/sshd_config
UseDNS no
14.7 性能问题排查
连接慢
# 测量连接时间
time ssh user@server "echo connected"
# 详细分析(查看各阶段耗时)
ssh -vvv user@server 2>&1 | ts '[%Y-%m-%d %H:%M:%S]'
# 常见原因和解决方案
# 1. DNS 反向解析慢 → UseDNS no
# 2. GSSAPI 认证超时 → GSSAPIAuthentication no
# 3. 主机密钥检查慢 → 客户端 StrictHostKeyChecking accept-new
# 4. 网络延迟 → 使用 ControlMaster 复用连接
传输慢
# 测试带宽
dd if=/dev/zero bs=1M count=100 | ssh user@server "cat > /dev/null"
# 启用压缩
ssh -C user@server
# 使用更快的加密算法
ssh -c chacha20-poly1305@openssh.com user@server
# 使用 rsync 代替 scp
rsync -avz -e ssh largefile user@server:/path/
14.8 日志分析
关键日志位置
# systemd 系统
sudo journalctl -u sshd
sudo journalctl -u sshd --since "1 hour ago"
sudo journalctl -u sshd --since today
# 传统日志
sudo tail -f /var/log/auth.log # Debian/Ubuntu
sudo tail -f /var/log/secure # RHEL/CentOS
常见日志模式
# 认证成功
grep "Accepted" /var/log/auth.log
# 认证失败
grep "Failed" /var/log/auth.log
# 无效用户
grep "Invalid user" /var/log/auth.log
# 会话开始/结束
grep "session opened\|session closed" /var/log/auth.log
# 按 IP 统计失败次数
grep "Failed password" /var/log/auth.log | \
awk '{print $(NF-3)}' | sort | uniq -c | sort -rn | head -20
# 实时监控攻击
sudo tail -f /var/log/auth.log | grep --line-buffered "Failed\|Invalid"
增强日志配置
# /etc/ssh/sshd_config
LogLevel VERBOSE
# 创建日志轮转配置
# /etc/logrotate.d/sshd-custom
/var/log/sshd/*.log {
daily
rotate 30
compress
delaycompress
notifempty
create 0640 root adm
sharedscripts
postrotate
/bin/systemctl reload sshd > /dev/null 2>&1 || true
endscript
}
14.9 问题排查速查表
| 症状 | 可能原因 | 解决方案 |
|---|---|---|
| Connection refused | SSH 服务未运行 | systemctl start sshd |
| Connection timed out | 防火墙阻止 | 检查安全组/防火墙规则 |
| Permission denied (publickey) | 权限错误 | 修复 ~/.ssh/ 权限 |
| Permission denied (password) | 密码错误或 PAM | 检查密码和 PAM 配置 |
| Host key changed | 主机密钥变更 | ssh-keygen -R host |
| Broken pipe | 连接超时 | 设置 ServerAliveInterval |
| Write failed | 网络中断 | 检查网络和保活设置 |
| Key is too open | 私钥权限过宽 | chmod 600 ~/.ssh/id_* |
| Connection reset | 服务端限制 | 检查 MaxStartups |
| No route to host | 网络不通 | 检查路由和防火墙 |
扩展阅读
下一章: 第15章 最佳实践与规范 → 学习生产环境的 SSH 密钥管理、审计日志和运维规范。