Netfilter 是如何工做的(一):HOOK点

写在前面

本系列不是介绍How to配置iptables的文章。由于网络上已经有不少这类型的教程了,其中一些还不错(好比连接).数组

本系列也不是通常意义上的Netfilter源码分析文章。由于大段粘贴代码也会让人心生畏惧和厌烦!网络

本系列文章的目标是,用尽可能少的文字和图片讲明白How Netfilter work框架

Netfilter 的基本概念

Netfilter是一套融入Linux内核网络协议栈中的报文处理(过滤或者修改)框架。它在内核中报文的关键流动路径上定义了5HOOK点(下图蓝色方框),各个协议(如IPv4IPv6ARP)能够在这些HOOK点安装钩子函数,报文流经此地,内核会按照优先级调用这些钩子函数,这些钩子函数最终会决定报文是被NF_ACCEPT(放行)仍是NF_DROP(丢弃)。函数

forward-model

图中红色虚线表示内核最多见的报文流经的路径:本机接收转发本机发送
5HOOK点分别是:路由前本地上送转发本地发送路由后1源码分析

链(chain) & 表(table)

初次接触iptables的同窗可能会被四表五链这个名字吓到,特别是这个名字真的很容易使人困惑! 而当你了解了Netfilter的实现细节后,才会发现:噢,原来就是HOOK点,HOOK点就是,由于有5HOOK点,因此有五链spa

那么,为何要叫呢?.net

由于一个HOOK点能够上能够安装多个钩子, 内核用“链条”将这些钩子串起来!设计

图片描述
相比之下,四表(table)就没那么神秘了: 起过滤做用的filter表、起NAT做用的nat表,用于修改报文的mangle表,用于取消链接跟踪的raw表。code

Netfilter设计多个表的目的,一方面是方便分类管理,另外一方面,更重要的是为了限定各个钩子(或者说用户规则)执行的顺序!教程

PREROUTING这个HOOK点为例,用户使用iptables设置的NAT规则和mangle会分别挂到nat hookmangle hookNAT表的优先级天生比mangle表低,所以报文必定会先执行mangle表的规则。

图片描述

这就是 四表五链 的概念。我我的认为 的比 重要多了. 由于就算 Netfilter没有表的概念,那么经过当心翼翼地设置各个 rule的顺序其实也能够达到相同的效果。但 (也就是 HOOK点)的做用是独一无二的。换个角度,用户在配置 iptables规则时,更多的精力也是放在 "应该在哪一个HOOK点进行操做",至于用的是 filter表、 nat表仍是其余表,其实都是瓜熟蒂落的事情。

Hook

HOOK 点的位置

用户经过iptables配置的规则最终会记录在HOOK点。HOOK点定义在struct net结构中,即HOOK点是各个net namespace中独立的。因此,在使用容器的场景中,每一个容器的防火墙规则是独立的。

struct net {
    /* code omitted */
    struct netns_nf        nf;
    /* code omitted */
}

struct netns_nf {
    /* code omitted */
    struct list_head hooks[NFPROTO_NUMPROTO][NF_MAX_HOOKS];
};

从上面的定义能够看到,HOOK点是一个二维数组,每一个元素都是一个链表头。它的第一个维度是协议类型,其中最经常使用的NFPROTO_IPV4,咱们使用的iptables命令都是将这个钩子安装到这个协议的hook,而使用ip6tables就是将钩子安装到NFPROTO_IPV6hook;第二个维度是,对于IPV4来讲,它的取值范围以下:

enum 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,
}

HOOK 点的元素

hooks的每一个元素都是链表头,链表上挂的元素类型是struct nf_hook_ops,这些元素有两个来源,一类来自于Netfilter初始化时各个表(如filter)的初始化,另外一类来自于如链接跟踪这样的内部模块。下图展现了第一类来源的元素的挂接状况,它们按优先级排列(数字越小优先级越高),而.hook就是报文到达对应的路径时会执行的钩子函数。

图片描述

附:相关内核函数的例子

iptable_filter_init 
  |--xt_hook_link
    |-- nf_register_hooks
       |-- nf_register_hook

HOOK 点的调用

Netfilter框架已经彻底融入内核协议栈了,因此在协议栈代码中经常能够看到NF_HOOK宏的调用,这个宏的参数指定了HOOK点。

以本机收到IPv4报文为例

int ip_rcv(struct sk_buff* skb,...)
{
   // code omitted
   return NF_HOOK(NFPROTO_IPV4, NF_INET_PRE_ROUTING, net, NULL, skb, dev, NULL, ip_rcv_finish); 
   // code omitted
}

它指定要遍历的钩子函数是net namespacenethooks[NFPROTO_IPV4][NF_INET_PRE_ROUTING]链表上的元素,也就是上面图中的第一行的链表。若是三个钩子函数执行的结果(verdict)都是NF_ACCEPT,那么NF_HOOK指定的ip_rcv_finish就会被执行。

相关文章
相关标签/搜索