📖 前言
在管理云服务器(ECS/CVM/EC2)时,最令人崩溃的瞬间莫过于输入 SSH 命令后,屏幕上长时间的静止,或者那行冷冰冰的 Connection timed out。
造成无法登录的原因千奇百怪,可能是网络不通、防火墙拦截、配置错误,甚至是服务器已经被"挤爆"了。本文将按照数据包的访问链路(客户端 -> 网络层 -> 云安全层 -> 系统层 -> 应用层 -> 认证层),为您梳理一套逻辑严密、无死角的排查方案。
🗺️ 排查总览图:数据包的"闯关"之路

在开始动手前,请先理解 SSH 连接的闯关流程:
-
客户端发起:本地网络是否正常?IP 是否写对?
-
网络传输:能否 Ping 通?DNS 是否解析?
-
云端安防 :安全组放行了吗?
-
操作系统:服务器还活着吗?(负载/带宽)
-
服务监听:SSH 服务启动了吗?系统防火墙拦了吗?
-
身份认证:密码/密钥对不对?权限合规吗?
第 0 步:明确现象与类型
登录失败通常只有两类:
-
连不通(网络问题)
- 典型提示:
Connection timed out、No route to host、Network unreachable、Connection refused
- 典型提示:
-
连得通但认证失败(账号/密码/密钥问题)
- 典型提示:
Permission denied、Authentication failed、Public key rejected
- 典型提示:
下面按"连不通"和"连得通但登不上"都能覆盖的 全链路排查流程。
🛠️ 第一关:客户端与基础网络排查
现象:直接报错 Could not resolve hostname 或本地断网。
1. 检查连接三要素
最低级的错误往往最难发现。请再次核对:
-
IP 地址:公网 IP 是否变更?(云服务器重启后,若未绑定弹性公网IP,IP可能会变)。
-
端口号:默认是 22,但为了安全,很多公司会改为 10022 等非常用端口。
-
用户名:确认登录用户。
-
CentOS 默认:root
-
Ubuntu 默认:ubuntu
-
AWS Amazon Linux 默认:ec2-user
-
检查本地网络是否正常
✔ 测试 DNS
bash
nslookup www.baidu.com
若 DNS 不通 → 本地网络本身异常。
✔ 关闭代理 / VPN / 公司防火墙
很多公司阻断了 SSH 22 端口。
若在公司网络,用手机热点再试。
2. 测试物理连通性 (Ping)
打开本地终端(CMD 或 Terminal),执行:
ping <服务器公网IP>
-
通 (Reply from...) :说明物理线路没问题,问题出在端口或软件层。 -> 直接跳到第三关。
-
不通 (Request timed out) :说明路由中断、服务器关机或禁用了 ICMP 协议。 -> 继续第二关。
🚧 第二关:云端安防与端口排查
现象:Ping 通但 SSH 连不上,或者 Ping 不通且 SSH Connection timed out。
这是云服务器最特有的环节,90% 的"无法连接"都发生在这里。
1. 探测端口连通性
Ping 通不代表端口开。使用 telnet 或 tcping 测试 SSH 端口:
# 格式:telnet IP 端口
telnet 1.2.3.4 22
-
结果 A:Connected / 出现 SSH 版本号 -> 说明网络和端口完全正常,问题在身份认证 。 -> 跳到第六关。
-
结果 B:Connection refused -> 请求到了服务器,但被拒绝 。 -> 跳到第五关。
-
结果 C:Connection timed out / 无响应 -> 请求被丢弃 ,通常是防火墙或安全组问题。 -> 继续向下。
2. 检查"云安全组" (Security Group)
登录阿里云/腾讯云/AWS 控制台,找到该实例的安全组配置。
-
核心检查:入方向(Inbound)规则。
-
常见错误:
-
缺少允许 TCP 22 端口的规则。
-
授权对象(源IP)设置错误(例如只允许了公司 IP,而你在家里办公)。
-
-
解决方案:添加一条规则 协议:TCP,端口:22,源IP:0.0.0.0/0(排查后建议改为特定IP)。
3、检查云平台层面的路由/子网/网关
主要看:
-
子网是否有 正确的路由表 指向 互联网网关(IGW)
-
防火墙(如 AWS NACL、阿里云安全策略)是否允许出/入方向
-
弹性公网 IP 是否正确绑定
📉 第三关:服务器资源健康排查
现象:连接极慢,卡顿,或者提示 Time out,控制台监控显示数据异常。
如果网络层没问题,可能是服务器"病"了,无力响应你的请求。
1. 带宽利用率过高
-
原因:突发流量、被 DDoS 攻击、中了挖矿病毒、或者正在下载大文件占满带宽。
-
症状:SSH 连接非常卡,或者断断续续。
-
排查:查看云控制台的"网络监控"。
-
急救:在云控制台临时升级带宽,连上后使用 iftop 找出流量黑洞进程并杀掉。
2. 服务器高负载 (CPU/内存/IO)
-
原因:代码死循环、Java OOM(内存溢出)、磁盘读写堵塞。
-
症状:Ping 丢包严重,SSH 无法建立连接(因为系统无法 Fork 新进程)。
-
急救:此阶段 SSH 通常已失效,必须使用**云控制台 VNC(管理终端)**登录。
-
运行 top 命令查看 Load Average。
-
如果无法操作,只能在控制台执行强制重启。
-
🧱 第四关:系统内部防火墙排查
现象:telnet 提示 No route to host 或 Connection refused。
流量通过了云安全组,却被 Linux 操作系统自己的"门卫"拦下了。
1. 检查 iptables / Firewalld / UFW
通过 VNC 登录服务器检查:
# CentOS 7+
systemctl status firewalld
# Ubuntu
sudo ufw status
-
解决方案:
-
临时关闭测试:systemctl stop firewalld。
-
永久解决:添加放行规则。
codeBash
firewall-cmd --zone=public --add-port=22/tcp --permanent firewall-cmd --reload -
⚙️ 第五关:SSH 服务自身排查
现象:telnet 提示 Connection refused。
说明服务器网络通畅,防火墙也放行了,但是 22 端口没人听电话(SSH 服务挂了或配置错了)。
1. 检查 SSHD 服务状态
通过 VNC 登录执行:
systemctl status sshd
-
如果状态是 Inactive/Dead:尝试启动 systemctl start sshd。
-
如果启动失败:查看报错日志 journalctl -xe。通常是配置文件写错了。
2. 检查 SSH 配置文件
文件路径:/etc/ssh/sshd_config
-
Port:是否被修改为非 22 端口?
-
ListenAddress:是否绑定了错误的 IP?
-
AllowUsers:是否限制了特定用户登录?
🔑 第六关:认证与权限排查
现象:连接成功,弹出登录界面,但提示 Permission denied 或 Authentication failed。
这是最后一步,门开了,但你没有正确的钥匙。
1. 密码问题
-
密码错误:注意大小写、全角半角。
-
Root 被禁:检查配置文件中 PermitRootLogin 是否为 no。
-
只允许密钥:检查配置文件中 PasswordAuthentication 是否为 no。
2. 密钥权限问题 (Key-based Auth)
SSH 对密钥文件的权限要求极高,权限太大(如 777)会直接拒绝登录。
-
排查:检查服务器端 ~/.ssh/authorized_keys 的权限。
-
修复:
chmod 700 ~/.ssh chmod 600 ~/.ssh/authorized_keys chown -R root:root ~/.ssh # 或者是对应用户
3. 账户锁定 (PAM 安全机制)
如果多次输错密码,Linux 的 PAM 模块可能会锁定账户。
-
排查:查看日志 /var/log/secure 或 /var/log/auth.log。
-
解锁 (需 VNC):
pam_tally2 --user=root --reset
🟦 最终快速定位表(腾讯云 + CentOS 专用)
| 现象 | 排查节点 |
|---|---|
| timeout | 安全组 / ACL / 云防火墙 / 路由 |
| refused | sshd 未运行 / 防火墙拦截 / 端口错误 |
| Permission denied | 密码/密钥/权限问题 |
| 登录后卡住 | 高负载 / IO 问题 / 带宽耗尽 |
| 控制台能登录,SSH 不行 | 安全组/防火墙问题 |
| 任何方式都不行 | 系统级问题(磁盘满/内核 panic) |
🔵 最终:常见问题与对应节点(快速定位)
| 现象 | 可能问题节点 |
|---|---|
| Connection timed out | 客户端 → 云平台安全组 → 服务端防火墙 |
| Connection refused | 服务端无 sshd 监听 |
| Permission denied | 用户层 / 密钥 / 密码错误 |
| SSH 连接卡住后超时 | 带宽耗尽 / 服务器高负载 |
| 控制台可登录但 SSH 不行 | 网络策略层面问题(安全组/防火墙) |
| 任意方式都无法登录 | 系统崩溃 / 内核 panic / 文件系统只读等 |
自动化排障脚本
适用于腾讯云 CVM + CentOS 7.6 的 SSH 自动化排障脚本 ,只做"检查+报告",不会自动修改系统配置,方便你先看清问题再决定是否手动修复。
使用方式:
在腾讯云控制台用 VNC/管理终端 登录到这台服务器
将下面脚本保存为:
/root/tencent_cvm_ssh_diag.sh赋予执行权限:
chmod +x /root/tencent_cvm_ssh_diag.sh执行:
bash /root/tencent_cvm_ssh_diag.sh(建议用 root)
bash
#!/bin/bash
#
# Tencent Cloud CVM SSH Troubleshooting Script for CentOS 7.6
# 仅做检测与报告,不自动修改配置
#
########################
# 基础输出函数和颜色定义 #
########################
RED='\e[31m'
GREEN='\e[32m'
YELLOW='\e[33m'
BLUE='\e[34m'
NC='\e[0m' # No Color
title() {
echo -e "\n${BLUE}==================== $1 ====================${NC}\n"
}
ok() {
echo -e "${GREEN}[OK]${NC} $1"
}
warn() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
err() {
echo -e "${RED}[FAIL]${NC} $1"
}
info() {
echo -e "${BLUE}[INFO]${NC} $1"
}
require_root() {
if [ "$(id -u)" -ne 0 ]; then
err "请使用 root 用户运行本脚本(sudo 或切换到 root)。"
exit 1
fi
}
################
# 0. 基础信息 #
################
basic_info() {
title "0. 基础系统信息"
echo "主机名: $(hostname)"
echo "时间: $(date)"
echo -e "\n发行版信息:"
if [ -f /etc/centos-release ]; then
cat /etc/centos-release
else
cat /etc/os-release 2>/dev/null
fi
echo -e "\nIP 地址信息:"
ip addr show | awk '/inet / && $2 !~ /^127/ {print $1,$2,$NF}'
echo -e "\n最近开机信息:"
uptime
}
########################
# 1. sshd 服务与端口检查 #
########################
check_sshd_service() {
title "1. sshd 服务与端口检查"
if systemctl status sshd >/dev/null 2>&1; then
active_state=$(systemctl is-active sshd)
enable_state=$(systemctl is-enabled sshd 2>/dev/null)
if [ "$active_state" = "active" ]; then
ok "sshd 服务正在运行 (active)。"
else
err "sshd 服务未在运行 (状态: $active_state)。"
info "可尝试:systemctl restart sshd"
fi
if [ "$enable_state" = "enabled" ]; then
ok "sshd 服务已设置为开机自启 (enabled)。"
else
warn "sshd 服务未设置为开机自启 (状态: $enable_state)。"
info "如有需要可执行:systemctl enable sshd"
fi
else
err "未检测到 systemd 管理的 sshd 服务,请确认是否安装了 openssh-server。"
fi
echo -e "\n当前 sshd 监听端口:"
ss -lntp | grep -i sshd || {
warn "未从 ss 输出中检测到 sshd 监听端口,可能 sshd 未启动或监听在本地回环。"
}
echo -e "\n从配置文件中读取 Port(如有):"
if [ -f /etc/ssh/sshd_config ]; then
port_cfg=$(grep -Ei '^[[:space:]]*Port[[:space:]]+' /etc/ssh/sshd_config | awk '{print $2}' | tail -n1)
if [ -n "$port_cfg" ]; then
info "sshd_config 中设置的端口: $port_cfg"
else
info "sshd_config 未显式设置 Port,默认应为 22。"
fi
else
warn "/etc/ssh/sshd_config 不存在,请检查 openssh-server 是否正确安装。"
fi
echo -e "\n检测 sshd 配置语法:"
if command -v sshd >/dev/null 2>&1; then
if sshd -t >/dev/null 2>&1; then
ok "sshd 配置语法检查通过。"
else
err "sshd -t 配置语法检查失败,请查看上方输出或执行:sshd -t"
fi
else
warn "未找到 sshd 命令,可能未安装 openssh-server。"
fi
}
#################################
# 2. 防火墙 / SELinux / 安全策略 #
#################################
check_firewall_selinux() {
title "2. 防火墙 (firewalld / iptables) 与 SELinux"
if systemctl is-active firewalld >/dev/null 2>&1; then
ok "firewalld 正在运行。"
echo -e "\n当前 firewalld 配置:"
firewall-cmd --list-all || warn "firewall-cmd 执行失败。"
# 检查是否放行 ssh 服务或 22 端口
fw_ports=$(firewall-cmd --list-ports 2>/dev/null)
fw_services=$(firewall-cmd --list-services 2>/dev/null)
if echo "$fw_services" | grep -qw ssh || echo "$fw_ports" | grep -qE '\b22/tcp\b'; then
ok "firewalld 中已放行 ssh 服务或 22/tcp 端口。"
else
warn "firewalld 中未检测到 ssh 服务或 22/tcp 端口放行,外部可能无法通过默认端口访问 SSH。"
info "如需放行,可执行:firewall-cmd --permanent --add-service=ssh && firewall-cmd --reload"
fi
else
warn "firewalld 未在运行。若使用 iptables,请确认规则。"
if command -v iptables >/dev/null 2>&1; then
echo -e "\n当前 iptables 规则:"
iptables -L -n
fi
fi
echo -e "\nSELinux 状态:"
if command -v getenforce >/dev/null 2>&1; then
selinux_state=$(getenforce)
echo "SELinux: $selinux_state"
if [ "$selinux_state" = "Enforcing" ]; then
warn "SELinux 处于 Enforcing 状态,如有 SELinux 策略配置错误可能影响 sshd。"
info "可临时设置为 Permissive 测试:setenforce 0 (重启后会恢复)。"
fi
else
info "未检测到 getenforce 命令,可能未启用 SELinux。"
fi
}
###########################
# 3. 系统负载 / 磁盘 检查 #
###########################
check_system_resources() {
title "3. 系统资源情况 (CPU/内存/负载/磁盘)"
echo -e "uptime:"
uptime
echo -e "\nCPU/内存/Top 进程(前 5 个按 CPU 排序):"
ps aux --sort=-%cpu | head -n 6
echo -e "\n内存使用情况:"
free -m
echo -e "\n磁盘使用情况:"
df -h | sed -n '1,10p'
# 简单阈值提示
root_usage=$(df -h / | awk 'NR==2 {gsub("%","",$5); print $5}')
if [ "$root_usage" -ge 90 ]; then
err "/ 分区使用率为 ${root_usage}%,磁盘几乎已满,可能影响 sshd 及系统运行。"
elif [ "$root_usage" -ge 80 ]; then
warn "/ 分区使用率为 ${root_usage}%,建议尽快清理磁盘。"
else
ok "/ 分区使用率为 ${root_usage}%,看起来正常。"
fi
}
#########################
# 4. SSH 认证相关配置 #
#########################
check_ssh_auth() {
title "4. SSH 认证相关配置 (密码/密钥/Root 登录)"
if [ -f /etc/ssh/sshd_config ]; then
echo "关键配置项:"
egrep -i '^(Port|PasswordAuthentication|PubkeyAuthentication|PermitRootLogin|AllowUsers|DenyUsers|AllowGroups|DenyGroups)' /etc/ssh/sshd_config | sed 's/^/ /' || true
pass_auth=$(grep -Ei '^[[:space:]]*PasswordAuthentication[[:space:]]+' /etc/ssh/sshd_config | awk '{print $2}' | tail -n1)
if [ "$pass_auth" = "no" ]; then
warn "PasswordAuthentication=no,禁止了密码登录,仅允许密钥认证。"
elif [ "$pass_auth" = "yes" ] || [ -z "$pass_auth" ]; then
ok "允许密码登录(或使用默认行为),若密码正确应可登录。"
fi
pubkey_auth=$(grep -Ei '^[[:space:]]*PubkeyAuthentication[[:space:]]+' /etc/ssh/sshd_config | awk '{print $2}' | tail -n1)
if [ "$pubkey_auth" = "no" ]; then
warn "PubkeyAuthentication=no,禁用了密钥登录。"
fi
fi
echo -e "\n检查 root 账号状态:"
if id root >/dev/null 2>&1; then
passwd -S root 2>/dev/null || true
chage -l root 2>/dev/null | sed 's/^/ /' || true
fi
if command -v faillock >/dev/null 2>&1; then
echo -e "\n近期 root 登录失败统计(faillock):"
faillock --user root 2>/dev/null || echo " 无记录或未启用 faillock。"
fi
}
#########################
# 5. SSH 日志检查 #
#########################
check_ssh_logs() {
title "5. SSH 登录相关日志 (最近 50 行)"
log_file=""
if [ -f /var/log/secure ]; then
log_file="/var/log/secure"
elif [ -f /var/log/auth.log ]; then
log_file="/var/log/auth.log"
fi
if [ -n "$log_file" ]; then
echo "日志文件: $log_file"
echo -e "\n最近与 sshd 相关的 50 行:"
grep -i sshd "$log_file" | tail -n 50 || echo "无 sshd 相关日志。"
else
warn "未找到 /var/log/secure 或 /var/log/auth.log,无法检查 SSH 日志。"
fi
}
#########################
# 6. 腾讯云连通性简单测 #
#########################
check_tencent_network() {
title "6. 腾讯云网络连通性简单检测"
echo "尝试 ping 腾讯云镜像站(仅作参考,可被防火墙阻断):"
ping -c 3 mirrors.tencentyun.com >/dev/null 2>&1
if [ $? -eq 0 ]; then
ok "能 ping 通 mirrors.tencentyun.com,外网连通性看起来正常。"
else
warn "无法 ping mirrors.tencentyun.com(可能被防火墙禁 ICMP,仅供参考)。"
fi
echo -e "\n如需进一步排查网络,可尝试:"
echo " traceroute <你的运维公网IP> 或 mtr,配合本地测试一起看。"
}
#########################
# 主流程入口 #
#########################
main() {
require_root
basic_info
check_sshd_service
check_firewall_selinux
check_system_resources
check_ssh_auth
check_ssh_logs
check_tencent_network
title "排查完成"
echo -e "建议根据上面各小节中的 ${RED}[FAIL]${NC}/${YELLOW}[WARN]${NC} 项,逐条处理。\n"
echo "如你愿意,可以把脚本输出整体复制给我,我可以帮你做进一步分析和给出具体修改命令。"
}
main "$@"
🚑 终极杀手锏:VNC (管理终端)
如果以上所有 SSH 修复手段都失效,VNC 是你最后的救命稻草。
它不依赖 SSH 协议,模拟物理显示器连接。只要云服务器没彻底硬件损坏,你都能通过云厂商控制台的 "远程连接" / "VNC登录" 按钮进去,在系统内部进行上述的本地排查。
📝 总结 Checklist
遇到连不上 Linux,按此表逐一打钩:
IP/端口/账号 确认无误?
Ping 能通吗?(通则网络正常)
Telnet 22端口 通吗?(不通查安全组)
控制台监控 CPU/带宽 炸了吗?
VNC 进去看 sshd 活了吗?
权限 chmod 600 给了吗?
希望这篇指南能帮助你快速定位"失联"原因,让服务器乖乖听话!🚀