SSH连接问题

title

SSH连接问题是Linux运维中非常常见的问题,影响远程管理和文件传输,需要快速诊断和解决。

🚨 问题现象

常见错误信息

# 连接被拒绝
ssh: connect to host [hostname] port 22: Connection refused

# 连接超时
ssh: connect to host [hostname] port 22: Connection timed out

# 权限错误
Permission denied (publickey)
Permission denied, please try again

# 主机密钥验证失败
Host key verification failed
WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!

# 协议版本不匹配
Protocol major versions differ: 2 vs. 1

系统表现

  • 无法建立SSH连接
  • 连接建立后立即断开
  • 密码认证失败
  • 密钥认证失败
  • 连接缓慢或卡顿

🔍 问题诊断

1. 检查SSH服务状态

# 检查SSH服务是否运行
systemctl status sshd
systemctl status ssh

# 检查SSH进程
ps aux | grep sshd
pgrep -f sshd

# 检查SSH服务启用状态
systemctl is-enabled sshd

2. 检查网络连通性

# 测试端口连通性
telnet hostname 22
nc -zv hostname 22

# 检查SSH监听端口
netstat -tuln | grep :22
ss -tuln | grep :22

# 检查防火墙规则
iptables -L | grep ssh
firewall-cmd --list-services

3. 检查SSH配置

# 查看SSH服务端配置
sudo cat /etc/ssh/sshd_config

# 测试SSH配置语法
sudo sshd -t

# 查看SSH客户端配置
cat ~/.ssh/config
cat /etc/ssh/ssh_config

4. 检查认证相关

# 检查SSH密钥
ls -la ~/.ssh/
cat ~/.ssh/authorized_keys

# 检查密钥权限
ls -la ~/.ssh/id_rsa*
ls -la ~/.ssh/authorized_keys

# 查看SSH日志
sudo tail -f /var/log/auth.log     # Ubuntu/Debian
sudo tail -f /var/log/secure       # CentOS/RHEL
journalctl -u sshd -f

5. 使用详细模式诊断

# 客户端详细输出
ssh -v hostname
ssh -vv hostname
ssh -vvv hostname  # 最详细输出

# 指定端口和用户
ssh -v -p 2222 user@hostname

# 测试特定认证方式
ssh -o PreferredAuthentications=password hostname
ssh -o PreferredAuthentications=publickey hostname

🛠️ 解决方案

SSH服务问题

1. 启动和重启SSH服务

# 启动SSH服务
sudo systemctl start sshd
sudo systemctl start ssh

# 重启SSH服务
sudo systemctl restart sshd
sudo systemctl restart ssh

# 设置开机自启
sudo systemctl enable sshd

2. 修复SSH配置

# 备份SSH配置
sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.backup

# 基本SSH配置示例
sudo vim /etc/ssh/sshd_config

# 基本配置
Port 22
Protocol 2
PermitRootLogin no
PasswordAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
UsePAM yes
X11Forwarding yes
PrintMotd no
AcceptEnv LANG LC_*
Subsystem sftp /usr/lib/openssh/sftp-server

# 测试配置并重启
sudo sshd -t
sudo systemctl restart sshd

3. 修改SSH端口

# 修改SSH端口(如果默认22端口被封)
sudo vim /etc/ssh/sshd_config

# 修改端口
Port 2222

# 更新SELinux配置(如果启用)
sudo semanage port -a -t ssh_port_t -p tcp 2222

# 更新防火墙规则
sudo firewall-cmd --add-port=2222/tcp --permanent
sudo firewall-cmd --reload

# 重启SSH服务
sudo systemctl restart sshd

认证问题解决

1. 密码认证问题

# 启用密码认证
sudo vim /etc/ssh/sshd_config

PasswordAuthentication yes
ChallengeResponseAuthentication yes
UsePAM yes

# 重启服务
sudo systemctl restart sshd

# 修改用户密码
sudo passwd username

# 检查用户账户状态
sudo chage -l username
sudo passwd -S username

2. 密钥认证问题

# 生成SSH密钥对
ssh-keygen -t rsa -b 4096 -C "your_email@example.com"
ssh-keygen -t ed25519 -C "your_email@example.com"

# 复制公钥到服务器
ssh-copy-id user@hostname
ssh-copy-id -i ~/.ssh/id_rsa.pub user@hostname

# 手动添加公钥
cat ~/.ssh/id_rsa.pub | ssh user@hostname "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"

# 设置正确权限
chmod 700 ~/.ssh
chmod 600 ~/.ssh/id_rsa
chmod 644 ~/.ssh/id_rsa.pub
chmod 600 ~/.ssh/authorized_keys

3. 修复权限问题

# 修复SSH目录权限
sudo chmod 700 /home/username/.ssh
sudo chmod 600 /home/username/.ssh/authorized_keys
sudo chown -R username:username /home/username/.ssh

