ARTICLE DETAIL

资讯详情

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

Linux网络抓包神器 tcpdump 入门到实战:安装、过滤与故障排查

Linux网络抓包神器 tcpdump 入门到实战:安装、过滤与故障排查 干运维的或者搞开发的几乎都绕不开一个场景某个服务突然调不通、接口超时、网页打开慢所有人盯着监控和日志翻来覆去最后发现问题根本不在这两层而是出在网络链路本身。这时候谁手里有一个趁手的抓包工具谁就能省下几个小时的排查时间。tcpdump 就是 Linux 上最经典、也是我日常用得最多的命令行抓包工具它小巧、依赖少、能装在几乎任何 Linux 环境里一条命令就能看清网卡上到底发生了什么。这篇文章就从一个完全没接触过 tcpdump 的新手视角出发从下载安装讲到常用命令再到真实故障排查的完整思路尽量把每一步怎么做、为什么这么做都交代清楚让你看完之后能够直接拿去用。1. 动手之前先想清楚为什么必学 tcpdump1.1 抓包工具到底在抓什么把网卡想象成一个快递驿站的门口数据包就是进进出出的包裹。tcpdump 做的事情就是在这个驿站门口装了一个带筛选功能的摄像头它能把经过网卡的每一个数据帧复制一份出来再根据你设定的规则只留下你关心的那部分流量。底层的核心组件是 libpcap 库它负责从内核网络协议栈中捕获原始数据包tcpdump 本身则是一个强化了过滤和展示能力的命令行前端。很多人会问业务都上云了、监控也接了一大堆了为什么还要自己抓包因为监控看到的是“结果”抓包看到的是“过程”。一台机器访问另一台机器的 80 端口连不上监控只会告诉你服务异常但它不会告诉你是 DNS 解析失败、TCP 三次握手没完成还是服务端直接回了一个 RST。这些信息藏在每一个包的网络层和传输层头部里不看包就只能靠猜。tcpdump 的核心价值就是把这个“过程”完整地摊在你面前。1.2 为什么选 tcpdump而不是 Wireshark新手容易犯的一个错误是一上来就想着装 Wireshark觉得界面友好、看得直观。可问题在于你要排查的服务器大概率是纯命令行环境没有图形界面Wireshark 装不了也没法用就算能装一个图形抓包工具扔在生产服务器上也显得过于笨重。tcpdump 的优势恰好对应了服务器的真实使用场景对比项tcpdumpWireshark / TShark运行环境纯命令行无图形依赖依赖图形界面TShark 除外安装体积很小依赖极少依赖较多安装包大脚本化/自动化天然适合比较别扭远程排查ssh 进去就能用一般需要下载抓包文件到本地数据分析配合 -w 保存 pcap 后分析自带强大分析界面实际项目里我最常用的组合是服务器上用 tcpdump 把包抓下来存成 pcap 文件然后下载到本地用 Wireshark 做深度分析。tcpdump 负责采集Wireshark 负责展示两者配合非常顺手。1.3 一条清晰的学习路径学 tcpdump 最大的误区是一上来就背命令。我的建议是这样的路径先把工具装好跑通一次最简单的抓包然后理解抓包结果里每一列代表什么再学会用过滤表达式缩小范围最后保存文件并尝试分析一次真实的故障场景。整个过程不需要一天跟着后面几节走一遍基本就能上手。真正值钱的部分不是命令本身而是你对网络状态的理解和对业务走向的判断这个只能靠多抓多看慢慢积累。2. 从零开始tcpdump在线与离线安装完整流程2.1 安装前的准备工作安装之前先花一分钟确认三件事操作系统发行版、当前用户权限、CPU 架构。这三件事直接决定了你该用哪个安装命令、下载哪个安装包。确认发行版和架构cat /etc/os-release uname -m如果 os-release 里显示的是 CentOS、Rocky Linux、Alibaba Cloud Linux、openEuler 这类一般走yum或者dnf如果是 Ubuntu、Debian走apt如果是 Alpine走apk。uname -m输出x86_64表示 x86 架构aarch64表示 ARM 架构离线下载安装包时架构必须匹配装错会直接报错。新手容易忽略权限问题。tcpdump 要抓包本质上需要读取网卡数据这需要 root 权限或者CAP_NET_RAW能力。所以最常见的安装命令和抓包命令都是sudo开头。你先执行id看一下自己是不是在wheel或者sudo组里免得下载装好了结果一运行报权限不足又卡半天。2.2 在线安装就三行命令如果你的服务器能访问软件源在线安装是最省事的不需要手动处理依赖关系。以最常见的两大系为例RHEL 系CentOS / Rocky / Alibaba Cloud Linux 等sudo yum install -y tcpdump # 或者 sudo dnf install -y tcpdumpDebian 系Ubuntu / Debiansudo apt-get update sudo apt-get install -y tcpdumpAlpine 系sudo apk add tcpdump装完之后执行tcpdump --version如果能看到版本号说明已经安装成功。这里有个细节tcpdump --version不仅会打印 tcpdump 的版本还会同时打印 libpcap 的版本。libpcap 对 tcpdump 来说就像地基对房子的关系版本太旧可能导致某些新协议解析不了后面如果遇到抓包正常但解析怪异的怪问题记得先回来看看 libpcap 版本。2.3 离线安装tcpdump重点在依赖很多生产环境是内网隔离的没法直接用 yum 或 apt。这时就要提前在有网环境准备好安装包再拷贝进去安装。整个离线安装过程我经历过很多次最核心的一件事就是别只下载 tcpdump 一个包它的依赖 libpcap 必须同时带上。缺少 libpcap 是最常见的离线安装失败原因。RHEL 系离线安装的标准流程。先在能联网的同版本机器上准备好 rpm 包# 创建目录 mkdir -p ./rpm_pkgs # 用 yumdownloader 下载 tcpdump 及其全部依赖 sudo yumdownloader --resolve --destdir./rpm_pkgs tcpdump执行完后ls ./rpm_pkgs应该能看到类似tcpdump-4.9.3-1.el8.x86_64.rpm和libpcap-1.9.1-5.el8.x86_64.rpm这样的文件。如果环境里没有 yumdownloader可以先sudo yum install -y yum-utils安装这个工具。然后把rpm_pkgs目录整个传到内网机器上执行安装sudo rpm -ivh ./rpm_pkgs/*.rpm如果之前已经装过旧版本可能需要升级安装sudo rpm -Uvh ./rpm_pkgs/*.rpmDebian 系离线安装也类似。在有网机器上apt-get download tcpdump libpcap0.8然后把下载的 deb 文件传过去sudo dpkg -i tcpdump*.deb libpcap*.deb注意 deb 系的依赖名各个版本可能不太一样建议用apt-cache depends tcpdump先查一下具体依赖名。还有一种情况是既没有 rpm 也没有 deb只能源码编译。这种方式需要 gcc、make、libpcap 的开发头文件步骤是./configure make sudo make install源码编译的优点是灵活缺点是依赖更多、编译时间更长。绝大多数场景下找对版本下载 rpm/deb 包是性价比最高的方案源码编译作为兜底思路了解即可。2.4 安装自检与版本验证安装完成后先验证别直接开始抓包。我习惯按下面顺序来# 1. 查看版本和 libpcap 版本 tcpdump --version # 2. 列出当前机器上所有可用的网卡接口 tcpdump -D然后跑一次最简单的最小化抓包确认整个链路是通的sudo tcpdump -i lo -c 5-i lo指定抓回环接口-c 5表示抓到 5 个包就自动退出。如果没有任何输出说明回环接口上这会儿没有流量新开一个终端执行ping 127.0.0.1制造一点流量后再看。如果能看到类似下面的输出说明 tcpdump 已经可以正常工作了tcpdump: verbose output suppressed, use -v[v]... for full protocol decode listening on lo, link-type EN10MB (Ethernet), capture size 262144 bytes 14:23:01.123456 IP 127.0.0.1 127.0.0.1: ICMP echo request, id 1, seq 1, length 64到这一步安装阶段就算完整走通了。3. 第一次抓包命令骨架和五个必会场景3.1 tcpdump命令到底怎么读tcpdump 的命令格式可以简化成一句话sudo tcpdump [选项] [过滤表达式]选项决定“怎么抓”过滤表达式决定“抓什么”。先看最常用的选项选项作用实践建议-i 接口名指定抓包的网卡接口用-D查看所有接口名-c 数量抓到指定数量后自动停止测试时务必加防止无限抓包-n不做 IP 反向域名解析生产环境建议用-nn-nn不解析 IP 也不解析端口避免额外 DNS 干扰-w 文件将原始包写入文件文件后缀习惯用.pcap-r 文件读取 pcap 文件结合其他选项分析-s 字节数每个包抓取前多少字节默认 262144通常无需改-B 大小设置内核缓冲区大小单位 KiB大量丢包时调大-e显示链路层头MAC 地址排查 ARP/交换问题用-tttt完整日期时间戳分析延迟问题时必备过滤表达式是 tcpdump 的灵魂。它基于 BPFBerkeley Packet Filter语法核心就是围绕五元组做组合协议、源 IP、源端口、目的 IP、目的端口。常用的关键字包括host、src、dst、port、tcp、udp、icmp、arp、and、or、not。写表达式时有两点最容易踩坑一是and一定要小写大写会被当成错误二是表达式里如果有and、or、not最好整段用单引号包起来防止 shell 拿这些单词搞事情。3.2 五个最常用的抓包场景场景一抓某个网卡上的全部流量sudo tcpdump -i eth0 -nn这条命令适合刚开始排查、还不知道问题在哪一层的时候。先看整体流量观察有没有明显的 TCP 重传、RST、连接反复建立等异常特征。生产环境不建议长时间这样抓流量大的话输出刷屏很影响判断。场景二抓某台特定主机的通信sudo tcpdump -i eth0 -nn host 192.168.1.10比如业务方说“只有这台机器连不上”其他机器都正常那就只筛这台机器的流量排除无关干扰。场景三只看某个端口的流量sudo tcpdump -i eth0 -nn tcp port 80我就经常用这个来确认 HTTP 请求到底有没有到服务器、到了之后有没有立刻被拒绝。如果想同时看 80 和 443可以这样sudo tcpdump -i eth0 -nn tcp port 80 or tcp port 443场景四保存文件和分析文件# 将抓包数据保存为文件 sudo tcpdump -i eth0 -nn -w /tmp/http.pcap tcp port 80 # 之后随时读取该文件进行分析 sudo tcpdump -r /tmp/http.pcap -nn保存 pcap 文件这个习惯建议从第一天就养成。直接看屏幕的实时输出有两个问题一是容易错过关键包二是没法做二次分析。保存成文件以后可以用-r反复读也可以拉到本地用 Wireshark 打开配合图形界面的时间线、统计功能排查效率会高很多。场景五组合过滤条件精确定位sudo tcpdump -i eth0 -nn host 192.168.1.10 and tcp port 22 and not src host 192.168.1.20这个例子的含义是抓取 192.168.1.10 与任何主机之间的 TCP 22 端口流量但排除源地址是 192.168.1.20 的包。组合条件是实际排查中使用频率最高的因为真实故障往往是“某台机器到某台机器、某个端口、某个协议”这种多维度的交集。3.3 关于snaplen、缓冲区与混杂模式的通俗理解抓包时有三个容易被忽略但实际影响很大的参数我展开说一下。第一个是 snaplen也就是-s参数它控制每个数据包最多捕获多少字节。默认值是 262144这个值对常规分析完全够用。如果只关心 TCP 标志、IP 地址、端口这些头部信息把 snaplen 调小到 96 或 128 能减少内存和磁盘占用但如果是排查 HTTP 请求内容、应用传输的数据就必须留足长度否则包内容会被截断。我一般默认不动-s只在流量极大、存储紧张的场景下才考虑调小。第二个是内核缓冲区大小也就是-B参数单位是 KiB。抓包流程是数据包先进入内核缓冲区tcpdump 进程再从缓冲区读出来处理。如果流量突发太大、内核缓冲区很快被填满而用户态读取速度跟不上就会发生内核丢包。tcpdump 退出时会打印一行统计X packets captured, Y packets received by filter, Z packets dropped by kernel。这个 Z 就是内核丢弃数如果它明显大于 0建议加-B 4096甚至更大来缓解。第三个是混杂模式。tcpdump 默认会把网卡设置为混杂模式也就是说哪怕目的 MAC 不是本机的包只要网卡能收到也会被抓进来。这个模式在分析交换机镜像口过来的流量时是必须的但在普通服务器上交换机本来就不会把别人的流量发给你所以开不开混杂模式对你实际能看到的包影响不大。如果你明确只想看本机流量可以加-p关闭混杂模式减少无关干扰。4. 真实问题排查模拟从抓包到定位的完整链条前面讲的都是命令这一节用三个我在实际生产中遇到过的典型故障场景演示从抓包到定位的完整思路。记住一个原则抓包之前先明确怀疑对象抓包之后用数据验证或推翻这个怀疑。4.1 场景一域名解析不出来到底卡在哪一环现象是应用日志报Unknown host但同一台机器上用浏览器访问同一个域名却是正常的。这种“部分程序解析失败”的问题优先怀疑 DNS 解析链路。我的排查步骤是这样的。先看系统配置的 DNS 服务器cat /etc/resolv.conf然后抓 DNS 请求和响应sudo tcpdump -i eth0 -nn port 53 -w /tmp/dns.pcap新开终端触发一次解析nslookup example.com等 nslookup 结束后CtrlC 停掉 tcpdump读取抓包结果sudo tcpdump -r /tmp/dns.pcap -nn怎么判断问题出在哪一环如果抓包文件里只有客户端发出的 DNS 查询请求没有来自 DNS 服务器的响应包那问题大概率出在网络链路或防火墙策略上请求根本没到服务器或者响应被拦了。如果请求和响应都在但响应里的记录内容不对或者返回了 NXDOMAIN域名不存在那就要去找 DNS 服务器管理员确认解析记录。还有一种情况压根就没抓到任何 DNS 查询包那说明问题出在应用自身或者本地缓存配置上请求根本没发出来。4.2 场景二接口响应慢是网络还是应用现象是调用某个内部接口时curl -w显示 total 耗时要好几秒但不确定是网络慢还是应用处理慢。这种问题用抓包拆分时间线答案非常清晰。先启动抓包然后发起一次请求sudo tcpdump -i eth0 -nn tcp port 8080 -tttt -w /tmp/api.pcap # 另一个终端执行 curl http://10.0.0.10:8080/api/hello保存文件后用-r查看每一次交互的时间戳。我通常关注三个时间节点SYN 发出时刻、SYN-ACK 返回时刻、最后一个数据包完成时刻。SYN 发出后如果隔了很久才收到 SYN-ACK说明问题出在中间链路或对端网络栈跟应用无关如果三次握手很快完成但客户端发完 HTTP 请求后等了很久才收到响应数据那问题大概率在应用本身比如线程池满、数据库慢查询。如果看到了大量相同序号的重传包则说明网络存在丢包重传机制在反复拉低吞吐。没有 Wireshark 的情况下-tttt输出的完整时间戳足够做这个大致的阶段判断。想要更精确的话把 pcap 文件下载到本地用 Wireshark 打开开启Analyze Expert Info它会直接标出重传、乱序、重复 ACK 等异常事件定位起来更快。4.3 场景三连接被拒和频繁重传怎么判断现象是客户端连服务器端口时报Connection refused但端口明明在监听。这个矛盾最容易在抓包里找到答案。用如下命令抓 TCP 连接过程sudo tcpdump -i any -nn tcp port 8080 -w /tmp/refused.pcap然后从客户端发起一次连接。读取 pcap 文件重点看 SYN 之后的返回标志。如果服务器回了 RST 包说明当前没有进程监听这个端口或者防火墙策略主动发了 reset如果 SYN 发出去之后石沉大海、完全没有回包说明包被中间设备丢弃了可能是安全组策略、防火墙拦截甚至是 IP 被限流。判断 TCP 重传也有一个很实用的技巧。TCP 报文头的标志位存在第 13 个字节通过过滤表达式可以直接筛选特定类型的包。比如只看 SYN 包sudo tcpdump -i eth0 -nn tcp[13] 2 ! 0只看 RST 包sudo tcpdump -i eth0 -nn tcp[13] 4 ! 0这种方式在包很多、屏幕刷得飞快的时候特别有用可以快速捕捉异常标志。5. 常见报错与坑位排查实录5.1 高频报错和解决办法速查表以下是 tcpdump 使用过程中最高频的报错和对应的排查思路基本上都是我在实际环境里踩过的报错信息原因分析解决办法tcpdump: no suitable device found没有找到可用网卡接口或者接口名写错用tcpdump -D查看接口列表确认名称You dont have permission to perform this capture当前用户没有抓包权限加sudo执行或者给用户分配 CAP_NET_RAWtcpdump: eth0: That device is not up指定网卡没有启用检查ip link show eth0网卡状态启动后再抓tcpdump: unknown keyword port过滤表达式语法错误检查关键字拼写and/or/not必须小写packets dropped by kernel数值很大内核缓冲区不足读不过来加-B 4096调大缓冲区或缩小过滤范围pcap_loop: The interface went down抓包过程中网卡状态发生了变化排查网卡断开原因重新开始抓包tcpdump: unable to open savefile无法打开抓包文件确认文件路径是否有读权限格式是否完整5.2 容易踩的坑但文档里一般不写第一不要在业务高峰期不加过滤地抓全量包。流量一大pcap 文件增长速度远超想象。我习惯先做粗粒度评估用${带宽峰值byte/s} x ${预计抓包时长s}先算一下可能产生的文件大小再决定抓包时长。比如峰值流速约 100MB/s 的环境抓 10 秒就有约 1GB 数据这个大小对磁盘和分析工具都是负担。所以生产环境抓包一定要用过滤条件缩小范围并加上-c控制包数量或者用timeout 30 tcpdump ...做时间上限。第二容器环境里抓包要特别注意网络命名空间。在宿主机上用 tcpdump 抓容器的 IP经常会发现请求和响应都能看到但看不到容器内部更细的交互细节。因为容器有自己的网络命名空间流量需要经过 veth 或宿主机网桥。我的做法是能进容器就进容器抓不能进就用nsenter进入容器的 netns 再抓或者在宿主机上找到对应的 veth 接口抓。记住一点抓包位置决定了你看到的视角换一个位置结论可能完全不同。第三抓 HTTPS 流量别指望 tcpdump 能看到明文。tcpdump 工作在 IP 层以下看到的是 TLS 加密后的密文。想分析 HTTPS 里的 HTTP 内容需要浏览器或应用支持 SSLKEYLOGFILE把会话密钥导出来配合 Wireshark 解密而不是直接在服务器上抓包就能看明文。如果你只是想确认客户端到服务器有没有建立连接、连接耗了多少时间TLS 握手过程中的 ClientHello、ServerHello 这些包在同一条抓包里也能看到不需要解密。第四过滤表达式里的and、or、not一定要加引号。不加引号时shell 可能把and当成内置命令或管道符号轻则命令报错重则抓包开始后就停不下来。我个人的习惯是无脑用单引号包住整个过滤表达式例如sudo tcpdump -i eth0 -nn host 192.168.1.10 and tcp port 80这样既不会出 shell 转义问题代码也更好读。5.3 写给新手先学会看包再学抓包最后分享一点我自己的体会。很多新手学 tcpdump把命令背得滚瓜烂熟但真遇到故障还是发懵原因在于对“包”本身不理解。tcpdump 的过滤条件说到底就是在描述五元组协议、源 IP、源端口、目的 IP、目的端口。你只要在脑海里能把一个网络请求拆成这几部分抓包命令自然就写出来了不需要死记硬背任何一个组合。我建议新手做一个小练习在本地搭一个简单的 HTTP 服务然后连续抓几次访问它的包在输出里把 TCP 三次握手的 SYN、SYN-ACK、ACK 三个包找出来再看 HTTP 请求和响应在握手之后是怎么衔接的。做完这一个练习你对网络连接的直观感受会比看十篇教程都深。我在实际排查网络问题时还有一个习惯抓包之前先写一句话说明我怀疑什么、要验证什么、抓到什么结果算证实抓到什么结果算证伪。这个习惯帮我避免了很多无目的的乱抓。tcpdump 本身并不难难的是带着问题去抓包然后从包里还原出网络链路的真实全貌。真到了那个阶段你会发现这台命令行抓包工具就是排查网络故障时最顺手的利器。
返回列表