参考http://www.linuxtcpipstack.com/685.html#NF_INET_PRE_ROUTING

https://opengers.github.io/openstack/openstack-base-netfilter-framework-overview/

http://blog.chinaunix.net/uid-26517122-id-4293010.html

https://netfilter.org/documentation/HOWTO/netfilter-hacking-HOWTO-3.html

https://en.wikipedia.org/wiki/Netfilter

在三层IPv4数据包的处理过程中,可能经过Netfilter的五个钩子点,分别为NF_INET_PRE_ROUTING、NF_INET_LOCAL_IN、NF_INET_FORWARD、NF_INET_LOCAL_OUT、NF_INET_POST_ROUTING,在每个点都可以设置一些规则,来对数据包进行匹配检查处理,这些规则的配置、布局和匹配流程。

Netfilter 提供了一个基本的报文拦截框架,即hook机制;

Netfilter 中定义了一个全局二维数组,来存放注册了的处理函数。

struct list_head hooks[NFPROTO_NUMPROTO][NF_MAX_HOOKS] __read_mostly;

在每个关键点上,有很多已经按照优先级预先注册了的回调函数;

每个钩子函数最后必须向Netfilter框架返回下列几个值其中之一

#define NF_DROP 0 /* 丢包,不再传输 */
#define NF_ACCEPT 1 /* 接受数据包,继续正常传输 这个返回值告诉 Netfilter:到目前为止,该数据包还是被接受的并且该数据包应当被递交到网络协议栈的下一个阶段 */
#define NF_STOLEN 2 /* 数据包已经被接管,回调函数处理该包,NF不再处理,该回调函数将从此开始对数据包的处理,并且Netfilter应当放弃对该数据包做任何的处理。但是,这并不意味着该数据包的资源已经被释放。这个数据包以及它独自的sk_buff数据结构仍然有效,只是回调函数从Netfilter 获取了该数据包的所有权 */
#define NF_QUEUE 3 /*对该数据报进行排队 ,通常用于将数据包交给用户空间的进程处理 */
#define NF_REPEAT 4 /* 再次调用该回调函数,应当谨慎使用这个值,以免造成死循环*/
#define NF_STOP 5    /*结束执行, 数据包通过了挂载点的所有规则。但与NF_ACCEPT不同的一点时,当某条规则的判定结果为NF_STOP,那么可以直接返回结果NF_STOP,无需进行后面的判定了。而NF_ACCEPT需要所以的规则都为ACCEPT,才能返回NF_ACCEPT */
#define NF_MAX_VERDICT NF_STOP
 

netfilter 回调函数注册

nf_hook_ops是注册的钩子函数的核心结构,字段含义如下所示,一般待注册的钩子函数会组成一个nf_hook_ops数组,在注册过程中调用nf_register_net_hooks将所有规则加入到指定的钩子点;

/*
list:因为在一个HOOK点有可能注册多个钩子函数,因此这个变量用来将某个HOOK点所注册的所有钩子函数组织
成一个双向链表;
hook:该参数是一个指向nf_hookfn类型的函数的指针,由该函数指针所指向的回调函数在该hook被激活时调用【nf_hookfn在后面做解释】;
owner:表示这个hook是属于哪个模块的
pf:该hook函数所处理的协议。目前我们主要处理IPv4,所以该参数总是PF_INET;
hooknum:钩子函数的挂载点,即HOOK点;
priority:优先级。前面也说过,一个HOOK点可能挂载了多个钩子函数,当Netfilter在这些HOOK点上遍历查找所注册的钩子函数时,这些钩子函数的先后执行顺序便由该参数来制定。
*/
struct nf_hook_ops {
struct list_head list; /* User fills in from here down. */
nf_hookfn *hook; /* 钩子函数 */
struct net_device *dev; /* 设备 */
void *priv; /* 私有数据 */
u_int8_t pf; /* 协议族 */
unsigned int hooknum; /* 钩子点 */
/* Hooks are ordered in ascending priority. */
int priority; /* 优先级 */
};

钩子函数原型为:

typedef unsigned int nf_hookfn(void *priv,
struct sk_buff *skb,
const struct nf_hook_state *state);

