首页 » PHP教程 » phpfilterframework技巧_Linux 收集层收发包流程及 Netfilter 框架浅析

phpfilterframework技巧_Linux 收集层收发包流程及 Netfilter 框架浅析

访客 2024-11-25 0

扫一扫用手机浏览

文章目录 [+]

内容如有理解缺点而导致解释缺点的地方,还请示正。
如存在引用而没有添加解释的,也请及时奉告,非常感谢!

2. 根本网络知识2.1 网络分层模型

OSI 模型中将网络划分为七层,但在目前实际广泛利用的 TCP/IP 协议框架体系内,我们一样平常将网络划分为五层,从下到上依次为物理层,链路层,网络层,传输层以及运用层。
两者的差异在于 OSI 模型在运用层对数据包做了更细致的划分。
两者的关系如下图所示:

phpfilterframework技巧_Linux 收集层收发包流程及 Netfilter 框架浅析

图片来源:https://www.cnblogs.com/qishui/p/5428938.html

phpfilterframework技巧_Linux 收集层收发包流程及 Netfilter 框架浅析
(图片来自网络侵删)

在 TCP/IP 协议框架体系的五层网络模型中,每一层卖力处理的数据包协议或类型均存在差异,物理层紧张卖力在物理载体上的数据包传输,如 WiFi,以太网,光纤,电话线等;数据链路层紧张卖力链路层协议解析(紧张为以太网帧,其他类型此处暂不考虑),网络层紧张卖力 IP 协议(包括 IPv4 和 IPv6)解析,传输层卖力传输层协议解析(紧张为 TCP,UDP 等),而传输层以上我们均归类为运用层,紧张包括各种运用层协议,如我们常用的 HTTP,FTP,SMTP,DNS,DHCP 等。

在 TCP/IP 协议框架体系内,下层协议对上层协议透明,即上层协议无需关注下层协议的实现逻辑和机制。

2.2 数据包协议分层

在 TCP/IP 协议框架体系内,上层协议报文被作为下层协议的数据载荷(Data Payload),存储不才层协议的数据段区域中进行传输。
结合这一特性,我们常见的几类网络协议嵌套关系如下图所示:

从上图我们可以清晰地看到各种协议之间的嵌套关系,如利用 HTTP 协议的运用 App1 在传输层封装在 TCP 协议中,TCP 协议在网络层又封装到 IP 协议中,末了交到数据链路层中。
其他运用层 App 也类似。

网际报文掌握协议(ICMP,利用该协议的 Ping 工具),以及网际组管理协议(IGMP,组播多播中的掌握报文)是直接嵌套到 IP 数据包中,而不依赖于 TCP 或 UDP。

地址解析协议(ARP)和反解析协议(RARP)则是直接嵌套在数据链路层数据包中进行传输。

注:在本文中,我们只大概理解整体的网络框架,各协议的详细内容这里不做赘述。

2.3 sk_buff 构造

在 Linux 内核中,系统利用 sk_buff 数据构造对数据包进行存储和管理。
在数据包吸收过程中,该数据构造从网卡驱动收包开始,一贯贯穿到内核网络协议栈的顶层,直到用户态程序从内核获取数据。
利用图形表示 sk_buff 的构造如下:

在 sk_buff 数据构造中包含了诸多关于数据包存储,定位和管理的指针,数据包在网络协议栈各层次之间进行传输的过程中,内核通过操作指针的办法对数据包进行逐层解析,避免频繁的大数据段拷贝操作,从而提高数据包处理效率(但在某些分外情形下依然会采取数据包拷贝操作)。

2.4 收发包整体框架

这里我们从客户端和做事端整体框架层面来看数据收发流程:

用户态(User Space)程序 Client 向另一台主机上的 Server 发送数据,须要通过调用内核态(Kernel Space)供应给用户态的 Socket 抽象层接口发送数据;Socket 抽象层接口收到用户态数据后,向下交给传输层接口(TCP 或 UDP);传输层卖力创建 sk_buff,并将用户数据(运用层数据)添补到缓冲区,做合法性检讨后,添加传输层头部,并通过网络层注册的接口将数据包交给网络层处理;网络层收到传输层数据包后,会查询路由表,决定数据包去向,如果是须要发出的数据包,会添补网络层头部,并交到内核虚拟网络接口设备的发送行列步队中;虚拟网络接口从发送行列步队获取数据,调用对应网卡驱动发送数据;

