继上一篇vlan学习笔记大致理清Linux内核的网络收发架构后,我们可以发现,在网络收发的路径上,基本上每一个连接点都可以做网络截包,如果说L1驱动截包和L3netfilter截包是在必经之路上设伏的话,那L2虚拟设备,L3自定义协议等,就是在大路旁开出一条小路来劫道了。
网络截包是一项很有意思的课题,可以有数据过滤,防火墙,流量控制,报文篡改等诸多应用,按照内核分层架构将一些截包方法不完全整理如下,欢迎补充。
1、 L1层驱动截包法
在驱动中下手应该可以说是最贴近底层的,网卡驱动中总有rx接收和xmit发送函数,参数总是sk_buffer,在这里修改很黄很暴力,而且几乎不需要什么linux内核的知识。
xmit函数调用时的参数sk_buffer已经是一个发育健全的成熟体,因此在这里做过滤那真是得心应手美呆了,当然修改的时候还是要下一番功夫,而rx的时候则相反,可怜的sk_buffer在这时候只发育了链路层(L2)头部,一旦涉及到较为复杂的过滤,则需要做一些模拟协议栈的分析,如需要获取udp端口,就要从sk_buffer中先取出L3 IP层的长度,对sk_buffer->data作相应位移。
2、 L2层虚拟设备截包法
与具体网卡设备无关,通过register_netdevice注册一个net_device结构,在驱动层上虚拟一个设备节点(ethx.y),来实现截包,通过设置路由,让需要拦截的报文通过该设备节点发出,从而实现过滤。
正是因为需要结合路由来使用,该方法显得特别优雅,对目的IP的过滤甚至在路由设置中就已经完成,避免其他无关报文不必要的拦截判断。虚拟设备拦截到的sk_buffer也已经基本成熟了,可以方便的过滤。
可惜佛说,优点即缺点,正是因为需要结合路由使用,该法对接收报文的过滤和修改无能为力(如果理解有误欢迎指正)。
3、 L3层自定义协议截包法
又是非常优雅的做法,通过dev_add_pack注册packet_type结构,挂接上自定义协议的收发流程,就算Linux升级到3.0 4.0,估计也能轻易的移植。
可惜该方法只能拦截接收的报文,而且只能拦截该协议的报文,多用于正规协议开发,不适用于一些小功能实现。
4、 L3层netfilter截包法
netfilter是linux内核自带的正规防火墙,转一个netfilter钩子分布图:
可以发现,netfilter钩子虽然不多,但是遍布协议栈的各个关键路径,通过这些钩子就可以基本实现二层以上报文的过滤和删改。
5、 应用层raw socket截包法
原始套接字也是常用的截包方法,可惜功能有限。内核处理的所有其它类型的数据包都会传一个拷贝给匹配的原始套接字,但是方便监听的同时是修改上的无力,因为得到的数据仅仅是个拷贝。而原始套接字对于其他线程发送的报文更是无能为力。
6、 应用层pcap软件包截包法
pcap的linux版本是libpcap函数库(在Windows下对应的函数库为Winpcap),libpcap有几个主要的调用函数,通过这些就可以看出libpcap的基本功能。
1)确定捕获网络数据包的网卡。
char *pcap_lookupdev(dev *errbuf);
2)设置过滤条件。
int pcap_compile(pcap_t *p, struct bpf_program *fp, char *str, int optimize, bpf_u_int32 netmask)
3)获取数据包。
const u_char *pcap_next(pcap_t *p, struct pcap_pkthdr *h)
总结:
L1层驱动截包法
优点:因为暴力所以方便,不需要对linux内核有很深入地了解,过滤输出的报文很简单。
缺点:与设备相关,扩展性差,对接收到的报文要做很复杂的修改相对麻烦。
适用:开发周期短,功能相对简单,不需要对接收报文做三层以上复杂过滤的情况。
L2层虚拟设备截包法
优点:与具体设备和协议无关,扩展性好,高效,通过修改路由也可以有很多更多功能的应用。
缺点:只能截获发出的报文,要结合路由使用。
适用:需要考虑扩展性或者多网卡支持的情况,或者基于路由的一些特殊应用。
L3层自定义协议截包法
优点:通过协议头来过滤报文,可读性和扩展性好。
缺点:因为优雅所以麻烦,只能截获接收的报文。
适用:有专用协议头的情况。
L3层netfilter截包法
优点:netfilter框架严密,钩子点很有代表性,易扩展,易维护,很容易作为一个单独的可加载模块来开发,方便调试。
缺点:修改3层以下的报文相对困难。
适用:不需要修改3层以下报文头的情况,应该是用途广的截包方法了。
应用层raw socket截包法
优点:在用户态运行就可以方便的监听想要的各种报文。
缺点:无力删改报文,无力截获其他线程发送的报文。
适用:只监听不修改的情况。
应用层pcap软件包截包法
优点:开发简单,而且libpcap库能大大简化对报文的分析工作。
缺点:需要libpcap库支持,无力删改报文,无力截获其他线程发送的报文。
适用:只监听不修改的情况。
当然,网络截包还有一个很重要的考虑因素就是性能,对于接收报文的拦截来说,偏底层的截包法
效率较高,而对于发送报文的拦截,偏上层的截包法效率更高。
佛说,没有最好的,只有最合适的,所以做网络报文截取的时候要综合考虑实际需求,采用最合适
的方法,就能事半功倍。