nf_register_net_hook为钩子函数注册的主流程,首先找到钩子点函数的入口,然后根据优先级将当前注册的钩子函数插入到链表中;

int nf_register_net_hook(struct net *net, const struct nf_hook_ops *reg)
{
struct list_head *hook_list;
struct nf_hook_entry *entry;
struct nf_hook_ops *elem;
/* 分配钩子入口结构 */
entry = kmalloc(sizeof(*entry), GFP_KERNEL);
if (!entry)
return -ENOMEM; entry->orig_ops = reg;
entry->ops = *reg;
/* 找到钩子点链表头部 */
hook_list = nf_find_hook_list(net, reg);
if (!hook_list) {
kfree(entry);
return -ENOENT;
} mutex_lock(&nf_hook_mutex);
/* 找到钩子应该插入的位置 */
list_for_each_entry(elem, hook_list, list) {
if (reg->priority < elem->priority)
break;
}
/* 插入钩子点 */
list_add_rcu(&entry->ops.list, elem->list.prev);
mutex_unlock(&nf_hook_mutex);
#ifdef CONFIG_NETFILTER_INGRESS
if (reg->pf == NFPROTO_NETDEV && reg->hooknum == NF_NETDEV_INGRESS)
net_inc_ingress_queue();
#endif
#ifdef HAVE_JUMP_LABEL
static_key_slow_inc(&nf_hooks_needed[reg->pf][reg->hooknum]);
#endif
return 0;
}
/*
对于nf
其钩子函数入口形式为hooks[协议族][钩子点],在二维数组的每个节点都对应着一个钩子函数链表,内部多个nf_hook_entry通过优先级从小到大排列;
*/
struct netns_nf {
#if defined CONFIG_PROC_FS
struct proc_dir_entry *proc_netfilter;
#endif
const struct nf_queue_handler __rcu *queue_handler;
const struct nf_logger __rcu *nf_loggers[NFPROTO_NUMPROTO];
#ifdef CONFIG_SYSCTL
struct ctl_table_header *nf_log_dir_header;
#endif
struct list_head hooks[NFPROTO_NUMPROTO][NF_MAX_HOOKS];
}; enum {
NFPROTO_UNSPEC = 0,
NFPROTO_INET = 1,
NFPROTO_IPV4 = 2,
NFPROTO_ARP = 3,
NFPROTO_NETDEV = 5,
NFPROTO_BRIDGE = 7,
NFPROTO_IPV6 = 10,
NFPROTO_DECNET = 12,
NFPROTO_NUMPROTO,
};
//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
};

linux netfilter 五个钩子点的更多相关文章

  1. Netfilter 之 五个钩子点

    概述 在协议栈的三层IPv4(IPv6还没看,不清楚)数据包的处理过程中,可能经过Netfilter的五个钩子点,分别为NF_INET_PRE_ROUTING.NF_INET_LOCAL_IN.NF_ ...

  2. 《sed的流艺术之四》-linux命令五分钟系列之二十四

    本原创文章属于<Linux大棚>博客,博客地址为http://roclinux.cn.文章作者为rocrocket. 为了防止某些网站的恶性转载,特在每篇文章前加入此信息,还望读者体谅. ...

  3. 《sed的流艺术之三》-linux命令五分钟系列之二十三

    本原创文章属于<Linux大棚>博客,博客地址为http://roclinux.cn.文章作者为rocrocket. 为了防止某些网站的恶性转载,特在每篇文章前加入此信息,还望读者体谅. ...

  4. 《sed的流艺术之二》-linux命令五分钟系列之二十二

    本原创文章属于<Linux大棚>博客,博客地址为http://roclinux.cn.文章作者为rocrocket. 为了防止某些网站的恶性转载,特在每篇文章前加入此信息,还望读者体谅. ...

  5. 《sed的流艺术之一》-linux命令五分钟系列之二十一

    本原创文章属于<Linux大棚>博客,博客地址为http://roclinux.cn.文章作者为rocrocket. 为了防止某些网站的恶性转载,特在每篇文章前加入此信息,还望读者体谅. ...

  6. 《paste命令》-linux命令五分钟系列之二十

    本原创文章属于<Linux大棚>博客,博客地址为http://roclinux.cn.文章作者为rocrocket. 为了防止某些网站的恶性转载,特在每篇文章前加入此信息,还望读者体谅. ...

  7. 《vi中的替换艺术》-linux命令五分钟系列之十一

    vi方面的内容不知道分类到哪里好,就放到<Linux命令五分钟系列>里吧! 今天编程,关于栈的一个小例子,其间我需要把”S.”替换为”S->”(替换不包括双引号). 其实这个不难,不 ...

  8. linux type 命令和Linux的五个查找命令

    type命令用来显示指定命令的类型.一个命令的类型可以是如下之一 alias 别名 keyword 关键字,Shell保留字 function 函数,Shell函数 builtin 内建命令,Shel ...

  9. Linux的五个查找命令find,locate,whereis,which,type

    Linux的五个查找命令 1. find 最常见且最强大的命令,可以查找任何文件. 格式 $ find   指定目录   指定条件   指定动作   指定目录: 所要搜索的目录及其子目录,默认当前目录 ...

