结论:服务器无法连接要按「网络层 → 主机层 → 服务层 → 认证层」四层由外向内排查:先用 ping 与 mtr 确认网络可达,再确认主机存活与负载,然后用 nc -zv IP 端口 与 ss -lntup 确认端口是否在监听、监听地址是否为 0.0.0.0,最后核对凭据与白名单。其中「连接超时」多半是防火墙或安全组丢包,「连接被拒」是端口没有进程监听,两者切勿混淆。
几乎所有"服务器连不上"的工单,本质都是同一个问题:数据包从客户端走到应用进程,中间有四个环节可能断掉。新手最常见的做法是反复重试 SSH、重启服务、甚至直接重启服务器,既没定位问题又破坏了现场。本文给出一套与具体协议无关的四层模型,无论你连的是 SSH(22)、RDP(3389)、HTTP(80/443)、MySQL(3306)还是 Redis(6379),排查路径完全一致。
先建立四层模型:网络层、主机层、服务层、认证层
结论:把"连不上"拆成四层,每层只回答一个问题,逐层排除就能在 5 分钟内定位 90% 的故障。这个模型的价值在于:每一层都有明确的"通过/不通过"判据,不需要靠猜。
| 层级 | 要回答的问题 | 关键命令 | 通过判据 | 不通过时的高概率成因 |
|---|---|---|---|---|
| 网络层 | 客户端到主机的 IP 通路通吗? | ping -c 4 IP、mtr -rw IP、traceroute IP | ping 有回包、mtr 无丢包节点 | 安全组拦截、路由/网关故障、运营商线路、DNS 解析错 |
| 主机层 | 主机本身活着吗、资源正常吗? | 云控制台状态、uptime、dmesg、df -h | 控制台显示运行中、负载正常、磁盘未满 | 宕机、内核 panic、OOM、磁盘满、CPU 打满 |
| 服务层 | 目标端口有进程在监听吗?监听在哪个地址? | ss -lntup、nc -zv IP 端口、nmap -Pn -p 端口 IP | ss 能看到 LISTEN 且外部 nc 返回 succeeded | 服务未启动、监听 127.0.0.1、系统防火墙 DROP、进程崩溃 |
| 认证层 | 凭据正确吗、有权限吗、被拉黑了吗? | journalctl -u 服务、/var/log/secure、服务端日志 | 服务端日志显示认证成功 | 密码/密钥错误、密钥权限 600、IP 被 fail2ban 封、账号锁定、DB 用户 host 授权不足 |
四层之外还有一个常被忽略的前提:必须从外部测试。在服务器本机执行 curl http://127.0.0.1:8080 通,只说明服务进程活着,不能证明外部能连。真正的验证必须换一台机器,或者用手机热点、在线端口扫描工具从公网发起。
第一层:网络层排查——ping、mtr 与 DNS
结论:网络层先用 ping 判断可达性,用 mtr 定位丢包发生在哪一跳,用 dig/nslookup 排除域名解析错误。这一层不通,后面三层都不用看。
# 1)基本可达性(注意:部分云主机禁 ICMP,ping 不通不代表端口不通)
ping -c 4 203.0.113.10
# 2)定位丢包节点(-r 报告模式,-w 宽输出,-n 不反解域名)
mtr -rwn -c 100 203.0.113.10
# 3)路由追踪(TCP 模式更贴近真实业务,可绕过 ICMP 封锁)
traceroute -T -p 443 203.0.113.10
# 4)域名解析是否正确(连域名不通时必查)
dig +short example.com A
nslookup example.com
dig example.com @223.5.5.5 +short
# 5)确认本机出口与默认网关
ip route show
ip addr show读结果的三个要点:
- ping 通但端口不通 → 网络层没问题,直接跳到服务层。云主机禁 ICMP 的情况很常见,此时 ping 全丢也属正常,应以
nc -zv为准。 - mtr 在某一跳开始 100% 丢包且后续全丢 → 问题出在该跳设备(通常是边界防火墙或运营商链路),需联系机房或云厂商。
- dig 返回的 IP 与实际服务器 IP 不一致 → DNS 问题。常见于刚换了服务器 IP、CDN 未刷新、本地 hosts 文件残留,可先用 IP 直连验证,再处理解析。
第二层:主机层排查——主机活着吗、资源够吗
结论:网络层通但连不上,第二步要确认主机是否真的在运行、是否有资源耗尽。这一层的排查入口通常是云控制台或带外管理,因为连不上时你已经进不去系统了。
需要确认的四件事:
- 实例状态:云控制台看是「运行中」还是「已停止」。物理机看 IPMI/iDRAC/iLO 的电源状态。
- 是否卡死而非关机:控制台显示运行中但无响应,通常是 CPU 打满、OOM 后关键进程被杀、或文件系统只读。用控制台 VNC 登录查看屏幕是否有内核 panic 信息。
- 磁盘是否写满:
df -h与df -i。根分区 100% 会导致 SSH 登录直接失败,这是非常高频但极易被忽略的成因。 - 是否被 OOM Killer 杀了进程:
dmesg | grep -i -E 'oom|killed process',常见于内存不足时 sshd、mysqld 被优先杀掉。
# 通过控制台 VNC / IPMI 登录后执行
uptime # 1/5/15 分钟负载
free -m # 内存与 swap
df -h && df -i # 磁盘容量与 inode
dmesg -T | grep -iE 'oom|killed|panic|read-only' | tail -20
journalctl -p err -b --no-pager | tail -30
last reboot | head -3 # 是否有非计划重启第三层:服务层排查——端口有没有在监听、监听在哪
结论:服务层是"服务器无法连接"最高发的故障层,核心命令是 ss -lntup 与 nc -zv。这一层要区分三种不同的失败现象,它们指向完全不同的成因。
| 客户端现象 | 含义 | 高概率成因 | 处理方向 |
|---|---|---|---|
Connection timed out(超时) | SYN 包发出后无任何回应 | 防火墙 DROP、云安全组未放行、路由不可达 | 查安全组与 iptables/ufw/firewalld |
Connection refused(被拒) | 收到 RST,主机在线但端口无进程 | 服务未启动、端口写错、监听在 127.0.0.1 | 查 ss -lntup 与监听地址 |
No route to host | 主机不可达或 ICMP 管理不可达 | 主机宕机、本机路由表错误 | 回到主机层 |
| 能建立连接但立即断开 | 三次握手成功,应用层主动关闭 | 协议不匹配、TLS 握手失败、认证前置拒绝 | 查服务端日志 |
服务端自查与外部验证:
# 服务端:看端口是否监听、监听在哪个地址、哪个进程占用
sudo ss -lntup
sudo ss -lntup | grep -E ':22|:80|:443|:3306|:3389'
# 等价的老写法
sudo netstat -tlnp
sudo lsof -i :3306
# 确认服务进程状态
systemctl status sshd nginx mysqld --no-pager
systemctl --failed
# 客户端(换一台机器):从外部探测 TCP 端口
nc -zv -w 3 203.0.113.10 22
nc -zv -w 3 203.0.113.10 3306
# UDP 端口需显式指定 -u(如 DNS 53、NTP 123)
nc -zv -u -w 3 10.0.10.11 123
# HTTP 类服务用 curl 看详细握手过程
curl -v http://203.0.113.10:8080/
curl -sv https://example.com/ -o /dev/null
# 只看连通性与耗时
curl -s -o /dev/null -w "HTTP=%{http_code} 连接=%{time_connect}s 总耗时=%{time_total}s\n" \
--connect-timeout 5 https://example.com/
# 端口扫描(确认多个端口状态)
nmap -Pn -p 22,80,443,3306 203.0.113.10监听地址 0.0.0.0 与 127.0.0.1 的差异(最经典的新手坑)
结论:127.0.0.1:8080 只有本机能连,0.0.0.0:8080 才允许外部连接,这是"本机 curl 通、远程连不上"的头号原因。ss -lntup 输出的 Local Address:Port 列就是要看的地方。
| 监听地址 | 可连接的来源 | 典型写法 | 适用场景 |
|---|---|---|---|
127.0.0.1:8080 | 仅本机 | Nginx listen 127.0.0.1:8080;MySQL bind-address=127.0.0.1 | 只允许本机反代/本地访问,最安全 |
0.0.0.0:8080 | 所有网卡、所有来源 | Nginx listen 8080;listen *:8080 | 需要对外提供服务 |
10.0.10.5:8080 | 仅该网卡所在网段 | listen 10.0.10.5:8080 | 只暴露内网网卡,公网不通 |
:::8080 / [::]:8080 | IPv6 全部地址 | listen [::]:8080 | IPv6 环境;注意 IPv4 映射需 ipv6only=off |
各服务的配置位置:
- Nginx:
server { listen 80; },改为listen 0.0.0.0:80;或确认没有被listen 127.0.0.1:80限制。 - MySQL/MariaDB:
/etc/my.cnf的[mysqld] bind-address = 0.0.0.0(默认多为 127.0.0.1)。 - Redis:
redis.conf的bind 0.0.0.0与protected-mode no,缺一不可。 - Java/Python 应用:Spring Boot 的
server.address=0.0.0.0;Python 的app.run(host='0.0.0.0'),默认常是 127.0.0.1。 - MongoDB:
net.bindIp: 0.0.0.0。
云安全组与系统防火墙是两层,必须都放行
结论:云服务器有「云平台安全组」与「操作系统内防火墙」两层过滤,任一层不放行都连不上,两者必须分别检查。这是云服务器区别于物理机的最大不同,也是"端口明明开了却连不上"的最常见解释。
# firewalld(RHEL / Rocky / AlmaLinux / openEuler)
sudo firewall-cmd --state
sudo firewall-cmd --list-all
sudo firewall-cmd --add-port=3306/tcp --permanent && sudo firewall-cmd --reload
# ufw(Ubuntu / Debian)
sudo ufw status verbose
sudo ufw allow 3306/tcp
# iptables / nftables 直查(看是否有 DROP/REJECT)
sudo iptables -L -n --line-numbers | grep -E 'DROP|REJECT'
sudo nft list ruleset排查顺序建议:先在云平台控制台临时把安全组改成「允许全部」做验证测试,若此时能连上,说明是安全组问题,改回去逐条加规则;若仍连不上,再回到系统防火墙与监听地址。规则放通后记得限制来源 IP,例如 MySQL 3306 只允许应用服务器网段,不要对 0.0.0.0/0 开放。
第四层:认证层排查——凭据、权限与黑名单
结论:端口通但登不进去,问题在认证层,此时必须看服务端日志而不是客户端报错。客户端通常只给一句 "Permission denied",真正的拒绝原因写在服务端。
常见成因与对应日志:
| 现象 | 高概率成因 | 排查命令/位置 |
|---|---|---|
| SSH 密码正确却拒绝 | PermitRootLogin no、PasswordAuthentication no | /etc/ssh/sshd_config、journalctl -u sshd |
| SSH 密钥登录失败 | 私钥权限非 600、~/.ssh 非 700、authorized_keys 属主错误 | chmod 600 ~/.ssh/id_rsa;chmod 700 ~/.ssh |
| SSH 连上立即断开 | fail2ban/denyhosts 封 IP、MaxStartups 限制 | fail2ban-client status sshd;/etc/hosts.deny |
| 账号无法登录 | 账号锁定或密码过期 | passwd -S 用户名、chage -l 用户名、faillog -u 用户名 |
MySQL Access denied | 用户 host 授权不含客户端 IP(如只有 'app'@'localhost') | SELECT user,host FROM mysql.user; |
Redis NOAUTH | 未配置 requirepass 或未发送密码 | redis-cli -a 密码 ping |
| RDP 提示"没有权限" | 用户不在 Remote Desktop Users 组、NLA 限制 | 本地用户和组、系统属性远程设置 |
| HTTP 401/403 | 鉴权中间件、IP 白名单、Referer 校验 | Nginx access log 与 error log |
# SSH 服务端实时日志(客户端连接时观察)
sudo journalctl -u sshd -f
sudo tail -f /var/log/secure # RHEL 系
sudo tail -f /var/log/auth.log # Debian 系
# 客户端输出详细握手过程,看卡在哪一步
ssh -vvv user@203.0.113.10 2>&1 | tail -40
# 密钥权限修正(这一步能解决大量"密钥登录失败")
chmod 700 ~/.ssh && chmod 600 ~/.ssh/id_rsa && chmod 600 ~/.ssh/authorized_keys
chown -R $USER:$USER ~/.ssh
# 检查是否被 fail2ban 封禁
sudo fail2ban-client status sshd
sudo iptables -L f2b-sshd -n 2>/dev/null
# MySQL 用户授权检查
mysql -e "SELECT user,host,plugin FROM mysql.user;"按现象反推:一张决策树对照表
结论:拿着客户端的报错原文,对照下表可以直接跳到最可能的成因,省去逐层排查的时间。这张表建议收藏为运维速查卡。
| 客户端报错原文 | 最可能层级 | 最可能成因 | 下一步动作 |
|---|---|---|---|
Connection timed out | 服务层/网络层 | 安全组或防火墙 DROP | 查云平台安全组 → 查 firewalld/ufw → nc -zv 复测 |
Connection refused | 服务层 | 服务未启动或监听 127.0.0.1 | ss -lntup 看监听地址 → systemctl start → 改 bind 地址 |
No route to host | 网络层/主机层 | 主机宕机或路由缺失 | 查控制台实例状态 → ip route → 联系机房 |
Network is unreachable | 网络层 | 本机无可用路由/网卡 down | ip link、ip route、检查 VPN |
Permission denied (publickey) | 认证层 | 密钥不匹配或权限错误 | ssh -vvv → 检查 authorized_keys 与权限 |
Access denied for user | 认证层 | DB 用户 host 授权不足或密码错 | SELECT user,host FROM mysql.user |
Connection reset by peer | 服务层 | 进程崩溃或协议不匹配 | 查服务日志与 dmesg OOM 记录 |
SSL handshake failed | 服务层 | 证书过期或协议/套件不匹配 | openssl s_client -connect IP:443 |
| 时好时坏、间歇性失败 | 网络层/主机层 | 丢包、带宽打满、连接数耗尽 | mtr 长测、ss -s 看连接数、查带宽监控 |
| 本机通、远程不通 | 服务层 | 监听 127.0.0.1 或防火墙 | 对比 ss -lntup 的 Local Address 列 |
四种典型连接的专项补充
结论:四层模型通用,但每种协议在认证层有自己的特殊检查项,记住下面四条能少走弯路。
- SSH(22):确认
sshd在跑且Port没被改;确认/etc/ssh/sshd_config里没有AllowUsers排除你的账号;确认客户端与服务端的 OpenSSH 版本兼容(新版本默认禁用 ssh-rsa 算法)。 - RDP(3389):确认「Remote Desktop Services」服务在运行;确认防火墙放行 TCP 3389 与 UDP 3389(UDP 用于提速,缺失会变慢但通常仍能连);确认用户属于 Remote Desktop Users 组,且未开启「仅允许 NLA」而客户端不支持。
- HTTP/HTTPS(80/443):确认 Nginx 配置里
server_name匹配、且该 server 块是default_server;确认没有把 HTTP 请求 301 到一个无法访问的域名;HTTPS 还要确认证书未过期。 - 数据库(3306/5432/6379):确认
bind-address与用户 host 授权;确认max_connections未打满(打满时表现为能连上但报错 "Too many connections");确认 VPC/内网互通,跨账号、跨地域的数据库默认不互通。
企业QQ咨询