# 修复主目录权限
sudo chmod 755 /home/username
sudo chown username:username /home/username

# 检查SELinux上下文
sudo restorecon -R /home/username/.ssh

网络和防火墙问题

1. 防火墙配置

# Ubuntu/Debian - ufw
sudo ufw allow ssh
sudo ufw allow 22/tcp

# CentOS/RHEL - firewalld
sudo firewall-cmd --add-service=ssh --permanent
sudo firewall-cmd --add-port=22/tcp --permanent
sudo firewall-cmd --reload

# 使用iptables
sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
sudo iptables-save > /etc/iptables/rules.v4

2. 网络问题排查

# 检查网络接口
ip addr show
ifconfig

# 检查路由
ip route show
netstat -rn

# 测试DNS解析
nslookup hostname
dig hostname

# 检查hosts文件
cat /etc/hosts

🔧 SSH故障排查脚本

SSH诊断脚本

#!/bin/bash
# ssh_diagnosis.sh

TARGET_HOST=$1
TARGET_PORT=${2:-22}
TARGET_USER=${3:-$(whoami)}

if [ -z "$TARGET_HOST" ]; then
    echo "用法: $0 <hostname> [port] [username]"
    exit 1
fi

echo "======== SSH连接诊断报告 ========"
echo "目标主机: $TARGET_HOST"
echo "端口: $TARGET_PORT"
echo "用户: $TARGET_USER"
echo "诊断时间: $(date)"
echo

# 1. 网络连通性测试
echo "=== 网络连通性测试 ==="
if ping -c 3 -W 2 "$TARGET_HOST" >/dev/null 2>&1; then
    echo "✓ 主机可达"
else
    echo "❌ 主机不可达"
fi

# 2. 端口连通性测试
echo "=== 端口连通性测试 ==="
if nc -z -w 5 "$TARGET_HOST" "$TARGET_PORT" 2>/dev/null; then
    echo "✓ 端口 $TARGET_PORT 开放"
else
    echo "❌ 端口 $TARGET_PORT 不可达"
fi

# 3. SSH服务检测
echo "=== SSH服务检测 ==="
SSH_BANNER=$(timeout 5 telnet "$TARGET_HOST" "$TARGET_PORT" 2>/dev/null | grep SSH)
if [ -n "$SSH_BANNER" ]; then
    echo "✓ SSH服务正在运行: $SSH_BANNER"
else
    echo "❌ 未检测到SSH服务响应"
fi

# 4. 本地SSH配置检查
echo "=== 本地SSH配置检查 ==="
if [ -f ~/.ssh/id_rsa ]; then
    echo "✓ 找到RSA私钥"
    KEY_PERMS=$(stat -c %a ~/.ssh/id_rsa)
    if [ "$KEY_PERMS" = "600" ]; then
        echo "✓ 私钥权限正确"
    else
        echo "⚠️  私钥权限不正确: $KEY_PERMS (应该是600)"
    fi
else
    echo "❌ 未找到RSA私钥"
fi

if [ -f ~/.ssh/config ]; then
    echo "✓ 找到SSH客户端配置文件"
else
    echo "ℹ️  未找到SSH客户端配置文件"
fi

# 5. 尝试连接测试
echo "=== 连接测试 ==="
echo "尝试连接 $TARGET_USER@$TARGET_HOST:$TARGET_PORT..."

# 尝试密钥认证
if timeout 10 ssh -o BatchMode=yes -o ConnectTimeout=5 -p "$TARGET_PORT" "$TARGET_USER@$TARGET_HOST" echo "Key auth test" 2>/dev/null; then
    echo "✓ 密钥认证可用"
else
    echo "❌ 密钥认证失败"
fi

# 6. 建议操作
echo "=== 建议操作 ==="
echo "1. 详细连接测试: ssh -vvv -p $TARGET_PORT $TARGET_USER@$TARGET_HOST"
echo "2. 检查服务器SSH日志: sudo tail -f /var/log/auth.log"
echo "3. 检查防火墙设置: sudo iptables -L | grep ssh"
echo "4. 生成SSH密钥: ssh-keygen -t rsa -b 4096"
echo "5. 复制公钥: ssh-copy-id -p $TARGET_PORT $TARGET_USER@$TARGET_HOST"

SSH自动修复脚本

#!/bin/bash
# ssh_auto_fix.sh

echo "SSH自动修复脚本"
echo "=================="

# 1. 检查SSH服务状态
if ! systemctl is-active --quiet sshd; then
    echo "SSH服务未运行,尝试启动..."
    sudo systemctl start sshd
    if systemctl is-active --quiet sshd; then
        echo "✓ SSH服务启动成功"
    else
        echo "❌ SSH服务启动失败"
        echo "检查配置: sudo sshd -t"
        exit 1
    fi
else
    echo "✓ SSH服务正在运行"
fi

