netfilter linux net core docker
Linux 网络层收发包流程及 Netfilter 框架浅析
本文主要对 Linux系统内核协议栈中网络层接收,发送以及转发数据包的流程进行简要介绍,同时对 Netfilter数据包过滤框架的基本原理以及使用方式进行简单阐述。
在 TCP/IP协议框架体系的五层网络模型中,每一层负责处理的数据包协议或类型均存在差异,物理层主要负责在物理载体上的数据包传输,链路层主要负责链路层协议解析(主要为以太网帧),网络层主要负责 IP协议(包括 IPv4和 IPv6)解析,传输层负责传输层协议解析(主要为 TCP,UDP等),而传输层以上我们均归类为应用层,主要包括各类应用层协议,如 HTTP,FTP,SMTP,DNS,DHCP等。在 TCP/IP协议框架体系内,下层协议对上层协议透明,即上层协议无需关注下层协议的实现逻辑和机制。
在 Linux内核中,系统使用 sk_buff数据结构对数据包进行存储和管理。在数据包接收过程中,该数据结构从网卡驱动收包开始,一直贯穿到内核网络协议栈的顶层,直到用户态程序从内核获取数据。
数据包在实际现网传输过程中,会经过各类交换机,路由器的转发处理,在这个过程中,路由器一般只处理到网络层。这里我们仅对 Linux内核中网络层接收,发送以及转发数据的流程进行简单介绍。
Netfilter是 Linux内核中进行数据包过滤,连接跟踪(Connect Track),网络地址转换(NAT)等功能的主要实现框架;该框架在网络协议栈处理数据包的关键流程中定义了一系列钩子点(Hook点),并在这些钩子点中注册一系列函数对数据包进行处理。这些注册在钩子点的函数即为设置在网络协议栈内的数据包通行策略,也就意味着,这些函数可以决定内核是接受还是丢弃某个数据包。
iptables在用户态提供了表格和链的概念,包含的表格有 filter,nat,mangle以及 raw,每个表格下包含不同的链,iptables中每个表格的作用不同,如 filter表主要起到数据包过滤和拦截作用,包含 INPUT,FORWARD和 OUTPUT三个链,根据链的名字我们可以知道,这三个链分别被放置到 Netfilter三个不同的钩子节点中生效。
Netfilter在内核中是以枚举数据类型进行标记的,其几个钩子节点的函数用于将自定义的钩子操作(struct nf_hook_ops)注册到指定的钩子节点中。这个结构体中存储了自定义的钩子函数(nf_hookfn),函数优先级(priority),处理协议类型(pf),钩子函数生效的钩子节点(hooknum)等信息。如果我们自己实现一个内核模块,该模块需要在 Netfilter框架的几个钩子节点中对经过的数据包进行处理,则该内核模块需要向 Netfilter中的钩子节点注册钩子函数。
了解 Linux网络协议栈设计思想和基本工作原理,对于日常工作中的前后台网络交互和服务器网络性能相关工作非常有帮助。
洞悉linux下的Netfilter&iptables:什么是Netfilter
Netfilter是什么?Netfilter是Linux 2.4.x版本内核引入的一个子系统,它作为一个通用的、抽象的框架,提供了一整套的hook函数管理机制,使得诸如数据包过滤、网络地址转换(NAT)和基于协议类型的连接跟踪成为可能。
Netfilter在内核中的位置如图所示,直观地展示了用户空间的iptables和内核空间基于Netfilter的ip_tables模块之间的关系及其通信方式,以及Netfilter在其中所扮演的角色。Netfilter通过将协议栈的五个关键点A、B、C、D和E重新命名,使得数据包的处理过程更为明确。
在每个关键点上,预先注册了按照优先级排列的回调函数,形成了一条链。对于每个到来的数据包,会依次经过这些回调函数的“处理”,决定是放行、丢弃还是其他操作。无论如何,每个回调函数最后必须向Netfilter报告数据包的状态。
Netfilter通过NF_HOOK宏在协议栈内部切入到Netfilter框架中,允许开发者在关键点上注册回调函数,实现对数据包的定制化处理。在2.6版本的内核中,NF_HOOK宏的定义更为灵活。
Netfilter使用一个二维的结构体数组nf_hooks来存储不同协议栈钩子点的回调处理函数,该数组的行数为32,表示目前内核支持的最大协议簇,列数为8,表示挂载点的数量。通过这个数组,可以为特定的协议族注册钩子函数。
例如,对于TCP/IP协议族,其钩子函数挂载点为nf_hooks[2][0]。根据内核流程,IP报文会首先传到Netfilter的NF_IP_PRE_ROUTING过滤点,检查该点是否已注册有用于处理数据包的钩子函数。如果有,则逐个遍历该过滤点下的钩子函数,根据返回值决定数据包的后续处理方式。
经过路由抉择后,需要本机转发的报文会交由ip_forward函数处理,该函数从NF_IP_FOWARD过滤点切入到Netfilter框架。对于发给本机的数据包,会先检测nf_hooks[2][1]过滤点,判断是否有相关回调处理函数。对于从本机发出的报文,则会先过滤nf_hooks[2][3]过滤点。
Netfilter框架的HOOK机制可以总结为:在数据包流经内核协议栈的整个过程中,在已预定义的关键点上(如PRE_ROUTING、LOCAL_IN、FORWARD、LOCAL_OUT和POST_ROUTING)检查是否注册有钩子函数。如果没有,则继续走协议栈;如果有,则调用nf_hook_slow函数,进一步调用注册在该过滤点下的钩子函数,并根据其返回值决定后续操作。
linux Netfilter在网络层的实现详细分析(iptables)
Linux netfilter在网络层的实现细节分析主要基于Linux内核版本4.18.0-80。
我绘制了一张Linux内核协议栈网络层netfilter(iptables)的全景图,其中包含了许多内容,以下将详细讲解。
INGRESS入口钩子是在Linux内核4.2中引入的。与其他netfilter钩子不同,入口钩子附加到特定的网络接口。可以使用带有ingress钩子的nftables来实施非常早期的过滤策略,甚至在prerouting之前生效。请注意,在这个非常早期的阶段,碎片化的数据报尚未重新组装,例如匹配ip saddr和daddr适用于所有ip数据包,但匹配传输层的头部(如udp dport)仅适用于未分段的数据包或第一个片段,因此入口钩子提供了一种替代tc入口过滤的方法,但仍需tc进行流量整形。
Netfilter/iptables由table、chain和规则组成。
iptables的链(chain)
netfilter在网络层安装了5个钩子,对应5个链,还可以通过编写内核模块来扩展这些链的功能。
⑴五个链(chain)及对应钩子
以下是网络层五条链的位置图:
①网络数据包的三种流转路径
②源码中网络层的5个hook的定义
include\uapi\linux etfilter_ipv4.h
在include\uapi\linux etfilter.h中有对应的hook点定义:
注:在4.2及以上版本内核中又增加了一个hook点NF_NETDEV_INGRESS:
为NFPROTO_INET系列添加了NF_INET_INGRESS伪钩子。这是将这个新钩子映射到现有的NFPROTO_NETDEV和NF_NETDEV_INGRESS钩子。该钩子不保证数据包仅是inet,用户必须明确过滤掉非ip流量。这种基础结构使得在nf_tables中支持这个新钩子变得更容易。
iptables的表
⑴五张表(table)
以下是五张表分布在对应链上的图:
相关视频推荐
免费学习地址:Linux C/C++开发(后端/音视频/游戏/嵌入式/高性能网络/存储/基础架构/安全)
需要C/C++ Linux服务器架构师学习资料加qun 579733396获取(资料包括C/C++,Linux,golang技术,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,TCP/IP,协程,DPDK,ffmpeg等),免费分享
⑵源码中IP层的表的定义
netfilter中的表的定义
include\linux etfilter\x_tables.h
网络层各hook点的优先级
数值越低优先级越高:
include\uapi\linux etfilter_ipv4.h
下面我们看下netfilter/iptables的这几张表在内核源码中的定义。
①raw表
源码里RAW_VALID_HOOKS宏可以看出raw表只有NF_INET_PRE_ROUTING、NF_INET_LOCAL_OUT链有效。
②mangle表
源码中valid_hooks参数可以看出mangle表对NF_INET_PRE_ROUTING、NF_INET_LOCAL_IN、NF_INET_FORWARD、NF_INET_LOCAL_OUT、NF_INET_POST_ROUTING五条链都有效。
③nat表
valid_hooks变量可以看出nat表只有NF_INET_PRE_ROUTING、NF_INET_POST_ROUTING、NF_INET_LOCAL_OUT、NF_INET_LOCAL_IN四条链有效。
④filter表
源码中valid_hooks参数可以看出filter表对NF_INET_LOCAL_IN、NF_INET_FORWARD、NF_INET_LOCAL_OUT三条链有效。
网络层的五张表在内核中对应了五个内核模块:
3、Netfilter在网络层安装的5个hook点
下面我们看下网络层的各个hook点安装的位置:
⑴、NF_INET_PRE_ROUTING
它是所有传入数据包到达的第一个hook点,它是在路由子系统中执行查找之前。这个钩子在IPv4的ip_rcv()方法中,在IPv6的ipv6_rcv()方法中。
①net\ipv4\ip_input.c
②net\ipv4\xfrm4_input.c
⑵、NF_INET_LOCAL_IN
这个钩子在IPv4的ip_local_deliver()方法中,在IPv6的ip6_input()方法中。所有路由到本地主机的数据包都会到达此hook点,它是在首先通过NF_INET_PRE_ROUTING hook点并在路由子系统中执行查找之后进到这里。
net\ipv4\ip_input.c
⑶、NF_INET_FORWARD
①net\ipv4\ip_forward.c
②net\ipv4\ipmr.c
⑷、NF_INET_LOCAL_OUT
①net\ipv4\ip_output.c
②net\ipv4\raw.c
⑸、NF_INET_POST_ROUTING
net\ipv4\ip_output.c
以上我们看到xfrm中也有安装相关hook点,这里引用官方资料介绍下什么是xfrm:
xfrm是IP层的一个框架,用于封装实现IPSec协议。
简单来说,xfrm就是IP层的一个框架,用于封装实现IPSec协议。
到此,我们基于源码分析介绍完了Netfilter在网络层的实现。