Server 端吸收数据时,按照相反的过程从网卡驱动中将数据包一层层上交,直到通过 Socket 抽象层接口将用户数据上交到用户态 Server 进程处理。

3. 网络层(IPv4)收发包流程

数据包在实际现网传输过程中,会经由各种交流机,路由器的转发处理,在这个过程中,路由器一样平常只处理到网络层。
这里我们仅对 Linux 内核中网络层吸收,发送以及转发数据的流程进行大略先容。

下图为基于 Linux 2.6.38 版本内核的网络层干系接口在数据包收发过程的调用逻辑图:

注:

1)不同版本内核在函数名上可能存在一定差异,但整体调用逻辑基本不变;

2)该图仅展示 IPv4 的处理流程,IPv6 不在该图的函数中处理,但整体流程基本相似;

3)该图展示的流程仅为普通单播并且未进行 IP 分片的数据包处理流程,组播,多播,IP 分片的数据包在某些流程上存在差异;

从图中可以看到,ip_rcv函数为网络层向下层开放的入口,数据包通过该函数进入网络层进行处理,该函数紧张对上传到网络层的数据包进行前期合法性检讨,通过后交由 Netfilter 的钩子节点;绿色方框内的IP_PRE_ROUTING为 Netfilter 框架的 Hook 点,该节点会根据预设的规则对数据包进行讯断并根据讯断结果做干系的处理,比如实行 NAT 转换;IP_PRE_ROUTING节点处理完成后,数据包将交由ip_rcv_finish处理,该函数根据路由讯断结果,决定数据包是交由本机上层运用场置,还是须要进行转发;如果是交由本机处理,则会交由ip_local_deliver走本地上互换程;如果须要转发,则交由ip_forward函数走转发流程;在数据包上交本地的流程中,IP_LOCAL_INPUT节点用于监控和检讨上交到本地上层运用的数据包,该节点是 Linux 防火墙的主要生效节点之一;在数据包转发流程中,Netfilter 框架的IP_FORWARD节点会对转发数据包进行检讨过滤;而对付本机上层发出的数据包,网络层通过注册到上层的ip_local_out函数吸收数据处理,处理 OK 进一步交由IP_LOCAL_OUT节点检测;对付即将发往下层的数据包,须要经由IP_POST_ROUTING节点处理;网络层处理结束,通过dev_queue_xmit函数将数据包交由 Linux 内核中虚拟网络设备做进一步处理,从这里数据包即离开网络层进入到下一层;4. Netfilter 框架

Netfilter 是 Linux 内核中进行数据包过滤,连接跟踪(Connect Track),网络地址转换(NAT)等功能的紧张实现框架;该框架在网络协议栈处理数据包的关键流程中定义了一系列钩子点(Hook 点),并在这些钩子点中注册一系列函数对数据包进行处理。
这些注册在钩子点的函数即为设置在网络协议栈内的数据包通畅策略,也就意味着,这些函数可以决定内核是接管还是丢弃某个数据包,换句话说,这些函数的处理结果决定了这些网络数据包的“命运”。

下图为 Netfilter 框架的整体组件图:

图片来源:http://wiki.dreamrunner.org/public_html/Linux/Networks/netfilter.html

从图中我们可以看到,Netfilter 框架采取模块化设计理念,并且贯穿了 Linux 系统的内核态和用户态。
在用户态层面,根据不同的协议类型,为上层用户供应了不同的系统调用工具,比如我们常用的针对 IPv4 协议 iptables,IPv6 协议的 ip6tables,针对 ARP 协议的 arptables,针对网桥掌握的 ebtables,针对网络连接追踪的 conntrack 等等。
不同的用户态工具在内核中有对应的模块进行实现,而底层都须要调用 Netfilter hook API 接口进行实现。

