关于Linux LOOPBACK网口抓包的一个细节

这个问题其实是我几个月前碰到,只是那时好像还在回忆着什么,心系上海,还没有完全适应这个新环境,加上这个问题也不是什么太深奥的问题,觉得太简单了,就搁置了。今天周末闲来无事就顺便写来来了。加上深圳经常下雨,越来越喜欢了。

本文没什么深度,仅为记录,以及阐述一个“看文档学习原理->猜测并自行实现->对比标准实现确认”的方法。

问题是这样的:
在Linux上如果使用tcpdump去抓取lo口的数据包,你只能抓到一遍,而不是两遍,按常理来讲,数据包在outgoing路径上和incoming路径上都会被抓到,对于lo口而言,两个路径都要经过它本身,为什么只能抓到一个呢?难道lo口做了什么特殊的处理吗?

依然是传统的三招破解:看文档学习原理,猜测实现,确认实现

1.看文档学习原理

最直接的就是先去man tcpdump,前面的参数详解部分可以不看,只看最后面的NOTES或者BUGS部分就好,其BUGS部分有一个细节正中这个话题:
BUGS
...
   On Linux systems with 2.0[.x] kernels:
          packets on the loopback device will be seen twice;
          packet filtering cannot be done in the kernel, so that all packets must be copied from the kernel in order to be filtered in user mode;
          all of a packet, not just the part that‘s within the snapshot length, will be copied from the kernel (the 2.0[.x] packet capture mechanism, if asked to copy only part of a packet to userland, will not report the true
          length of the packet; this would cause most IP packets to get an error from tcpdump);
          capturing on some PPP devices won‘t work correctly.

看样子已经说的很清楚了,“packets on the loopback device will be seen twice”描述了问题,“packet filtering cannot be done in the kernel, so that all packets must be copied from the kernel in order to be filtered in user mode”假装说明了原因。

2.猜测实现

如果在Linux内核内部对lo进行特殊的抓包过滤,那就太不靠谱了,如果有这么一个需求就这么过滤一次的话,内核会遍布if-else...switch-case...搞不好还要引入正儿八经的多态。内核只要提供足够的信息,用户态自己过滤即可。在看代码之前,做出以上猜测是合理的。

3.确认实现

最直接的先看内核代码的packet_rcv函数,这个函数是tcpdump抓包的入口函数(当然如果经过了PF_RING的优化,就不是这样了,但简单来讲,大多数就是这样):

static int packet_rcv(struct sk_buff *skb, struct device *dev,  struct packet_type *pt)
{
	struct sock *sk;
	struct sockaddr_ll *sll = (struct sockaddr_ll*)skb->cb;

	/*
	 *	When we registered the protocol we saved the socket in the data
	 *	field for just this event.
	 */

	sk = (struct sock *) pt->data;
	// 注意,PACKET_LOOPBACK只是和multicast相关的,与我们讨论的无关
	if (skb->pkt_type == PACKET_LOOPBACK) {
		kfree_skb(skb);
		return 0;
	}

	skb->dev = dev;

	sll->sll_family = AF_PACKET;
	sll->sll_hatype = dev->type;
	sll->sll_protocol = skb->protocol;
	sll->sll_pkttype = skb->pkt_type;
	sll->sll_ifindex = dev->ifindex;
	sll->sll_halen = 0;
...
}

然后看一下发送路径的处理:

void dev_queue_xmit_nit(struct sk_buff *skb, struct device *dev)
{
	...
	skb2->pkt_type = PACKET_OUTGOING;
	ptype->func(skb2, skb->dev, ptype);
	...
}

看来,PACKET_OUTGOING是一个核心的标志,它可以告诉tcpdump数据包是从哪里路径发出的。最后,我们看一下pcap的数据包读取函数pcap_read_linux_mmap:

if (sll->sll_pkttype == PACKET_OUTGOING) {
	/*
	 * Outgoing packet.
	 * If this is from the loopback device, reject it;
	 * we‘ll see the packet as an incoming packet as well,
	 * and we don‘t want to see it twice.
	 */
	if (sll->sll_ifindex == handle->md.lo_ifindex)
		goto skip;

	/*
	 * If the user only wants incoming packets, reject it.
	 */
	if (handle->direction == PCAP_D_IN)
		goto skip;
} 

直接看注释就好了。

只可惜,Linux 2.0的内核中,并没有提供这个PACKET_OUTGOING信息,抓上去的就是一个裸包,没有足够的信息,当然就无法区分两个方向了,这也是tcpdmp的manual中那个BUG的根源。这个BUG的解决也帮助我们理解了为什么lo口抓包只抓到一个方向的,而不是两遍。还让我们知道了,lo口抓包抓取的是incoming方向的数据包。