随机推荐

  1. 联赛%你测试10T2:漫无止境的八月

    题意: 思路: 有几个特殊的性质: 在不考虑q里面的单点修改,我们先只判断一个序列是否Yes. 我们注意到每次操作都是对一个长度为k的区间进行区间加减1的操作,所以我们如果将序列里面的数按%k分组,把 ...

  2. File、Blob、ArrayBuffer等文件类的对象有什么区别和联系

    前言 在前端中处理文件时会经常遇到File.Blob.ArrayBuffer以及相关的处理方法或方式如FileReader.FormData等等这些名词,对于这些常见而又不常见的名词,我相信大多数人对 ...

  3. 《我想进大厂》之Dubbo普普通通9问

    这是面试专题系列第四篇,Dubbo系列.Dubbo本身并不复杂,而且官方文档写的非常清楚详细,面试中dubbo的问题一般不会很多,从分层到工作原理.负载均衡策略.容错机制.SPI机制基本就差不多了,最 ...

  4. 在学习python的过程中,遇到的最大的困难是什么?

    本人文科生,回顾自己近 2 年的Python 自学经历,有一些学习心得和避坑经验分享给大家,让大家在学习 Python 的过程中少走一些弯路!减少遇到不必要的学习困难! 首先,最开始最大的困难应该就是 ...

  5. ORACL-重做日志详解

    作用:oracle重做日志主要目的是数据恢复及数据修改效率提升 前言:oracle重做日志主相关视图: 1.v$log记录当前数据库重做日志组 2.v$logfie记录当前数据库重做日志组状态.类型等 ...

  6. Ubuntu 18.04 LTS IP 地址设置

    和之前的版本不太一样, Ubuntu 18.04 的 ip地址设置是用netplan管理的     配置文件在: /etc/netplan/50-cloud-init.yaml 示例文件如下: # T ...

  7. JSP标签语法、JSTL标签库、EL表达式辨析

    <一.JSP > JSP 语法语法格式: <% 代码片段 %>或者<jsp:scriptlet> 代码片段</jsp:scriptlet> JSP声明 ...

  8. APIO2008免费道路

    题目大意 给定一张n个点m条边的图,图上有两种边,求保证有k条第一种边的情况下的最小生成树 传送门 题解 考虑最小生成树kruskal算法 先找到不含限制的最小生成树,然后就可以知道哪些第一种边是必选 ...

  9. 宝塔面板无法进入phpadmin管理数据库解决办法

    ECS--华为云 宝塔面板6.0 phpMyAdmin 4.4 经过搜索发现问题在于端口和安全组规则 解决方法如下 1.在安全中添加888端口 2.华为云安全组规则--入方向规则--添加规则 3.打开 ...

  10. NB-IOT覆盖范围有多大 NB-IOT的强覆盖是怎么实现的

    NB-IoT技术自出现以来就以其强大的覆盖范围和通讯距离长而受到广泛的欢迎,发展到现在已经成为万物互联网络中的一个重要分支.那么NB-IoT覆盖范围到底有多大,是怎么来衡量其覆盖能力? 强大的覆盖范围 ...