常见连接问题
连接被拒绝(Connection Refused)
问题表现
ssh: connect to host example.com port 22: Connection refused
可能原因和解决方案
SSH服务未运行 “`bash
检查SSH服务状态
sudo systemctl status sshd
或
sudo service ssh status
启动SSH服务
sudo systemctl start sshd
或
sudo service ssh start
设置开机自启
sudo systemctl enable sshd
2. **端口配置错误**
```bash
# 检查SSH配置中的端口
sudo grep "^Port" /etc/ssh/sshd_config
# 检查端口是否被监听
sudo netstat -tlnp | grep :22
# 或
sudo ss -tlnp | grep :22
# 使用正确端口连接
ssh -p 2222 user@hostname
防火墙阻止 “`bash
检查防火墙状态
sudo ufw status
或
sudo iptables -L
允许SSH端口
sudo ufw allow 22
或
sudo iptables -A INPUT -p tcp –dport 22 -j ACCEPT
### 连接超时(Connection Timeout)
#### 问题表现
```bash
ssh: connect to host example.com port 22: Connection timed out
排查步骤
网络连通性测试 “`bash
测试网络连通性
ping example.com
测试端口连通性
telnet example.com 22
或
nc -zv example.com 22
路由跟踪
traceroute example.com
2. **DNS解析问题**
```bash
# 测试DNS解析
nslookup example.com
# 或
dig example.com
# 直接使用IP地址连接
ssh user@192.168.1.100
网络代理设置 “`bash
检查代理设置
echo $http_proxy echo $https_proxy
通过代理连接
ssh -o ProxyCommand=“nc -X connect -x proxy:8080 %h %p” user@hostname
### 权限被拒绝(Permission Denied)
#### 密钥认证失败
```bash
# 详细调试信息
ssh -vvv user@hostname
# 检查密钥权限
ls -la ~/.ssh/
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_rsa
chmod 644 ~/.ssh/id_rsa.pub
# 测试密钥
ssh-keygen -y -f ~/.ssh/id_rsa
# 检查公钥是否正确部署
ssh user@hostname "cat ~/.ssh/authorized_keys"
服务器端权限问题
# 检查用户主目录权限
ls -la /home/user/
chmod 755 /home/user
# 检查.ssh目录权限
ls -la /home/user/.ssh/
chmod 700 /home/user/.ssh
chmod 600 /home/user/.ssh/authorized_keys
# 检查文件所有者
sudo chown -R user:user /home/user/.ssh
认证问题排查
密钥认证调试
客户端调试
# 详细调试输出
ssh -vvv user@hostname
# 仅使用公钥认证
ssh -o PreferredAuthentications=publickey user@hostname
# 指定特定密钥
ssh -i ~/.ssh/specific_key user@hostname
# 禁用其他认证方式
ssh -o PasswordAuthentication=no -o ChallengeResponseAuthentication=no user@hostname
服务器端调试
# 查看SSH日志
sudo tail -f /var/log/auth.log | grep sshd
# 或
sudo journalctl -u sshd -f
# 临时启用调试模式
sudo /usr/sbin/sshd -D -d
# 检查SSH配置
sudo sshd -t
sudo sshd -T
常见认证配置问题
SELinux问题 “`bash
检查SELinux状态
getenforce
查看SELinux日志
sudo ausearch -m avc -ts recent
恢复SSH相关文件的SELinux上下文
sudo restorecon -R ~/.ssh sudo restorecon -R /home/user/.ssh
2. **SSH配置错误**
```bash
# 检查关键配置项
sudo grep -E "^(PubkeyAuthentication|PasswordAuthentication|PermitRootLogin)" /etc/ssh/sshd_config
# 常见配置修复
# /etc/ssh/sshd_config
PubkeyAuthentication yes
PasswordAuthentication yes # 或 no,根据需要
PermitRootLogin no # 安全考虑
AuthorizedKeysFile .ssh/authorized_keys
性能问题诊断
连接缓慢
DNS反向解析问题
# 禁用DNS反向解析
# /etc/ssh/sshd_config
UseDNS no
# 重启SSH服务
sudo systemctl restart sshd
GSSAPI认证延迟
# 客户端禁用GSSAPI
ssh -o GSSAPIAuthentication=no user@hostname
# 配置文件设置
# ~/.ssh/config
Host *
GSSAPIAuthentication no
传输速度慢
加密算法优化
# 使用快速加密算法
ssh -c aes128-gcm@openssh.com user@hostname
# 配置文件设置
# ~/.ssh/config
Host fast-server
HostName server.example.com
Ciphers aes128-gcm@openssh.com,aes256-gcm@openssh.com
Compression yes
网络优化
# 启用TCP窗口缩放
echo 'net.core.rmem_max = 134217728' | sudo tee -a /etc/sysctl.conf
echo 'net.core.wmem_max = 134217728' | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
# 调整SSH缓冲区
# /etc/ssh/sshd_config
TcpKeepAlive yes
ClientAliveInterval 30
ClientAliveCountMax 3
文件传输问题
SCP/SFTP传输失败
权限问题
# 检查目标目录权限
ssh user@hostname "ls -la /target/directory/"
# 检查磁盘空间
ssh user@hostname "df -h"
# 检查文件系统权限
ssh user@hostname "touch /target/directory/test && rm /target/directory/test"
传输中断恢复
# 使用rsync恢复传输
rsync -avz --partial --progress -e ssh large-file user@hostname:/path/
# SFTP恢复传输
sftp user@hostname
sftp> reput interrupted-file.txt
文件完整性验证
# 传输前计算校验和
md5sum large-file.txt
# 传输后验证
ssh user@hostname "md5sum /path/large-file.txt"
# 使用rsync验证
rsync -avz --checksum -e ssh large-file.txt user@hostname:/path/
网络问题排查
连接不稳定
保持连接活跃
# 客户端配置
# ~/.ssh/config
Host *
ServerAliveInterval 60
ServerAliveCountMax 3
TCPKeepAlive yes
# 服务器端配置
# /etc/ssh/sshd_config
ClientAliveInterval 60
ClientAliveCountMax 3
TCPKeepAlive yes
网络质量测试
# 测试网络延迟
ping -c 10 hostname
# 测试网络带宽
iperf3 -c hostname
# 测试丢包率
mtr hostname
防火墙和NAT问题
端口转发调试
# 测试本地端口转发
ssh -L 8080:target:80 -v user@gateway
telnet localhost 8080
# 测试远程端口转发
ssh -R 8080:localhost:80 -v user@server
# 在服务器上测试
telnet localhost 8080
NAT穿透
# 使用autossh保持连接
autossh -M 20000 -R 8080:localhost:80 user@public-server
# 配置自动重连
# ~/.ssh/config
Host tunnel
HostName public-server.com
RemoteForward 8080 localhost:80
ServerAliveInterval 30
ServerAliveCountMax 3
ExitOnForwardFailure yes
系统级问题
资源限制
连接数限制
# 检查当前连接数
ss -tn | grep :22 | wc -l
# 检查SSH配置限制
sudo grep MaxStartups /etc/ssh/sshd_config
sudo grep MaxSessions /etc/ssh/sshd_config
# 调整限制
# /etc/ssh/sshd_config
MaxStartups 20:30:100
MaxSessions 20
文件描述符限制
# 检查当前限制
ulimit -n
# 检查SSH进程限制
sudo cat /proc/$(pgrep sshd)/limits
# 调整限制
# /etc/security/limits.conf
* soft nofile 65536
* hard nofile 65536
日志分析
系统日志
# 查看SSH相关日志
sudo grep sshd /var/log/auth.log | tail -50
sudo journalctl -u sshd --since "1 hour ago"
# 查看系统资源使用
top
htop
iotop
自定义日志分析
#!/bin/bash
# SSH连接分析脚本
echo "=== SSH连接统计 ==="
sudo grep "Accepted" /var/log/auth.log | awk '{print $9}' | sort | uniq -c | sort -nr
echo "\n=== 失败登录尝试 ==="
sudo grep "Failed password" /var/log/auth.log | awk '{print $11}' | sort | uniq -c | sort -nr
echo "\n=== 最近连接 ==="
sudo grep "Accepted" /var/log/auth.log | tail -10
故障排除工具
SSH调试工具
ssh-audit
# 安装ssh-audit
pip3 install ssh-audit
# 审计SSH服务器
ssh-audit hostname
# 审计特定端口
ssh-audit hostname:2222
nmap扫描
# 扫描SSH端口
nmap -p 22 hostname
# 详细扫描
nmap -sV -p 22 hostname
# 扫描SSH版本和算法
nmap --script ssh2-enum-algos hostname
网络诊断工具
tcpdump抓包
# 抓取SSH流量
sudo tcpdump -i any -n port 22
# 保存到文件
sudo tcpdump -i any -n port 22 -w ssh-traffic.pcap
# 分析特定主机
sudo tcpdump -i any -n host hostname and port 22
Wireshark分析
# 过滤SSH流量
tcp.port == 22
# 分析SSH握手
ssh.protocol
# 查看加密算法协商
ssh.kex
应急处理
紧急访问
控制台访问
# 物理控制台
# 直接在服务器上操作
# 虚拟控制台(云服务器)
# 通过云服务商的Web控制台
# IPMI/iDRAC
ipmitool -I lanplus -H ipmi-hostname -U username -P password sol activate
单用户模式
# 重启到单用户模式
# 在GRUB菜单中添加 single 或 1
# 修复SSH配置
sudo nano /etc/ssh/sshd_config
sudo systemctl restart sshd
配置恢复
备份和恢复
# 备份SSH配置
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.backup
cp ~/.ssh/config ~/.ssh/config.backup
# 恢复默认配置
sudo cp /etc/ssh/sshd_config.backup /etc/ssh/sshd_config
sudo systemctl restart sshd
# 重新生成主机密钥
sudo rm /etc/ssh/ssh_host_*
sudo ssh-keygen -A
sudo systemctl restart sshd
预防措施
监控和告警
连接监控脚本
#!/bin/bash
# SSH连接监控
HOST="critical-server"
MAX_ATTEMPTS=3
for i in $(seq 1 $MAX_ATTEMPTS); do
if ssh -o ConnectTimeout=10 -o BatchMode=yes $HOST "echo 'SSH OK'" >/dev/null 2>&1; then
echo "SSH connection to $HOST: OK"
exit 0
else
echo "SSH connection to $HOST: FAILED (attempt $i/$MAX_ATTEMPTS)"
sleep 5
fi
done
# 发送告警
echo "SSH connection to $HOST failed after $MAX_ATTEMPTS attempts" | mail -s "SSH Alert" admin@company.com
日志轮转
# /etc/logrotate.d/ssh-custom
/var/log/ssh-custom.log {
daily
missingok
rotate 30
compress
delaycompress
notifempty
postrotate
/bin/kill -HUP $(cat /var/run/rsyslogd.pid 2>/dev/null) 2>/dev/null || true
endscript
}
定期维护
健康检查清单
- [ ] SSH服务状态正常
- [ ] 配置文件语法正确
- [ ] 密钥权限设置正确
- [ ] 日志文件大小合理
- [ ] 防火墙规则有效
- [ ] 系统资源充足
- [ ] 网络连通性正常
- [ ] 证书未过期
自动化检查脚本
#!/bin/bash
# SSH健康检查脚本
echo "=== SSH健康检查报告 ==="
echo "检查时间: $(date)"
echo
# 检查SSH服务状态
echo "1. SSH服务状态:"
systemctl is-active sshd
echo
# 检查配置文件
echo "2. 配置文件语法:"
sudo sshd -t && echo "配置文件语法正确" || echo "配置文件语法错误"
echo
# 检查端口监听
echo "3. 端口监听状态:"
ss -tlnp | grep sshd
echo
# 检查磁盘空间
echo "4. 磁盘空间:"
df -h | grep -E "(Filesystem|/$|/var|/home)"
echo
# 检查内存使用
echo "5. 内存使用:"
free -h
echo
# 检查最近的连接
echo "6. 最近的SSH连接:"
sudo grep "Accepted" /var/log/auth.log | tail -5
echo
echo "=== 检查完成 ==="
小结
SSH故障排除是一个系统性的过程,需要从网络、系统、配置、权限等多个层面进行分析。关键要点包括:
- 系统化排查:按照网络连通性 → 服务状态 → 配置正确性 → 权限设置的顺序
- 详细日志分析:充分利用SSH的详细调试输出和系统日志
- 工具辅助:使用专业的网络和SSH诊断工具
- 预防为主:建立监控机制,定期检查和维护
- 应急准备:准备多种访问方式和恢复方案
掌握这些故障排除技能,能够快速定位和解决SSH相关问题,确保系统的稳定运行。