从图中我们可以看到,我们常用的 Linux 防火墙工具 iptables 实在也是 Netfilter 框架中的一个组件。
接下来我们就以 IPv4 为例,描述 iptables 在 Netfilter 框架中生效的基本事理,同时,我们也看一下如果我们希望在内核中添加我们自己的处理函数,我们该怎么做。

4.1 IPv4 网络层的 Netfilter Hook 点

在第二章已经提及,Linux 内核中,Netfiler 在网络层设置了多个 Hook 点,这里我们不考虑实际的处理函数,仅看 Netfilter 的钩子节点,从而将网络层处理流程进行简化,如下图:

个中,矩形方框中的即为 Netfilter 的钩子节点。
从图中可以看到,三个方向的数据包须要经由的钩子节点不完备相同:

发往本地:NF_INET_PRE_ROUTING-->NF_INET_LOCAL_IN转发:NF_INET_PRE_ROUTING-->NF_INET_FORWARD-->NF_INET_POST_ROUTING本地发出:NF_INET_LOCAL_OUT-->NF_INET_POST_ROUTING4.2 iptables 工具

iptables 在用户态供应了表格和链的观点。
包含的表格有 filter,nat,mangle 以及 raw。
而每个表格下包含不同的链,如下图所示:

iptables 中每个表格的浸染不同,以我们比较常用的 filter 表为例,其紧张起到数据包过滤和拦截浸染,包含 INPUT,FORWARD 和 OUTPUT 三个链,根据链的名字我们可以知道,这三个链分别被放置到 Netfilter 三个不同的钩子节点中生效。
INPUT 链是在NF_INET_LOCAL_IN节点,FORWARD 链是在NF_INET_FORWARD节点,OUTPUT 链则是在NF_INET_LOCAL_OUT节点。
其他表格的链也类似。

以如下 iptables 指令为例:

iptables -t filter -A INPUT -s 172.16.0.0/16 -p udp --dport 53 -j DROP

该指令是在 filter 表的 INPUT 链中添加一条过滤规则,凡是收到源地址为 172.16.0.0/16,传输层协议为 UDP 并且目的端口为 53 的数据包(即 DNS 数据包),都将该数据包丢弃。
在 Linux 内核中,这一个指令会在 Netfilter 网络层NF_INET_LOCAL_IN节点天生处理操作,凡是经由这个钩子节点的数据包,在前面规则都通过的情形下,都必须经由这一规则的检讨,如果符合这条规则的匹配条件,则该数据包会被丢弃;如果不符合,则进行下一条规则的匹配。

在 Linux 内核内部,利用 iptables 工具下发的指令规则,会存储在内核中的 Xtables 模块中,这部分内容这里不再深入剖析。

4.3 Netfilter 主要数据构造及干系函数钩子点列举类型

上面提到的网络层中 Netfilter 的几个钩子节点,在内核中因此列举数据类型进行标记的。
如下:

// include/linux/netfilter.henum nf_inet_hooks { NF_INET_PRE_ROUTING, NF_INET_LOCAL_IN, NF_INET_FORWARD, NF_INET_LOCAL_OUT, NF_INET_POST_ROUTING, NF_INET_NUMHOOKS};注册和解注册钩子函数

// include/linux/netfilter.h/ Function to register/unregister hook points. /int nf_register_hook(struct nf_hook_ops reg);void nf_unregister_hook(struct nf_hook_ops reg);int nf_register_hooks(struct nf_hook_ops reg, unsigned int n);void nf_unregister_hooks(struct nf_hook_ops reg, unsigned int n);

这些函数用于将自定义的钩子操作(struct nf_hook_ops)注册到指定的钩子节点中。

钩子操作数据构造

// include/linux/netfilter.hstruct nf_hook_ops { struct list_head list; / User fills in from here down. / nf_hookfn hook; struct module owner; u_int8_t pf; unsigned int hooknum; / Hooks are ordered in ascending priority. / int priority;};

这个构造体中存储了自定义的钩子函数(nf_hookfn),函数优先级(priority),处理协议类型(pf),钩子函数生效的钩子节点(hooknum)等信息。

钩子函数声明

// include/linux/netfilter.htypedef unsigned int nf_hookfn(unsigned int hooknum, struct sk_buff skb, const struct net_device in, const struct net_device out, int (okfn)(struct sk_buff ));