# 2. 检查SSH配置
echo "检查SSH配置..."
if sudo sshd -t; then
    echo "✓ SSH配置正确"
else
    echo "❌ SSH配置有错误,请检查 /etc/ssh/sshd_config"
    exit 1
fi

# 3. 修复SSH目录权限
echo "修复SSH目录权限..."
if [ -d ~/.ssh ]; then
    chmod 700 ~/.ssh
    find ~/.ssh -name "authorized_keys" -exec chmod 600 {} \;
    find ~/.ssh -name "id_rsa" -exec chmod 600 {} \;
    find ~/.ssh -name "*.pub" -exec chmod 644 {} \;
    echo "✓ SSH目录权限已修复"
else
    mkdir -p ~/.ssh
    chmod 700 ~/.ssh
    echo "✓ 创建SSH目录"
fi

# 4. 检查防火墙
echo "检查防火墙设置..."
if command -v firewall-cmd &> /dev/null; then
    if ! sudo firewall-cmd --list-services | grep -q ssh; then
        echo "添加SSH服务到防火墙..."
        sudo firewall-cmd --add-service=ssh --permanent
        sudo firewall-cmd --reload
        echo "✓ 防火墙规则已添加"
    else
        echo "✓ 防火墙已允许SSH"
    fi
elif command -v ufw &> /dev/null; then
    if ! sudo ufw status | grep -q "22/tcp"; then
        echo "添加SSH端口到ufw..."
        sudo ufw allow ssh
        echo "✓ UFW规则已添加"
    else
        echo "✓ UFW已允许SSH"
    fi
fi

# 5. 生成SSH密钥(如果不存在)
if [ ! -f ~/.ssh/id_rsa ]; then
    echo "生成SSH密钥对..."
    ssh-keygen -t rsa -b 4096 -f ~/.ssh/id_rsa -N ""
    echo "✓ SSH密钥对已生成"
else
    echo "✓ SSH密钥已存在"
fi

echo "SSH自动修复完成!"
echo "如果仍有问题,请使用: ssh -vvv user@hostname 进行详细诊断"

📊 SSH安全最佳实践

1. 安全配置

# 编辑SSH配置
sudo vim /etc/ssh/sshd_config

# 推荐安全配置
Port 2222                          # 更改默认端口
Protocol 2                         # 使用SSH协议版本2
PermitRootLogin no                  # 禁止root直接登录
PasswordAuthentication no           # 禁用密码认证(使用密钥)
PubkeyAuthentication yes            # 启用密钥认证
MaxAuthTries 3                      # 限制认证尝试次数
ClientAliveInterval 600             # 客户端心跳间隔
ClientAliveCountMax 3               # 最大心跳失败次数
AllowUsers user1 user2              # 限制允许登录的用户
DenyUsers baduser                   # 禁止特定用户登录

2. 密钥管理

# 生成强密钥
ssh-keygen -t ed25519 -a 100 -C "your_email@example.com"
ssh-keygen -t rsa -b 4096 -a 100 -C "your_email@example.com"

# 使用SSH Agent
ssh-agent bash
ssh-add ~/.ssh/id_rsa

# 配置SSH客户端
vim ~/.ssh/config

Host production-server
    HostName prod.example.com
    Port 2222
    User deploy
    IdentityFile ~/.ssh/prod_key
    IdentitiesOnly yes

3. 监控和日志

# 实时监控SSH登录
sudo tail -f /var/log/auth.log | grep sshd

# SSH登录统计
grep "Accepted" /var/log/auth.log | awk '{print $1,$2,$3,$9,$11}' | sort | uniq -c

# 失败登录尝试
grep "Failed password" /var/log/auth.log | awk '{print $11}' | sort | uniq -c | sort -nr

🚨 应急处理

SSH服务完全不可用时

  1. 使用控制台访问

    # 通过物理控制台或VNC访问系统
    # 检查SSH服务状态
    sudo systemctl status sshd
    sudo journalctl -u sshd -n 50
    
  2. 重置SSH配置

    # 恢复默认配置
    sudo cp /etc/ssh/sshd_config.default /etc/ssh/sshd_config
    sudo systemctl restart sshd
    
  3. 紧急网络访问

    # 临时开启telnet(极不安全,仅应急使用)
    sudo apt install telnetd    # Ubuntu/Debian
    sudo systemctl start telnet
    

📚 相关工具

  • ssh - SSH客户端
  • scp - 安全文件复制
  • sftp - 安全文件传输
  • ssh-keygen - 密钥生成工具
  • ssh-copy-id - 公钥复制工具
  • fail2ban - 自动防护工具

通过系统的诊断和正确的配置,可以解决大多数SSH连接问题,确保安全可靠的远程访问。


powered by Gitbook© 2025 编外计划 | 最后修改: 2025-07-28 12:47:16

results matching ""

    No results matching ""