十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Linux网络故障排查:从分层诊断到tcpdump抓包的全链路实战

Linux网络故障排查:从分层诊断到tcpdump抓包的全链路实战 很多朋友遇到Linux网络问题第一反应是“ping一下”ping不通就懵了ping通了就觉得网络没问题。这两种反应都太极端了。我调试过不少线上故障从“网卡光模块被老鼠咬了一口”到“内核协议栈参数被某次加固脚本改坏”各种稀奇古怪的问题都碰过。说实话Linux网络Debug最大的门槛不是命令记不住而是你不知道该用什么工具、按什么顺序去查以及拿到结果后怎么解读。这篇东西不打算写成man手册的翻译版而是把我平时排查网络问题的一套流程、常用到的工具、以及这些工具背后到底在做什么讲明白。无论你是刚接触Linux的新手还是被线上问题折磨的运维应该都能从中找到点有用的东西。1. 排查网络问题的底层逻辑先分层再动手很多人在排查网络问题时东一榔头西一棒子其实是心里没有一张地图。网络通信这件事从网线插上到数据到达应用中间要经过物理层、链路层、网络层、传输层、应用层每一层都有可能出现故障。你的排查工具本质上就是每一层的“探针”。1.1 从“应用正常吗”回溯到“链路正常吗”举个例子你在浏览器里打不开某个网页大部分人的第一反应是“要不重启一下服务”这种操作不是不对但那是跳跃式的——你直接从应用层跳到了解决方案跳过了中间所有可以验证的环节。正确的排查思路应该是自顶向下或者自底向上一层层剥开。我习惯的做法是先从本机看网卡起来了没有IP配置对不对路由表正不正常。然后往外探网关能不能通到目标机器的每一跳通不通。再往细看目标端口通不通协议握手是否正常。最后抓包看如果端口通但业务不行那问题一定在应用层或数据内容上。这样排查的好处是每一步都有一个明确的结论不会绕圈子。比如你检查完发现本机网卡是down的状态那你根本不需要去管什么防火墙、什么路由问题已经定位到了。1.2 工具和网络分层的对应关系我整理了一张对应表排查的时候心里大概有个数网络分层常见故障表现排查工具物理层/链路层网线松动、光模块故障、协商速率异常ethtool, ip link, dmesg网络层IP冲突、路由丢失、丢包ip, ping, traceroute, mtr传输层端口不通、连接超时、队列堆积ss, netstat, nc, telnet应用层DNS解析慢、HTTP报错dig, nslookup, curl, tcpdump这个表格不是死的但是能帮你快速判断自己“应该用哪个工具”“查出来的结果代表哪一层有问题”。我这几年下来最深的体会是绝大部分排查效率低都是因为拿错了工具去查错误的层。比如明明是端口没监听偏偏去抓包分析数据包内容当然什么都查不出来。2. 连通性三件套ping、traceroute 和 mtr 的正确打开方式说ping是Linux网络排障的第一步应该没人反对。但真正用对ping的人其实没那么多。2.1 ping 不止是看通不通更要看延迟和丢包ping的本质是发送一个ICMP Echo Request报文目标主机收到后回一个ICMP Echo Reply。它能告诉你两件事目标可达不可达以及到目标的往返延迟。但这里有一个非常常见的误区业务服务器通常会禁ping或者某些机房会过滤ICMP报文。如果ping不通就断定网络断了往往会误判。我之前遇到过好几起事故服务器明明能正常访问但ping就是超时最后发现是安全组策略把ICMP给丢了。所以用ping的正确姿势是# 连续ping观察延迟波动和丢包率 ping -c 100 192.168.1.1 # 指定间隔0.2秒快速测试不稳定的链路 ping -i 0.2 10.0.0.1 # 指定源IP适用于多网卡服务器 ping -I eth1 10.0.0.1 # 不要分片地探测MTU ping -M do -s 1472 10.0.0.1最后一个命令值得单独说。-M do表示不允许分片-s 1472是1500字节MTU减去28字节ICMP头后的负载长度。如果你用这个大小能ping通但更大的包不通那基本就是链路上某个设备MTU设置不对典型的“能上微信但打不开网页”故障元凶。2.2 traceroute定位“卡在哪一跳”ping告诉你的是结果而traceroute告诉你的是路径上每一跳的情况。它的原理是利用IP报文头的TTL字段每经过一个路由器TTL减1减到0时路由器会返回一个ICMP Time Exceeded报文。traceroute就是从TTL1开始递增地发包从而拿到每一跳路由器的IP。默认情况下traceroute使用的是UDP封包目标端口从33434开始递增。但在很多网络环境中UDP报文会被防火墙拦截导致你看到一连串的* * *。这时候可以换成ICMP模式# 用ICMP模式绕过UDP限制 traceroute -I baidu.com # 用TCP SYN模式指定端口适合探测目标端口可达性 traceroute -T -p 443 baidu.com-T模式在实际排查中非常有用因为它模拟的是真实应用发起连接的过程。我曾经排查过一个诡异问题从A机器到B机器ping通、traceroute通但业务方死活说连不上。最后用traceroute -T -p 8080一测发现在中间的某一跳设备上TCP的8080端口被ACL策略拦了。这一下就把问题从“网络层”拉到了“策略层”。2.3 mtr把ping和traceroute合体持续监控链路质量如果说traceroute是拍了一张快照那mtr就是一段录像。它综合了ping和traceroute的功能持续发送探测包并统计每一跳的丢包率和延迟变化是排查链路抖动、间歇性丢包的利器。# 安装Debian/Ubuntu系 apt install mtr-tiny # 持续跟踪到目标地址的链路质量 mtr -r -c 100 10.0.0.1-r是report模式打100个包之后输出一份统计报告然后退出不加-r则是交互式界面实时刷新。mtr输出里最需要关注的是中间的某一段丢包率突然升高而它后面所有节点也跟着丢包那问题基本就定位在丢包的这个节点上。但如果只是末尾节点丢包、中间都正常通常是末端节点本身不给回ICMP而已不代表链路有问题。我遇到过的情况是mtr显示某一条线路的某一跳掉包率在30%以上但业务流量走的不是这条路径所以看起来“一切正常”。这时候要记住mtr只代表探测路径的质量不代表所有业务流量都走这条路。多测几个目标IP对比路径才能画出真实的影响范围。3. 端口与连接排查ss 和 nc 的实际用法排到传输层核心问题是“端口通不通、连接建不建得起来”。传统思路是telnet IP 端口但Linux上更常用、信息量更大的是ss。3.1 ss比netstat更快的连接状态查看工具ss是iproute2包里的工具读取的是内核的socket信息比netstat遍历/proc/net/tcp要快得多。在高连接数的服务器上netstat可能卡个好几秒而ss瞬间就出来了。最常用的几个组合# 查看所有TCP连接显示进程信息 ss -tnp # 只看监听状态 ss -tlnp # 统计各种连接状态的数量 ss -s # 按目标端口过滤 ss -tnp dst 10.0.0.5:80-t是TCP-n是不反解域名显示IP而非主机名速度快很多-l是只看监听-p是显示进程PID和名称。这个组合几乎覆盖了端口排查的90%场景。举个实际场景某天服务商反馈他们连不上我们的数据库端口3306我第一件事不是抓包而是先看端口有没有在监听ss -tlnp | grep 3306如果显示LISTEN 0 128 0.0.0.0:3306说明数据库本身在正常监听。如果压根没有这一行那问题就是服务没起来或者监听地址配错了。如果监听的是127.0.0.1:3306那么外部当然连不上因为只绑定了回环地址。很多人在这里翻车以为是防火墙问题结果是自己绑定的地址不对。3.2 ncnetcat传输层的瑞士军刀nc这个工具简单的用法像一个轻量级的telnet但功能远不止于此。我最常用的场景有这么几个测试端口连通性nc -zv 10.0.0.5 3306-z是zero I/O模式只扫描端口不发送有效数据。-v输出详细日志。通了会显示Connection succeeded不通会显示Connection refused或者超时。临时开启一个端口做测试# 在服务器A上监听12345端口把收到的内容输出到终端 nc -l 12345 # 在服务器B上发送测试数据 echo hello | nc 10.0.0.1 12345这个方法在验证网络连通性、防火墙规则是否放行时特别好用不需要真的起一个业务服务。我在内网调试跨机房的网络访问时经常这么干先在一台机器上nc -l 8080再从另一台机器发数据通了就说明链路和防火墙都放行了。端口转发nc -l 8080 | nc 10.0.0.5 80这个命令把本机8080端口收到的数据原封不动转发到内网10.0.0.5的80端口。我曾在没有ssh隧道权限的环境下用它在一个跳板机上开了个临时转发解决了调试问题。当然这个用法比较野生产环境还是建议用iptables的DNAT或ssh隧道。4. 带宽与性能瓶颈iperf3 和 ethtool 侧重点完全不同“网络很慢”和“网络不通”是两个维度的故障。前者往往更需要带宽测试工具来量化评估而不是一直靠ping测延迟解释。4.1 iperf3测带宽的唯一标准iperf3可能是目前局域网和机房环境里最常用的带宽测试工具了。用法上分服务端和客户端服务端一般是网络质量较好、作为测试基准的一端iperf3 -s -p 5201客户端发起测试的一端# 默认TCP测试双向测试 iperf3 -c 10.0.0.5 -p 5201 -t 30 # 反向测试从服务端到客户端的方向 iperf3 -c 10.0.0.5 -p 5201 -R # UDP测试模拟实时音视频流等对丢包敏感的业务 iperf3 -c 10.0.0.5 -p 5201 -u -b 100M-t 30是持续测试30秒-R测试反向带宽-u -b 100M是以100Mbps的速率发送UDP流量。看输出结果的时候重点关注三个指标带宽Bandwidth、重传Retr、丢包Lost。TCP测试里如果带宽达不到物理上限看重传数是否很高——重传多说明链路质量差或缓冲区不够。UDP测试里Lost比例超过1%就说明链路对实时性业务已经不友好了。有一次客户反馈说两机房之间专线的带宽“不对”买的是千兆实际传输文件只有200Mbps左右。我用iperf3一测TCP确实只能跑到200M但重传率高达5%。接着在两端分别用ethtool看协商速率发现一端的网卡协商成了1000Mbps但光模块是千兆的没问题。最后检查两端服务器的网卡队列、中断绑核、TCP缓冲区参数才定位到是接收端的ring buffer太小导致丢包触发TCP拥塞控制降速。这个案例里iperf3只负责“报问题”报完问题还得靠ethtool和内核参数去“找原因”。4.2 ethtool看物理链路状态和网卡统计ethtool这个名字听起来像是只改网卡参数的实际上它也是排查物理层和链路层的得力工具。# 查看网卡基本信息包括协商速率、双工模式 ethtool eth0 # 查看网卡的统计计数器 ethtool -S eth0 # 查看网卡上收到的错误包、丢弃包数量 ethtool -S eth0 | grep -E rx_error|rx_dropped|tx_error|tx_droppedethtool eth0输出里的Speed就是协商后的速率Duplex是双工模式正常情况下应该是Speed: 1000Mb/s, Duplex: Full。如果显示Duplex: Half或者速率很低说明网卡和对端设备协商出了问题。网线、光模块、对端交换机端口故障都可能造成这种结果。ethtool -S里的计数器是宝库尤其是这些关键项rx_crc_errors接收数据包CRC校验错误说明物理链路质量差常见于网线老化、电磁干扰。rx_dropped网卡驱动层丢弃的包可能是队列已满或驱动bug。rx_missed硬件FIFO溢出导致的丢包通常意味着网卡处理能力不足或中断处理不过来。有一次线上业务出现间歇性卡顿ping网关偶尔丢一两个包机房说“链路正常”我登录服务器看了一眼ethtool -S eth0 | grep rx_crc_errors发现短短一天增长了上万次。这就说明物理层有信号问题最后查下来是机柜里的网线被相邻设备的电源线干扰了换了一根屏蔽网线后问题消失。4.3 网卡多队列和软中断绑核性能瓶颈的第二战场有时候带宽上不去、延迟抖得厉害问题并不在网络上而在CPU处理数据包的能力上。Linux收到网络包后网卡通过硬中断通知CPUCPU再触发软中断softirq去处理协议栈。默认情况下所有队列的中断都可能落在同一个CPU核心上这个核心忙不过来其他核心在闲着就会导致丢包和性能瓶颈。查看当前网卡队列和中断绑核情况# 查看队列数量 ethtool -l eth0 # 查看中断号分布 cat /proc/interrupts | grep eth0 # 查看RPSReceive Packet Steering是否启用 cat /sys/class/net/eth0/queues/rx-0/rps_cpus如果你发现服务器的网卡有多队列但中断全部落在同一个CPU上可以通过irqbalance服务或手动绑定中断到不同核心来分流。对于纯软中断业务也可以启用RPS把接收到的包均匀分发到多个CPU核心上。这一步的排查思路是如果带宽测试正常、物理链路正常、没有CRC错误但应用还是说“网络慢”那问题可能根本不在网络上而在数据包到用户态之前的处理链路里。这种情况用top看CPU使用率时会看到某个核的si软中断占用特别高而其他核心很低。遇到这种情况不要瞎猜网络问题赶紧查队列和绑核才对。5. 抓包分析学会 tcpdump 和 tshark才算真正掌握网络Debug如果前面所有工具都查不出问题或者你想非常精确地知道某个连接上传输了什么内容抓包分析就是最后的手段也是最不容易扯皮的手段。5.1 tcpdump 基本使用网上请求和响应的“录音机”tcpdump是Linux上最经典的抓包工具基于libpcap库。它的强大之处在于过滤器表达式可以很精细地组合。# 抓本机与某个IP的所有包 tcpdump -i eth0 host 10.0.0.5 # 抓某个端口的TCP流量 tcpdump -i eth0 tcp port 80 # 抓特定源和目的地组合 tcpdump -i eth0 src host 192.168.1.100 and dst port 8080 # 抓HTTP请求内容把应用层数据也打出来 tcpdump -i eth0 tcp port 80 -A-A参数把每个数据包的ASCII内容打印出来适合看纯文本协议HTTP简单粗暴。但要注意一旦流量加密HTTPS-A只能看到加密后的乱码。抓包时有个重要技巧在网卡上抓包会丢包的。tcpdump复制一份数据包给用户态程序处理这会消耗CPU和内存。在高流量场景下直接tcpdump -i eth0甚至可能影响业务本身所以务必配合过滤条件使用避免大范围抓包。如果非要大量抓包建议用-w参数把结果存成文件事后分析tcpdump -i eth0 -w /tmp/capture.pcap host 10.0.0.55.2 tshark命令行版Wireshark抓完还能精细过滤tshark是Wireshark的命令行版本比tcpdump的展示和分析能力更强。如果说tcpdump是录音机那tshark就是带着录音笔的分析师。# 安装Debian/Ubuntu系 apt install tshark # 读取pcap文件按HTTP请求路径过滤 tshark -r capture.pcap -Y http.request.method GET # 显示每个TCP流的统计信息 tshark -r capture.pcap -z conv,tcp # 只看TCP重传的包 tshark -r capture.pcap -Y tcp.analysis.retransmission-Y是显示过滤它不丢弃原始数据只是选择性地展示符合条件的数据包。这在分析“某个连接为什么慢”“有没有重传”“三次握手是否正常”时非常直观。5.3 抓包案例一次SSL握手卡顿的定位过程有一次服务商反馈“HTTPS请求特别慢要好几秒才建立连接”我在服务器上抓包tcpdump -i eth0 tcp port 443 -w /tmp/ssl.pcap然后用tshark看一下TCP握手是否正常tshark -r /tmp/ssl.pcap -Y tcp.flags.syn 1 -c 10结果显示三次握手瞬间就完成了SYN、SYN-ACK、ACK的间隔都是几个毫秒。那问题就不在TCP层而在TCP之上的SSL/TLS协商。继续过滤tshark -r /tmp/ssl.pcap -Y ssl.handshake.type 1 -c 5发现Client Hello发出后服务端迟迟没有响应Server Hello中间隔了1.8秒。再去看服务端进程的日志和CPU占用发现一个定时任务在同一时间点触发了大规模日志写入导致服务端事件循环被阻塞。这个问题的根因根本不是网络而是应用层处理不及时。如果没有抓包你可能会去调内核TCP参数、换网络设备折腾一晚上都找不对方向。还有一次抓包发现大量的快速重传tcptrace和tshark -z conv,tcp一分析定位到是发送端的TCP窗口设置过小导致吞吐量上不去。这种问题靠ping和iperf都很难一眼看出来只有抓包到报文级别你才能看到窗口值、序列号的变化轨迹。6. 从现象到结论一个真实故障的完整排查链拉通前面所有工具演示一次从“用户反馈连不上内网服务器”到“定位到根因”的完整过程。这个案例是真实遇到过的故障主诉为办公室的某台Linux服务器从内网其他机器访问其上的8080端口时时通时不通且很不稳定。第一步物理层和链路层检查登录到服务器上先看网卡状态ip link show ethtool eth0输出是UP状态协商速率千兆、全双工看起来正常。再扫一眼错误计数器ethtool -S eth0 | grep -E err|drop发现rx_crc_errors有几百次不多但也没有在持续增长。这个数据暂时存疑继续往上查。第二步网络层检查从本机ping网关、ping客户端IP都通且延迟在0.2ms左右认为网络层看起来正常。mtr -r -c 50 客户端IP链路也没有丢包。到这里物理层和网络层的嫌疑暂时洗清。第三步传输层检查在服务器上查看8080端口的监听状态ss -tlnp | grep 8080显示是LISTEN 0 128 *:8080正常监听。然后从客户端机器上反复连接测试for i in $(seq 1 30); do nc -zv -w 1 服务器IP 8080; done结果30次里大约有7次连接失败看起来确实是不稳定。但ss的监听正常问题在链路中间还是服务端第四步抓包定位在服务器上抓包tcpdump -i eth0 tcp port 8080 -nn -c 200在抓包的同时从客户端发一批连接请求。抓到的包里发现了一个关键规律失败的连接请求SYN包根本没有到达服务器网卡。这意味着问题大概率出在服务器前面的设备上而不是服务本身。再回头看ethtool -S里面那个几百次的rx_crc_errors结合SYN丢失的情况判断可能链路物理层信号质量有问题。让机房的同事检查了网络线缆发现交换机端口跟服务器连接的网线水晶头压接有问题存在偶发接触不良重新做了一根网线后问题彻底消失。这个案例想说的是不要只依赖单一工具的结论而是要用多个工具从不同层面交叉验证。每条线索单独看都“还行”但合在一起指向性就很明确了。ss排除了服务端的监听问题tcpdump排除了数据包到达服务器却没反应的情况剩下的可能面已经很窄再结合网卡计数器里的异常结论就自然浮出来了。7. 按需补充的小技巧DNS 和系统集成层的专项排查除了以上链路层面的工具还有两类在“连不上、访问慢”问题中出镜率极高的专项DNS和系统层文件描述符。很多人排查半天网络结果卡在DNS解析上这种故障在开发环境里我见过太多。7.1 dig 和 nslookup别只看能不能解析还要看解析耗时一般的解析测试dig 8.8.8.8 www.example.com dig www.example.com 21 | grep Query timeQuery time这个字段可以看解析耗时如果每次都几百毫秒甚至几秒说明DNS服务器响应很慢。如果用的内网DNS可以看看是不是上游运营商DNS下游超时。7.2 文件描述符和连接队列溢出有时候端口监听正常、网络也通可连接就是失败大概率是文件描述符或连接队列满了。检查的方法# 查看当前文件描述符占用 ss -s # 查看核心进程的fd限制 cat /proc/$(pidof 服务进程)/limits | grep open files # 查看TCP全连接队列溢出次数ListenOverflows netstat -s | grep -i overflow如果ListenOverflows次数很高表示请求到达后应用来不及accept队列已经堆积新连接只能被内核丢弃。这时就算网络层面完全通畅也会看到“连接失败”的现象。这已经不是网络Debug的问题了而是应用性能问题在网络层的投影。7.3 不要忽视systemd和Cloud-init对网络配置的影响使用NetworkManager或systemd-networkd管理的服务器上很多人排查完网络参数一段脚本或一条nmcli命令就会把之前的手动改配置冲掉。我之前遇到过一台服务器手动配置了静态IP结果systemd-networkd自动把他不认识的网卡配置文件全部给移除了IP就丢了。排查了半天最后发现是网卡命名规则 systemd的配置文件顺序问题。所以有时候你查“网络”查到最后其实是在查“配置管理”的问题。这也是为什么我建议把网络排障当成一个全链路过程不要局限在某个单独的工具或单独的一层。
返回列表