如果我们自己实现一个内核模块,该模块须要在 Netfilter 框架的几个钩子节点中对经由的数据包进行处理,则该内核模块须要向 Netfilter 中的钩子节点注册钩子函数,我们须要按照 nf_hookfn 函数的声明类型,供应我们自己的实现,再按照之前供应的注册接口将干系数据类型注册到内核中使之生效。

4.4 一个 Demo

如下为在网络上找到的一个内核模块 Demo,该模块的基本功能是将经由 IPv4 网络层 NF_INET_LOCAL_IN 节点的数据包的源 Mac 地址,目的 Mac 地址以及源 IP,目的 IP 打印出来。
代码如下所示:

#include <linux/module.h>#include <linux/kernel.h>#include <linux/types.h>#include <linux/skbuff.h>#include <linux/ip.h>#include <linux/udp.h>#include <linux/tcp.h>#include <linux/netfilter.h>#include <linux/netfilter_ipv4.h>MODULE_LICENSE("GPLv3");MODULE_AUTHOR("SHI");MODULE_DESCRIPTION("Netfliter test");static unsigned intnf_test_in_hook(unsigned int hook, struct sk_buff skb, const struct net_device in, const struct net_device out, int (okfn)(struct sk_buff));static struct nf_hook_ops nf_test_ops[] __read_mostly = { { .hook = nf_test_in_hook, .owner = THIS_MODULE, .pf = NFPROTO_IPV4, .hooknum = NF_INET_LOCAL_IN, .priority = NF_IP_PRI_FIRST, },};void hdr_dump(struct ethhdr ehdr) { printk("[MAC_DES:%x,%x,%x,%x,%x,%x" "MAC_SRC: %x,%x,%x,%x,%x,%x Prot:%x]\n", ehdr->h_dest[0],ehdr->h_dest[1],ehdr->h_dest[2],ehdr->h_dest[3], ehdr->h_dest[4],ehdr->h_dest[5],ehdr->h_source[0],ehdr->h_source[1], ehdr->h_source[2],ehdr->h_source[3],ehdr->h_source[4], ehdr->h_source[5],ehdr->h_proto);}#define NIPQUAD(addr) \ ((unsigned char )&addr)[0], \ ((unsigned char )&addr)[1], \ ((unsigned char )&addr)[2], \ ((unsigned char )&addr)[3]#define NIPQUAD_FMT "%u.%u.%u.%u"static unsigned intnf_test_in_hook(unsigned int hook, struct sk_buff skb, const struct net_device in, const struct net_device out, int (okfn)(struct sk_buff)) { struct ethhdr eth_header; struct iphdr ip_header; eth_header = (struct ethhdr )(skb_mac_header(skb)); ip_header = (struct iphdr )(skb_network_header(skb)); hdr_dump(eth_header); printk("src IP:'"NIPQUAD_FMT"', dst IP:'"NIPQUAD_FMT"' \n", NIPQUAD(ip_header->saddr), NIPQUAD(ip_header->daddr)); return NF_ACCEPT;}static int __init init_nf_test(void) { int ret; ret = nf_register_hooks(nf_test_ops, ARRAY_SIZE(nf_test_ops)); if (ret < 0) { printk("register nf hook fail\n"); return ret; } printk(KERN_NOTICE "register nf test hook\n"); return 0;}static void __exit exit_nf_test(void) { nf_unregister_hooks(nf_test_ops, ARRAY_SIZE(nf_test_ops));}module_init(init_nf_test);module_exit(exit_nf_test);

该 Demo 为网络上找到的 Demo 程序,地址:http://wiki.dreamrunner.org/public_html/Linux/Networks/netfilter.html

这个 Demo 程序是个内核模块,模块入口为module_init传入的init_nf_test函数。

在init_nf_test函数中,其通过 Netfilter 供应的 nf_register_hooks 接口将自定义的nf_test_opt注册到钩子节点中。
nf_test_opt为struct nf_hook_ops类型的构造体数组,其内部包含了所有关键元素,比如钩子函数的注册节点(此处为NF_INET_LOCAL_IN)以及钩子函数(nf_test_in_hook)。

