网站打不开、SSH 连不上、后台突然变慢,很多站长第一反应就是重启服务、重启服务器,一通操作下来发现没用,问题还在。其实网络故障是有规律可循的,从物理链路到应用层一层层排查,配合对应的工具,几分钟就能定位到问题出在哪一层。这篇文章按照"从下往上"的排查思路,把 ping、traceroute、ss、dig、curl、tcpdump 这几个工具的用法和判断标准串起来,最后用一个完整的排查案例收尾,让你下次遇到网络故障不再瞎折腾。
一、网络排查的分层思路
一次网络请求要经过物理链路、网络层(IP 寻址和路由)、传输层(TCP/UDP 端口)、应用层(HTTP、SSH 等协议),故障可能出在任意一层。排查的原则是自下而上:先确认链路通不通,再看路由通不通,然后看端口有没有监听、服务有没有响应,最后才轮到应用本身。每层都有对应的工具:ping 测链路和网络层,traceroute/mtr 测路由,ss/netstat 看端口和连接状态,dig/nslookup 查 DNS,curl 测 HTTP 应用层,tcpdump 抓包看传输层细节。按顺序用下来,问题在哪一层一目了然。
二、ping:先确认基本连通性
ping 是最基础的连通性测试,发送 ICMP 回显请求,看目标是否响应以及响应延迟:
ping -c 4 1.2.3.4-c 4 表示发送 4 个包。看两个指标:丢包率和延迟。100% 丢包且全部 timeout,说明网络不通,或者对方禁了 ICMP——很多服务器出于安全考虑设置了 icmp_echo_ignore_all=1,ping 不通不代表服务不通,需要继续用后面的工具确认;延迟忽高忽低,说明链路拥塞或跨运营商线路质量差。ping 还有一个高级用法:测 MTU。发送不允许分片的大包,如果报 fragmentation needed,说明链路上某个设备的 MTU 小于你的包大小,会导致大包丢、小包通的现象:
ping -s 1472 -M do 1.2.3.4ping 通了,说明网络层没问题,接着用 traceroute 看路由。
三、traceroute / mtr:定位卡在哪一跳
ping 只能告诉你通不通,traceroute 能告诉你数据包经过了哪些节点、卡在哪一跳:
traceroute -n 1.2.3.4-n 参数直接显示 IP,不解析域名,速度快很多。输出里每一行是一跳,三列是三次探测的延迟。看到 * * * 不要慌,很多骨干节点禁用了 ICMP 回显,显示星号不代表断线,看下一跳是否正常就能判断。更推荐用 mtr,它把 traceroute 和 ping 结合,持续探测并统计每一跳的丢包率:
mtr -n 1.2.3.4判断标准:如果中间某几跳丢包,但最后一跳正常,说明丢包的是路由器策略(路由器只转发不回应,丢包率不代表真实链路质量),不用管;如果最后一跳持续高丢包,那才是目标服务器或目标机房的问题;如果中途某跳开始丢包,之后所有跳都丢,说明问题出在那一段链路上。个人站长遇到"部分地区用户打不开网站"的反馈,自己服务器上 traceroute 一切正常,多半是用户到服务器之间的跨网链路问题(电信、联通、移动之间的互联互通瓶颈),这种问题通常只能靠换线路或上 CDN 缓解。
四、ss:端口与服务状态
网络通、路由通,接下来确认服务器上的服务有没有在监听。ss 是 netstat 的现代替代品,输出更清晰、速度更快:
ss -lntp # 查看所有监听的 TCP 端口及对应进程
ss -ant # 查看所有 TCP 连接及状态
ss -s # 汇总统计部分老系统还没有 ss 命令,可以用 netstat 替代,参数基本对应:netstat -lntp 看监听端口,netstat -ant 看连接状态,老命令输出更啰嗦但信息一致。另外,如果 ss -ant 里看到 TIME_WAIT 状态堆积到上万,说明短连接创建太频繁,可以通过调整内核参数缓解,在 /etc/sysctl.conf 里设置 net.ipv4.tcp_fin_timeout = 30 和 net.ipv4.tcp_tw_reuse = 1,然后执行 sysctl -p 生效。正常服务运行中少量 TIME_WAIT 是正常现象,不必过度紧张。
网站打不开时,先看 80/443 端口有没有 Nginx 在监听,MySQL 的 3306、SSH 的 22 是否正常。如果端口没有 LISTEN,说明服务没起来,去查服务状态;如果端口在监听但连不上,那就是防火墙或安全组的问题。ss -ant 里重点看两类异常状态:SYN_RECV 大量堆积,说明有人发大量半连接请求(SYN Flood 攻击的典型特征,TCP 连接永远停留在第一次握手);CLOSE_WAIT 大量堆积,说明对端关闭了连接,但程序没有正确关闭 socket,通常是代码 bug,连接资源被慢慢耗尽。
五、dig:排查 DNS 解析
很多"网站打不开"其实是 DNS 的问题,用户输入的域名解析到了一个错误或者过期的 IP。用 dig 检查:
dig zz1984.com +short # 快速看 A 记录解析结果
dig @8.8.8.8 zz1984.com # 指定 DNS 服务器查询,绕过本地缓存判断方法:解析出的 IP 是不是你服务器的 IP?用 @8.8.8.8 查出来的结果和本地查出来的结果不一致,说明本地或本地运营商的 DNS 缓存了旧记录,等 TTL 过期或换 DNS 即可。还有一种常见情况:新域名解析没生效,检查域名商那边 A 记录是否添加、TTL 是不是设得太长(上线前先设 600 秒,稳定后再调大)。
六、curl:应用层的快速验证
网络层、传输层、DNS 都正常,就该测应用层了。curl 是 HTTP 排查的瑞士军刀:
curl -I https://zz1984.com # 只看响应头,快速看状态码
curl -o /dev/null -s -w "连接:%{time_connect} TTFB:%{time_starttransfer} 总耗时:%{time_total}\n" https://zz1984.com第一条命令看状态码:200 正常、301/302 是跳转、403 是权限问题、502/504 是后端故障。第二条命令把耗时拆解开:time_connect 是 TCP 建连耗时,大说明网络或防火墙问题;time_starttransfer 是从发请求到收到第一个字节的耗时(TTFB),大说明服务器处理慢,要去查 PHP-FPM 和数据库;time_total 是总耗时。还有一个很实用的技巧:绕过 DNS 直接测本机服务:
curl -H "Host: zz1984.com" http://127.0.0.1/在服务器本机用 Host 头伪装域名访问 127.0.0.1,如果这样能通而公网访问不通,问题就锁定在网络层或防火墙,而不是服务本身。
七、tcpdump:抓包看传输层真相
前面的工具都是"间接推断",tcpdump 直接看数据包,是最后一锤定音的工具。几个最常用的组合:
tcpdump -i eth0 -n port 80 # 抓 80 端口流量
tcpdump -i any -n host 1.2.3.4 # 抓与某 IP 的全部通信
tcpdump -i eth0 -nn -c 100 'tcp port 443 and tcp[tcpflags] & tcp-syn != 0' # 只看 SYN 包抓包要 root 权限,先加 -c 限制数量避免刷屏。看 TCP 三次握手:客户端发 SYN,服务器回 SYN-ACK,客户端回 ACK。如果只看到客户端发 SYN 而服务器没有回应,说明请求被防火墙 DROP 了;如果服务器直接回 RST,说明端口没有服务在监听;如果看到同一序列号的包反复出现并标记 retransmission,说明网络丢包严重,重传导致连接慢。最后一个命令只过滤 SYN 包,配合 -c 统计数量,可以快速判断是不是有人在扫描端口或发动 SYN 攻击。
八、一个完整的排查案例
把上面的工具串起来看一个真实场景:早上起来发现网站打不开,SSH 也连不上。第一步,ping 服务器 IP:通了,延迟 20ms 无丢包,说明链路和网络层正常;第二步,尝试 SSH:连不上,问题不在 Web 服务,而是整机的网络或防火墙层面;第三步,登录云控制台用 VNC 进入服务器,发现 Nginx、sshd 进程都在,ss -lntp 显示 22 和 443 都在监听,说明服务本身没挂;第四步,检查云厂商安全组和服务器 iptables:昨天刚改过安全组,把 22 端口的放行规则误删了,重新加回规则,网站和 SSH 立刻恢复。整个排查过程不到十分钟,没有重启任何服务。这个案例的关键在于:服务正常、监听正常,问题必然在防火墙或安全组,方向对了,问题就藏不住。
九、总结
网络排查的核心不是背命令,而是建立分层思维:ping 测链路,traceroute 测路由,ss 测端口,dig 测 DNS,curl 测应用,tcpdump 看真相,一层层排除,永远比瞎重启高效。建议把这几个命令记熟,遇到故障按顺序过一遍,大多数网络问题都能在几分钟内定位。另外,日常把服务器的防火墙规则、安全组变更记录下来,出问题时先回顾"最近改过什么",往往就是最快的答案。