Netfilter再来亿遍

Netfilter/IPTables
Linux 2.4 版本以上新加入的防火墙机制
Netfilter与IP协议栈是无缝契合的,工具模块IPTables从用户态的iptables连接到内核态的Netfilter的架构中

主要功能
1.数据报过滤
2.链接跟踪 (一条tcp会话)
3.网络地址转换(NAT)
4.数据报修改(mangle)

可以这么说,Netfilter是表的容器,表是链的容器,链是规则的容器,最终形成对数据报处理规则的实现。
在这里插入图片描述
以下的绿底图,都是复制的别人的
每个链挂有一系列规则,链称为钩子点
链的实际拓扑是下面这样的,
在这里插入图片描述
他说明了三种 数据流向
1.pre -> local_in -> 上层
2.pre -> forward -> post
3.上层 -> local_out ->post

理解这个流向很重要,因为刚开始接触的时候很可能以为
pre -> local_in ->上层 ->local_out ->post 是一条 ,这个认知会为理解nf带来很大阻碍

对于数据的实际处理,是在链上的规则(钩子函数nf_hook_ops)内进行的
经过规则的判断,会返回一个值,告诉ntfilter 应该 丢掉这个包还是放行,或者其他操作
具体的返回值,及动作可以再去查看

上面的链 拓扑看起来是 一个平面的, 实际上, netfilter 是一个三维的结构,更高一维是协议
,每选择一种协议, 对应的二维平面,都是像上面的图展示的一样,只不过,里面的规则会有差别

在这里插入图片描述

在这里插入图片描述

NF_HOOK 是一个宏,指明了 要调用哪一个协议层的哪个钩子点,
使用 NF_HOOK 可以将流程切入到netfilter之中 在头文件(include/linux/netfilter.h)
#define NF_HOOK(pf, hook, skb, indev, outdev,okfn)
NF_HOOK_THRESH(pf, hook, skb, indev, outdev, okfn, INT_MIN)

调用
NF_HOOK(刚才所说的协议, 钩子,skb(数据),输入设备, 输出设备,处理走完钩子状态的回调函数)
最后一个参数指定通过该宏去遍历钩子函数时的优先级,越小越优先

NF_HOOK_THRESH宏只增加了一个thresh参数,这个参数就是用来指定通过该宏去遍历钩子函数时的优先级,同时,该宏内部又调用了nf_hook_thresh函数:
static inline int nf_hook_thresh(int pf, unsignedint hook,
                           struct sk_buff **pskb,
                           struct net_device *indev,
                           struct net_device *outdev,
                           int (*okfn)(struct sk_buff *), int thresh,
                           int cond)
{
if (!cond)
return 1;
#ifndef CONFIG_NETFILTER_DEBUG
if (list_empty(&nf_hooks[pf][hook]))
        return 1;
#endif
return nf_hook_slow(pf, hook, pskb, indev, outdev,okfn, thresh);
}

这个函数又只增加了一个参数cond,该参数为0则放弃遍历,并且也不执行okfn函数;为1则执行nf_hook_slow去完成钩子函数okfn的顺序遍历(优先级从小到大依次执行)。

可以看到函数的最后调用了 nf_hook_slow, 主要就是通过这个函数,根据优先级,遍历 钩子点上的钩子函数 ,钩子点都在 nf_hooks[][] 上


pre钩子 在ip_rcv()调用
(优先级顺序):Conntrack(-200)、mangle(-150)、DNAT(-100)
主要是对数据报作报头检测处理,以捕获异常情况。

local_in 钩子 ,在ip_local_deliver()调用
(优先级顺序):mangle(-150)、filter(0)、SNAT(100)、Conntrack(INT_MAX-1)
防火墙一般建立在这个HOOK上。

forward钩子 ,在ip_forward()调用
(优先级顺序)mangle(-150)、filter(0)

local_out 钩子,在 ip_build_and_send_pkt()调用
(优先级顺序) Conntrack(-200)、mangle(-150)、DNAT(-100)、filter(0)

post钩子 在ip_finish_output() 中调用
mangle(-150)、SNAT(100)、Conntrack(INT_MAX)

可以发现, 钩子函数的优先顺序 (相对于一条流来说)
都是 先 跟踪链接(ct), 然后 mangle nat 、filter ,最后再 链接跟踪(ct)



要注册一个钩子函数 需要调用 nf_register_hook() 函数,并且准备一个数据 结构nf_hook_ops
nf_register_hook(&nf_hook_ops) 能完成对钩子函数的注册
nf_unregister_hook(&nf_hook_ops) 能完成对钩子函数的注销
钩子函数对应的结构就是下面这个
struct nf_hook_ops {
struct list_head list;

              /* 此下的值由用户填充 */
              nf_hookfn *hook;
              int pf;
              int hooknum;
              /* Hook以升序的优先级排序 */
              int priority;
      };
  • list 即 netfilter 的链表结构,链接各个钩子函数
  • nf_hookfn *hook 真正的 处理函数,具体执行的内容

nf_hookfn 函数指针
在这里插入图片描述
okfn 即用来处理

  • pf 是 协议 ,
  • hooknum 即 表明是在哪个钩子点上的 pre post foward ,由宏定义
  • priority 调用优先级

如何调用钩子函数

netfilter 有5条链: pre,forword,post,in,out
实际上,就是在内的5个位置上调用 NF_HOOK ,(正常代码逻辑,通过NF_HOOK,切入到netfileter之中)

重要结构

钩子函数保存在全局二维数组nf_hooks中。

nf hooks

struct list_head nf_hooks[NFPROTO_NUMPROTO][NF_MAX_HOOKS] __read_mostly;

NFPROTO_NUMPROTO,是说在哪个协议层(模式)
NF_MAX_HOOKS , 是说在哪个钩子点
每个成员都是一个链表,表示某个协议下的钩子点的钩子函数链

上述二维数组成员的具体结构

struct nf_hook_ops
{
    struct list_head list; //该成员将会把这个结构添加在nf_hooks数组引导的队列头中。

    /* User fills in from here down. */
    nf_hookfn *hook;        //钩子处理函数:用于判断报文是否需要经过本钩子到检测过滤等
    struct module *owner;   //可以使用动态加载的内核模块
    u_int8_t pf;            //协议族,对应于nf_hooks的第一维
    unsigned int hooknum;   //钩子点,对应于nf_hooks的第二维

    /* Hooks are ordered in ascending priority. */
    int priority;//这里不是一个先来先服务队列,而是一个优先级队列。
}

钩子处理函数的 回调函数接口,nf_hook_ops 结构的hook成员的类型。

//return:   NF_DROP,NF_ACCEPT...
typedef 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 *));
作为回调函数,他的参数由NF_HOOK 传递到netfilter框架中去

重要函数

切入到Netfilter 框架的入口NF_HOOK

当nf_hook_ops 数据填充完毕后,调用nf_register_hook(& ops),将钩子函数点注册到框架上

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值