在nf_test_in_hook函数内部,其检讨每一个通报过来的数据包,并将其源 Mac 地址,目的 Mac 地址,源 IP 地址以及目的 IP 地址打印出来。
末了返回NF_ACCEPT,将数据包交给下一个钩子函数处理。

4.5 NAT 和 conntrack

NAT(Network Address Translation)技能现如今被广泛运用于路由器等网络设备中,其在办理 IPv4 地址紧缺的问题上起到了至关主要的浸染,但与此同时也存在一定的安全隐患。

而 conntrack(连接追踪)也是广泛运用于路由器网络设备中的模块,其根据数据包的五元组以及 NAT 的转换结果,记录每一条连接的状态,在提升设备转发效率上起到了很大的浸染,但另一方面,记录连接信息须要花费一部分资源,也会导致设备涌现性能瓶颈。

5. 总结

Linux 网络协议栈是 Linux 内核中非常主要的子系统之一,虽然上层运用的开拓掩护事情极少涉及修正内核网络部分的事情,但理解其设计思想,基本事情事理,也可以为我们日常事情带来比较不少的帮助,特殊是涉及到前后台网络交互,做事器网络性能干系的事情时。

这篇文章所涉及的内容也仅仅是 Linux 网络协议栈中网络层的极小一部分,如下为 Linux 内核中数据包流向的整体脉络图以及 Netfilter 的整体生效节点:

图片来源: http://wiki.dreamrunner.org/public_html/Linux/Networks/netfilter.html

从上图可以看到,除了在网络层,链路层中 Netfilter 也被广泛地运用,ebtables 是 Netfilter 供应给用户态的链路层配置接口(工具),其生效机制与 iptables 基本类似。

6. 扩展

这篇文章仅仅对 Linux 内核中网络层数据处理流程以及 Netfilter 基本事理进行大略先容,在此根本上,关于 Linux 内核网络协议栈的其他技能还包括:

Linux TC(Traffic Control)模块:Linux 供应的 QoS 功能支持模块;网桥和 VLAN 技能;Wireshark(tcpdump)等网络抓包工具的基本实现事理;7. 参考

博客

Linux Netfilter and Traffic ControlOSI 七层模型与 TCP/IP 五层模型

书本

《TCP/IP 详解 卷 I:协议》《深入理解 Linux 网络技能底细》
标签:

相关文章

五一十字,传承红色基因,弘扬民族精神

五一十字,一个饱含红色基因的词汇,承载着中国人民为实现民族独立、人民解放、国家富强而不懈奋斗的历史记忆。如今,在全面建设社会主义现...

PHP教程 2024-12-27 阅读0 评论0

乐学网,开启智能教育新篇章

随着科技的飞速发展,人工智能在教育领域的应用日益广泛。作为国内领先的在线教育平台,乐学网凭借其先进的技术和优质的服务,为广大学习者...

PHP教程 2024-12-27 阅读0 评论0

绵阳IT产业,崛起中的西部硅谷

近年来,随着我国西部大开发战略的深入推进,绵阳市凭借其独特的区位优势、丰富的科教资源以及良好的产业基础,逐渐成为我国西部地区的IT...

PHP教程 2024-12-27 阅读0 评论0

网络直播的争吵,文明交流还是恶意宣泄

随着互联网的普及,网络直播成为了人们获取信息、娱乐休闲的重要途径。近年来,直播平台上的争吵事件频发,引发了社会各界的广泛关注。本文...

PHP教程 2024-12-27 阅读0 评论0

网管IT招聘,解码新时代技术人才的摇篮

随着互联网技术的飞速发展,我国IT行业迎来了前所未有的机遇。在这个技术变革的时代,网管IT人才的招聘成为各大企业争相追逐的热点。本...

PHP教程 2024-12-27 阅读0 评论0

主流编程语言介绍,技术发展的风向标

在信息技术飞速发展的今天,编程语言作为软件开发的基石,其重要性不言而喻。近年来,随着互联网、大数据、人工智能等领域的爆发式增长,主...

PHP教程 2024-12-27 阅读0 评论0