tcpdump无法捕获Wireshark可见的DNS请求,求原因及解决方法
我来拆解下这个问题的核心矛盾:Wireshark能抓到包,但tcpdump不行,而且目标主机的UDP53是关闭的。常见的原因主要有这几个:
1. 内核反向路径过滤(rp_filter)开启导致包被丢弃
Linux内核的rp_filter(反向路径过滤)机制是用来防止IP欺骗的,它会检查数据包的源IP是否符合当前主机的路由表——如果内核认为这个数据包的来源路径“不合理”,就会直接把它丢掉。
而Wireshark和tcpdump的抓包时机不一样:
- Wireshark是在网卡驱动层抓取原始数据包,这时候包还没进入内核网络栈的过滤逻辑;
- tcpdump虽然也是用libpcap抓包,但如果
rp_filter已经把包丢弃了,它就看不到这些被内核丢掉的包。
2. tcpdump没有指定正确的网卡
如果你的主机有多个网络接口(比如eth0、wlan0、docker0等),tcpdump默认会选择系统默认的网卡(通常是第一个激活的网卡),但DNS请求可能是发送到另一个网卡上的。而Wireshark会让你选择具体的网卡来抓包,所以能抓到目标流量。
3. 权限或过滤规则的细节问题
虽然你用了简化过滤规则,但如果没有以root权限运行tcpdump,可能会因为权限不足无法抓取全部流量;另外如果目标数据包带有特殊标记(比如VLAN标签),你的过滤规则也可能漏掉这些包。
针对上面的原因,一一对应解决:
解决方法1:临时关闭反向路径过滤
先查看当前的rp_filter设置:
sysctl -a | grep rp_filter
如果输出里net.ipv4.conf.all.rp_filter或者对应网卡的rp_filter值是1(开启状态),可以临时关闭:
# 关闭所有网卡的rp_filter sysctl -w net.ipv4.conf.all.rp_filter=0 # 关闭特定网卡(比如eth0)的rp_filter sysctl -w net.ipv4.conf.eth0.rp_filter=0
如果需要永久生效,编辑/etc/sysctl.conf或者/etc/sysctl.d/下的配置文件,添加或修改:
net.ipv4.conf.all.rp_filter=0 net.ipv4.conf.eth0.rp_filter=0
然后执行sysctl -p让配置生效。
解决方法2:指定tcpdump抓取的网卡
用-i参数指定具体的网卡,比如你知道DNS请求是到eth0,就运行:
tcpdump -i eth0 -v -s0 udp and dst port 53 and dst 192.168.16.2
如果不确定是哪个网卡,可以用-i any让tcpdump抓取所有网卡的流量:
tcpdump -i any -v -s0 udp and dst port 53 and dst 192.168.16.2
解决方法3:调整权限和过滤规则
确保用root权限运行tcpdump(或者加sudo),同时尝试去掉所有过滤规则,先抓所有UDP包验证:
sudo tcpdump -i any -v -s0 udp
内容的提问来源于stack exchange,提问作者Shuzheng