时间: 2024-10-12 05:23:03

关于Linux LOOPBACK网口抓包的一个细节的相关文章

[转]Linux操作系统tcpdump抓包分析详解

PS:tcpdump是一个用于截取网络分组,并输出分组内容的工具,简单说就是数据包抓包工具.tcpdump凭借强大的功能和灵活的截取策略,使其成为Linux系统下用于网络分析和问题排查的首选工具. tcpdump提供了源代码,公开了接口,因此具备很强的可扩展性,对于网络维护和入侵者都是非常有用的工具.tcpdump存在于基本的Linux系统中,由于它需要将网络界面设置为混杂模式,普通用户不能正常执行,但具备root权限的用户可以直接执行它来获取网络上的信息.因此系统中存在网络分析工具主要不是对本

linux使用tcpdump抓包工具抓取网络数据包,多示例演示

tcpdump是linux命令行下常用的的一个抓包工具,记录一下平时常用的方式,测试机器系统是ubuntu 12.04. tcpdump的命令格式 tcpdump的参数众多,通过man tcpdump可以查看tcpdump的详细说明,这边只列一些笔者自己常用的参数: tcpdump [-i 网卡] -nnAX '表达式' 各参数说明如下: -i:interface 监听的网卡. -nn:表示以ip和port的方式显示来源主机和目的主机,而不是用主机名和服务. -A:以ascii的方式显示数据包,

Linux命令行抓包及包解析工具tshark(wireshark)使用实例解析

在Linux下,当我们需要抓取网络数据包分析时,通常是使用tcpdump抓取网络raw数据包存到一个文件,然后下载到本地使用wireshark界面网络分析工具进行网络包分析. 最近才发现,原来wireshark也提供有Linux命令行工具-tshark.tshark不仅有抓包的功能,还带了解析各种协议的能力.下面我们以两个实例来介绍tshark工具.1.安装方法 CentOS: yum install -y wireshark    Ubuntu: apt-get install -y tsha

云计算之路-阿里云上:Wireshark抓包分析一个耗时20秒的请求

这篇博文分享的是我们针对一个耗时20秒的请求,用Wireshark进行抓包分析的过程. 请求的流程是这样的:客户端浏览器 -> SLB(负载均衡) -> ECS(云服务器) -> SLB -> 客户端浏览器. 下面是分析的过程: 1. 启动Wireshark,针对内网网卡进行抓包. 2. 在IIS日志中找出要分析的请求(借助Log Parser Studio) 通过c-ip(Client IP Address)可以获知SLB的内网IP,在分析Wireshar抓包时需要依据这个IP进

linux下简单抓包分析

有时候会遇到一些问题需要我们来抓包分析,当手头又没有专业的抓包工具的时候,可以用tcpdump来替代一下(一般的发行版都自带这个工具) 比如我们要分析一下eth0接口下跟192.168.7.188 这个目的IP地址22端口的发包情况 tcpdump -i eth0 dst 192.168.7.188 and port 22 tcpdump -i eth0 dst 192.168.7.188 and port 22 tcpdump: verbose output suppressed, use -

windows和linux下的抓包工具

Linux 抓包工具 tcpdump 示例 tcpdump  -i   bond0  host 10.70.11.182 -w  ./sms.cap windows抓包工具 常用静态式 ip.dst==211.137.124.14 or ip.src==211.137.124.14 原文地址:https://www.cnblogs.com/veryvalley/p/8447888.html

linux镜像数据抓包监控

主要是用户监控和分析进出设备端口报文和数据,根据目的端口抓包对出现故障进行分析. 1.三层交换机划分vlan 区别不同网段 2.三层交换机做端口镜像vlan32监控端口 vlan31为被监控端口 3.Centos5.6平台把bssgate和bssgate.ini拷贝到/bin文件夹,打开bssgate.ini修改下配置脚本. 4.Centos5.6平台的bin文件里面执行./bssgate文件

linux tcpdump命令抓包

tcpdump host 210.27.48.1 and \ (210.27.48.2 or 210.27.48.3 \) 截获主机210.27.48.1 和主机210.27.48.2 或210.27.48.3的通信 http://www.cnblogs.com/ggjucheng/archive/2012/01/14/2322659.html

wireshark抓包分析

wireshark抓包分析 wireshark是非常流行的网络封包分析软件,功能十分强大.可以抓取各种网络包,并显示网络包的详细信息. 开始界面 wireshark是捕获机器上的某一块网卡的网络包,当你的机器上有多块网卡的时候,你需要选择一个网卡. 点击Caputre->Interfaces.. 出现下面对话框,选择正确的网卡.然后点击"Start"按钮, 开始抓包 Wireshark 窗口介绍 WireShark 主要分为这几个界面 1. Display Filter(显示过滤