1. 服务访问异常排障:当Ping通但服务不可用时的深度解析
在Linux网络故障排查中,最令人困惑的场景之一就是:你能ping通远程主机,但关键的HTTP(80)、SSH(22)等服务却无法访问。这种情况通常意味着问题出在传输层(TCP/UDP)或应用层,而非底层的网络连通性。作为一名运维老兵,我处理过数百次这类问题,今天就把最实用的排查方法分享给大家。
1.1 核心排查工具:tcpdump的实战应用
tcpdump是Linux网络排查的瑞士军刀,但很多新手面对其复杂的输出望而却步。其实只要掌握几个关键场景的命令组合,就能快速定位问题:
bash复制# 基础抓包命令模板
tcpdump -nn -i [网卡名] [过滤条件]
这里的-nn表示不解析主机名和端口名(直接显示IP和端口号),-i指定监听的网卡(如ens33、eth0等)。过滤条件是我们排查不同问题的关键。
注意:执行tcpdump需要root权限,普通用户请使用sudo。如果不知道网卡名,可以用
ip a或ifconfig查看。
1.2 四大典型场景的针对性抓包策略
场景一:访问特定IP的所有服务都失败
bash复制tcpdump -nn -i ens33 host 10.0.0.12
这个命令会捕获所有与10.0.0.12的通信。关键要看TCP三次握手是否完成:
-
如果客户端发出了SYN包,但服务器没有回复SYN+ACK:
- 可能是服务器防火墙拦截了连接
- 也可能是目标服务根本没有启动
-
如果服务器回复了RST包:
- 这明确表示目标端口没有监听服务
- 需要检查服务是否启动,或者是否监听在正确端口
场景二:特定端口服务无法访问(如HTTP 80)
bash复制tcpdump -nn -i ens33 port 80
这个过滤条件只看80端口的流量。排查要点:
- 请求是否到达了服务器?
- 服务器是否有响应?
- 响应是否被中间设备拦截?
我曾经遇到过一个案例:客户端能发送SYN到服务器,服务器也回复了SYN+ACK,但客户端就是收不到。最后发现是客户端的本地防火墙静默丢弃了入站包。
场景三:ICMP通但TCP服务不通
bash复制tcpdump -nn -i ens33 host 10.0.0.12 and icmp
ICMP协议(ping使用的协议)和TCP协议走的路径可能不同。通过专门抓取ICMP包,可以分析:
- 是否有"目标不可达"类型的ICMP消息?
- 是否有"超时"消息?
- 这些消息来自哪一跳路由器?
这能帮助我们判断是路由问题还是防火墙拦截。
场景四:复杂问题需要离线分析
bash复制tcpdump -nn -i ens33 host 10.0.0.12 -w service_fail.pcap
对于复杂问题,保存抓包数据后用Wireshark分析更高效。Wireshark的图形界面能直观展示:
- 完整的TCP会话流程
- 各阶段的耗时
- 协议细节解码
专业提示:抓包文件可能会很大,可以加
-c 100参数限制只抓100个包,或者用更精确的过滤条件减少数据量。
1.3 抓包现象与根因的快速对照表
根据多年经验,我总结了以下常见现象与对应解决方案:
| 抓包现象 | 可能根因 | 解决方案 |
|---|---|---|
| 客户端没有发出SYN包 | 本地路由或防火墙拦截 | 检查本机iptables/ufw/firewalld规则,确认路由表(ip route)正确 |
| SYN发出但无SYN+ACK回复 | 目标防火墙拦截或服务未启动 | 1. 检查目标机防火墙规则 2. 确认目标服务正在监听( netstat -tulnp) |
| 收到SYN+ACK但客户端无ACK | 客户端网络或系统异常 | 1. 重启客户端网络服务 2. 检查客户端防火墙 3. 极端情况下重启系统 |
| 连接建立但立即收到RST | 服务进程崩溃或配置错误 | 检查服务日志,常见于PHP-FPM配置错误或Nginx监听地址设置错误 |
| 重复的SYN包无响应 | 中间设备丢包或MTU不匹配 | 1. 使用mtr检查路径丢包2. 调整MTU值( ifconfig eth0 mtu 1400) |
2. Linux网络排障的标准流程与实战口诀
2.1 系统化的排障方法论
经过无数次深夜故障排查,我总结出了一个高效的排障流程:
-
基础连通性测试:
- 单主机测试:
ping 目标IP - 批量测试:
fping -g 子网(如fping -g 192.168.1.0/24)
- 单主机测试:
-
路由追踪:
- 内网路由:
ip route show检查本地路由表 - 外网路径:
traceroute 目标IP或mtr 目标IP(更强大的实时监控工具)
- 内网路由:
-
服务层分析:
- 端口检测:
telnet 目标IP 端口或nc -zv 目标IP 端口 - 深度抓包:如前面介绍的tcpdump方法
- 端口检测:
2.2 运维老兵的排障口诀
为了方便记忆,我把这个流程浓缩为三句口诀:
-
先单后批:
- 单主机
ping测基本连通性 - 网段
fping快速扫描批量主机
- 单主机
-
先内后外:
- 内网查
ip route确认路由表正确 - 外网用
traceroute/mtr追踪故障跳点
- 内网查
-
三层通四层断:
- 网络层(ICMP)通但传输层(TCP)不通时
tcpdump抓包分析TCP握手过程
2.3 极简排障逻辑图
plaintext复制基础连通性(ping/fping)→ 网络层路由(traceroute/mtr)→ 服务层抓包(tcpdump)
↓ ↓ ↓
通不通 哪一跳故障 服务为何不通
3. 进阶技巧与实战经验分享
3.1 那些手册上不会告诉你的细节
-
关于tcpdump的时间戳:
- 默认时间戳精度不够,加
-tttt选项显示完整时间:bash复制
tcpdump -nn -tttt -i ens33 port 80 - 这对分析时序相关问题至关重要
- 默认时间戳精度不够,加
-
抓取特定方向的流量:
- 只抓取发送到目标的数据:
dst host 10.0.0.12 - 只抓取来自目标的数据:
src host 10.0.0.12
- 只抓取发送到目标的数据:
-
组合过滤条件:
bash复制tcpdump -nn -i ens33 "host 10.0.0.12 and (port 80 or port 443)"这个命令可以同时监控HTTP和HTTPS流量
3.2 PHP应用的特殊注意事项
当排查PHP应用(如WordPress、Laravel等)的网络问题时,还需要额外检查:
-
PHP-FPM配置:
- 确认监听地址和端口正确
- 检查进程是否正常运行:
systemctl status php-fpm
-
Nginx/Apache与PHP的通信:
- 对于Unix Socket连接,使用
socat工具检查:bash复制
socat - UNIX-CONNECT:/var/run/php-fpm.sock - 对于TCP连接,用
telnet 127.0.0.1 9000测试
- 对于Unix Socket连接,使用
-
慢日志分析:
- 启用PHP-FPM慢日志定位执行时间过长的脚本
- 在php-fpm.conf中设置:
ini复制slowlog = /var/log/php-fpm/slow.log request_slowlog_timeout = 5s
3.3 网络排障工具箱推荐
除了基本命令,这些工具也能大幅提升效率:
-
netcat (nc):
- 快速测试端口连通性:
bash复制
nc -zv 10.0.0.12 80
- 快速测试端口连通性:
-
nmap:
- 全面扫描目标开放端口:
bash复制
nmap -sS -p 1-65535 10.0.0.12
- 全面扫描目标开放端口:
-
ss:
- 比netstat更强大的套接字查看工具:
bash复制
ss -tulnp
- 比netstat更强大的套接字查看工具:
-
conntrack:
- 查看连接跟踪信息(对NAT环境特别有用):
bash复制
conntrack -L
- 查看连接跟踪信息(对NAT环境特别有用):
4. 经典案例复盘与经验总结
4.1 案例一:SYN_SENT但无响应
现象:客户端显示连接卡住,抓包显示只有SYN包发出。
排查过程:
- 确认目标IP能ping通
- 目标服务器
ss -tln显示端口在监听 - 目标服务器抓包发现SYN包未到达
- 中间防火墙发现DROP规则
解决方案:调整防火墙规则,放行相关端口。
4.2 案例二:连接随机中断
现象:连接建立后,随机出现连接重置(RST)。
排查过程:
- 抓包发现RST包来自服务器
- 检查服务器日志发现PHP进程频繁崩溃
- 内存监控显示OOM Killer在终止进程
解决方案:优化PHP内存配置,增加服务器内存。
4.3 案例三:外网访问慢但内网正常
现象:外网用户反映访问慢,但内网测试正常。
排查过程:
mtr测试显示某跳路由器丢包率高- 联系ISP更换路由路径
- 同时优化TCP参数:
bash复制echo "net.ipv4.tcp_window_scaling = 1" >> /etc/sysctl.conf echo "net.ipv4.tcp_timestamps = 1" >> /etc/sysctl.conf sysctl -p
经验总结:网络问题常常需要端到端的全面排查,不能只关注服务器本身。