在 Linux 运维和后端开发岗位的面试中,网络排查能力始终是重点考察方向,而 tcpdump 作为最经典的命令行抓包工具,几乎是面试必问的知识点。面试官不仅关心你是否会用几条过滤表达式,更在意你是否理解它背后的抓包原理,以及在真实故障场景中如何定位问题。本文围绕 tcpdump 的底层机制与高频过滤表达式展开,帮助你在面试中答出深度。
一、tcpdump 的抓包原理
1.1 从网卡到用户态:数据包的完整路径
tcpdump 本身并不“创造”数据包,它做的事情是从内核中“截获”已经流经网络协议栈的数据包。理解这条路径是回答原理类问题的关键。
当一块网卡收到一个以太网帧时,硬件会通过 DMA 将数据写入内核预先分配好的环形缓冲区(Ring Buffer),然后触发中断通知 CPU。内核的网络驱动在中断处理中把数据包封装成 sk_buff(socket buffer)结构,随后沿着协议栈向上传递:链路层 → 网络层 → 传输层 → 应用层。
tcpdump 的介入点位于链路层和网络层之间。它通过 AF_PACKET 套接字(早期使用 PF_PACKET)直接访问网络设备驱动层的数据,从而在数据包被协议栈进一步处理之前就拿到一份副本。这也是为什么 tcpdump 能抓到非本机目标的广播包、ARP 包,甚至目标 MAC 不是本机的混杂模式流量。
1.2 内核中的 BPF 过滤器
如果每个数据包都要复制到用户态再由 tcpdump 过滤,性能开销会非常大。Linux 的解决方案是 BPF(Berkeley Packet Filter),现在通常称为 eBPF 的前身或经典 BPF。
当你输入 tcpdump port 80 时,tcpdump 并不会简单地把这个字符串当作命令行参数记住,而是会把它编译成一段 BPF 字节码,然后通过 setsockopt 的 SO_ATTACH_FILTER 选项把这段字节码挂载到 AF_PACKET 套接字上。此后,每个到达该套接字的数据包都会先在内核中执行这段 BPF 程序,只有返回非零值(表示“匹配”)的包才会被复制到用户态。这样,无关流量在内核层面就被丢弃了,极大降低了 CPU 和内存开销。
1.3 混杂模式与普通模式
默认情况下,网卡只接收目的 MAC 地址是自己或广播/组播的帧。tcpdump 通过 PACKET_MR_PROMISC 选项可以请求网卡进入混杂模式(Promiscuous Mode),此时网卡会接收所有经过它的帧,无论目的地址是谁。在交换式网络中,这意味着你能看到本机网卡上能收到的所有流量,但不等于能看到整个局域网的所有流量——那需要端口镜像或集线器环境。
面试中常被追问:“tcpdump 能抓到本机不相关的流量吗?”答案是:在混杂模式下可以抓到同一冲突域或镜像端口上的流量,但在普通交换网络中,默认只能看到本机参与或经过本机的流量。
1.4 抓包对性能的影响
由于 BPF 在内核中过滤,tcpdump 对系统性能的影响通常可控。但在高流量场景下,如果过滤表达式写得过于宽泛(比如不加任何过滤),大量数据包被复制到用户态,会导致 CPU 软中断升高、丢包甚至影响业务。因此面试中如果被问到“线上抓包要注意什么”,一定要提到:尽量使用精确过滤、限制抓包数量(-c)、限制抓包大小(-s)、避免长时间全量抓包,必要时配合 -w 写入文件而不是直接打印。
二、常见过滤表达式
tcpdump 的过滤表达式遵循 BPF 语法,由类型(type)、**方向(dir)和协议(proto)**三个维度的原语组合而成,支持 and、or、not(或 &&、||、!)进行逻辑组合。
2.1 按主机过滤
tcpdump host 192.168.1.100 # 源或目的为该主机
tcpdump src host 192.168.1.100 # 仅源地址
tcpdump dst host 192.168.1.100 # 仅目的地址
tcpdump host 192.168.1.100 and host 10.0.0.1 # 两台主机之间的流量
注意:host 后面可以跟 IP 或域名,但域名会在抓包前解析一次,生产环境建议直接用 IP。
2.2 按端口过滤
tcpdump port 80 # 源或目的端口为 80
tcpdump src port 1024 # 源端口
tcpdump dst port 443 # 目的端口
tcpdump portrange 8000-9000 # 端口范围
tcpdump port 80 or port 443 # 多个端口
面试高频题:“如何同时抓多个不连续端口?”答案是使用 or 连接,或者写成 tcpdump 'port 80 or port 443 or port 8080'。
2.3 按协议过滤
tcpdump tcp # 仅 TCP
tcpdump udp # 仅 UDP
tcpdump icmp # 仅 ICMP
tcpdump arp # 仅 ARP
tcpdump ip # 仅 IPv4
tcpdump ip6 # 仅 IPv6
协议过滤可以和其他条件组合,例如 tcpdump tcp port 22 and host 10.0.0.5。
2.4 按网络过滤
tcpdump net 192.168.1.0/24 # 整个网段
tcpdump src net 10.0.0.0/8 # 源网段
tcpdump dst net 172.16.0.0/12 # 目的网段
2.5 按数据包特征过滤
这是体现深度的地方,面试中能答出这些往往加分:
tcpdump 'tcp[tcpflags] & (tcp-syn|tcp-fin) != 0' # 抓 SYN 或 FIN 包
tcpdump 'tcp[tcpflags] & tcp-syn != 0' # 仅 SYN 包
tcpdump 'tcp[tcpflags] & tcp-rst != 0' # 仅 RST 包
tcpdump 'ip[8] < 64' # TTL 小于 64
tcpdump 'greater 1000' # 包长大于 1000 字节
tcpdump 'less 100' # 包长小于 100 字节
tcpdump 'tcp port 80 and (tcp[((tcp[12] & 0xf0) >> 2)] = 0x47)' # HTTP GET 请求
最后一条虽然复杂,但面试中如果被问到“如何只抓 HTTP GET 请求”,能说出基于 TCP 头部长度偏移定位 payload 首字节的思路,会让人印象深刻。
2.6 常用组合与实战场景
# 抓取某主机与某服务之间的 TCP 流量,写入文件
tcpdump -i eth0 -w capture.pcap host 192.168.1.100 and port 3306
# 抓取非本机 SSH 的流量,限制 100 个包,不解析域名
tcpdump -i any -c 100 -nn tcp port 22 and not host 127.0.0.1
# 抓取 ICMP 包并显示详细信息
tcpdump -i eth0 -v icmp
# 抓取 VLAN 标签流量
tcpdump -i eth0 -e vlan
其中 -i any 表示监听所有接口,-nn 表示不解析主机名和端口名(避免 DNS 反查拖慢抓包),-c 限制数量,-w 写入文件,-r 读取文件,-s 设置 snaplen(0 表示抓完整包)。
三、面试中的常见追问
问:tcpdump 和 Wireshark 有什么区别?
答:tcpdump 是命令行工具,依赖 BPF 在内核过滤,适合服务器环境;Wireshark 是图形化工具,解析能力更强,适合离线分析。两者可以配合使用:tcpdump 抓包存为 pcap,再用 Wireshark 打开分析。
问:为什么抓到的包不完整?
答:可能是 snaplen 设置过小(默认 262144 字节,旧版本默认 68 或 96 字节),或者抓包时发生丢包。可以用 -s 0 抓完整包,用 -w 写文件减少用户态处理压力。
问:如何判断抓包时是否丢了包?
答:tcpdump 退出时会打印 “packets captured” 和 “packets received by filter”,如果两者差距大,说明内核到用户态之间丢了包,通常是过滤太宽或磁盘写入太慢。
掌握 tcpdump 的原理和过滤表达式,不仅能应对面试,更是线上排障的硬功夫。建议在实验环境中多用 -w 抓包再用 Wireshark 分析,把每一条过滤表达式对应到真实的 TCP 握手、HTTP 请求和异常 RST 场景中,理解会深刻得多。
未经允许不得转载:任鹏个人博客 » Linux 面试题:tcpdump 抓包原理与常见过滤表达式

