HOOK函数注册

image.png

上图是netfilter中注册的部分hook函数。这些hook函数是通过 nf_register_hook注册到二维数组nf_hooks中的。

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
};enum {NFPROTO_UNSPEC =  0,NFPROTO_INET   =  1,NFPROTO_IPV4   =  2,NFPROTO_ARP    =  3,NFPROTO_BRIDGE =  7,NFPROTO_IPV6   = 10,NFPROTO_DECNET = 12,NFPROTO_NUMPROTO,
};
extern struct list_head nf_hooks[NFPROTO_NUMPROTO][NF_MAX_HOOKS];

数组的第一维即上图的第一列,表示不同的地址族,上图只画出了 IPV4,ARP和BRIDGE相关的。数组的第二维即上图的第一排,表示不同模块的hook函数,对于不同的地址族,使用的宏定义不同,但都是从0开始。拿最常见的IPV4地址族来说,五个hook函数安置在数据包的必经之路,不管数据是到本机的,还是需要本机转发的,还是从本机发出去的,都会覆盖到。

NF_INET_PRE_ROUTING和NF_INET_LOCAL_OUT相当于netfilter的入口点,即不管哪种情况,数据包肯定会从这俩hook点之一进入。
NF_INET_LOCAL_IN和NF_INET_POST_ROUTING相当于netfilter的出口点,即不管哪种情况,数据包肯定会从这俩hook点之一出去。

hook函数的执行顺序: 同一个hook点上的从优先级值最小的开始执行,即上图从上往下执行,不同的hook点互不影响。

对于IPV4地址族来说,包含了多个模块的hook函数:

filter,raw,mangle,security: 这四个模块相对独立,不依赖其他模块。
conntrack: 连接跟踪模块是状态防火墙和nat的基础。
nat: 基于conntrack对于数据包的跟踪,对数据流的收包查找nat规则进行nat转换,此流的后续数据包直接查找conntrack的ct信息做nat转换。
ipvs: 四层负载均衡模块

HOOK函数执行

hook函数的执行是通过调用函数NF_HOOK来实现的,
其第一个参数pf指定了地址族,第二个参数指定了在哪个hook点,第三个参数skb是数据包,第六个参数是数据包通过hook点上hook函数的检查后,如果结果是accept而执行的函数。

static inline int
NF_HOOK(uint8_t pf, unsigned int hook, struct sk_buff *skb,struct net_device *in, struct net_device *out,int (*okfn)(struct sk_buff *))
{return NF_HOOK_THRESH(pf, hook, skb, in, out, okfn, INT_MIN);
}static inline int
NF_HOOK_THRESH(uint8_t pf, unsigned int hook, struct sk_buff *skb,struct net_device *in, struct net_device *out,int (*okfn)(struct sk_buff *), int thresh)
{int ret = nf_hook_thresh(pf, hook, skb, in, out, okfn, thresh);//执行完hook函数后,返回值为1才会执行okfn。if (ret == 1)ret = okfn(skb);return ret;
}static inline int nf_hook_thresh(u_int8_t pf, unsigned int hook,struct sk_buff *skb,struct net_device *indev,struct net_device *outdev,int (*okfn)(struct sk_buff *), int thresh)
{//地址族pf对应的hook点上注册了hook函数,如果没注册直接返回1if (nf_hooks_active(pf, hook))return nf_hook_slow(pf, hook, skb, indev, outdev, okfn, thresh);return 1;
}/* Returns 1 if okfn() needs to be executed by the caller,* -EPERM for NF_DROP, 0 otherwise. */
int nf_hook_slow(u_int8_t pf, unsigned int hook, struct sk_buff *skb,struct net_device *indev,struct net_device *outdev,int (*okfn)(struct sk_buff *),int hook_thresh)
{struct nf_hook_ops *elem;unsigned int verdict;int ret = 0;/* We may already have this, but read-locks nest anyway */rcu_read_lock();//取出hook点的hook函数的链表头elem = list_entry_rcu(&nf_hooks[pf][hook], struct nf_hook_ops, list);
next_hook://遍历执行此hook点上所有的hook函数verdict = nf_iterate(&nf_hooks[pf][hook], skb, hook, indev,outdev, &elem, okfn, hook_thresh);//如果返回NF_ACCEPT或者NF_STOP说明通过hook函数的检查,则返回1//如果返回NF_DROP,说明数据包在此hook点丢了,返回0if (verdict == NF_ACCEPT || verdict == NF_STOP) {ret = 1;} else if ((verdict & NF_VERDICT_MASK) == NF_DROP) {kfree_skb(skb);ret = NF_DROP_GETERR(verdict);if (ret == 0)ret = -EPERM;} else if ((verdict & NF_VERDICT_MASK) == NF_QUEUE) {int err = nf_queue(skb, elem, pf, hook, indev, outdev, okfn,verdict >> NF_VERDICT_QBITS);if (err < 0) {if (err == -ECANCELED)goto next_hook;if (err == -ESRCH &&(verdict & NF_VERDICT_FLAG_QUEUE_BYPASS))goto next_hook;kfree_skb(skb);}}rcu_read_unlock();return ret;
}

遍历执行hook点上所有的hook函数。

unsigned int nf_iterate(struct list_head *head,struct sk_buff *skb,unsigned int hook,const struct net_device *indev,const struct net_device *outdev,struct nf_hook_ops **elemp,int (*okfn)(struct sk_buff *),int hook_thresh)
{unsigned int verdict;/** The caller must not block between calls to this* function because of risk of continuing from deleted element.*/list_for_each_entry_continue_rcu((*elemp), head, list) {//只执行优先级比hook_thresh大的hook函数if (hook_thresh > (*elemp)->priority)continue;/* Optimization: we don't need to hold modulereference here, since function can't sleep. --RR */
repeat:verdict = (*elemp)->hook(*elemp, skb, indev, outdev, okfn);//hook函数的返回值不为accept,并且不为repeat才返回if (verdict != NF_ACCEPT) {if (verdict != NF_REPEAT)return verdict;goto repeat;}}//走到这里说明所有的hook函数都返回acceptreturn NF_ACCEPT;
}

也可参考:netfilter hook函数 - 简书 (jianshu.com)

netfilter hook函数相关推荐

  1. linux hook 任意内核函数,【求助】Kernel 4.8下编译编写的Netfilter Hook函数失败

    该楼层疑似违规已被系统折叠 隐藏此楼查看此楼 #include #include #include #include #include MODULE_LICENSE("Dual BSD/GP ...

  2. linux 内核 hook函数介绍

    在编写linux内核中的网络模块时,用到了钩子函数也就是hook函数.现在来看看linux是如何实现hook函数的. 先介绍一个结构体: struct nf_hook_ops,这个结构体是实现钩子函数 ...

  3. linux钩子函数和回调函数,Linux Kernel 学习笔记10:hook函数

    (本章基于: Linux -4.4.0-37) linux 内核中有一套hook函数机制,可在不同hook点位置监控网络数据包,并执行丢弃.修改等操作.网络防火墙就是通过此机制实现的. 注册注销hoo ...

  4. 关于PyTorch中的register_forward_hook()函数未能执行其中hook函数的问题

    关于PyTorch中的register_forward_hook()函数未能执行其中hook函数的问题 Hook 是 PyTorch 中一个十分有用的特性.利用它,我们可以不必改变网络输入输出的结构, ...

  5. 内核级利用通用Hook函数方法检测进程

    介绍通用Hook的一点思想:     在系统内核级中,MS的很多信息都没公开,包括函数的参数数目,每个参数的类型等.在系统内核中,访问了大量的寄存器,而很多寄存器的值,是上层调用者提供的.如果值改变系 ...

  6. linux内核中的hook函数详解,linux内核中的hook函数详解

    在编写linux内核中的网络模块时,用到了钩子函数也就是hook函数.现在来看看linux是如何实现hook函数的. 先介绍一个结构体: struct nf_hook_ops,这个结构体是实现钩子函数 ...

  7. pytest测试框架4-插件与hook函数

    一.简介 pytest的自带功能很强大,通过添加插件可以扩展功能,pytest的代码结构适合定制和扩展插件, 可以借助hook函数来实现. 把fixture函数或者hook函数添加到conftest文 ...

  8. 安卓怎么调用系统的ui_安卓逆向 | 为了反射调用我们怎么能拿到被HOOK函数的实例...

    先打一拳,打的时候再把问题问遍. 蔚 前言当我们在xposed进行反射调用的时候,很多时候被HOOK函数并不是static函数,但是我们在调用的时候需要传入该函数的类的实例,那实例我们怎么拿到呢,今天 ...

  9. linux hook 任意内核函数,linux内核中的hook函数详解

    在编写linux内核中的网络模块时,用到了钩子函数也就是hook函数.现在来看看linux是如何实现hook函数的. 先介绍一个结构体: struct nf_hook_ops,这个结构体是实现钩子函数 ...

最新文章

  1. Ghost XP基本介绍
  2. 特性开关框架 java_关于Mosfet你应当知道的开关特性
  3. lhgdialog 4.2.0 正式版发布
  4. python循环捕捉异常_python异常捕捉以及处理
  5. VMware虚拟机磁盘操作占用过高问题(转:http://blog.csdn.net/New_When/article/details/73731149)
  6. leetcode 787. Cheapest Flights Within K Stops | 787. K 站中转内最便宜的航班(BFS)
  7. Jmeter5.3(windows下)安装过程问题总结
  8. matlab根据给定3点画圆弧_圆弧齿廓面齿轮齿顶尖化研究
  9. CLR via C# 内存管理读书记
  10. HTML5学习笔记(六):CSS基本样式
  11. ListView可拖拽item的原理
  12. Linux-eth0 eth0:1 和eth0.1关系
  13. 软件测试周刊(第11期):飞狗
  14. 2023华为OD机试备考攻略 以及题库目录分值说明 考点说明
  15. Response设置响应数据功能介绍及重定向
  16. 【BZOJ1004】【HNOI20008】cards
  17. Tableau:自定义地图的使用
  18. LINUX留后门--教程(六)—— PAM后门
  19. Check Problems---二分
  20. 解决Chrome不支持NPAPI插件的方法(贴吧旺旺等)

热门文章

  1. 在Windows2003下安装Blackice导致蓝屏的解决办法
  2. 030-用Swing组件及Action事件实现登录功能
  3. OPENGL ES 2.0 知识串讲(1)――OPENGL ES 2.0 概括
  4. matlab的plot没有反应,用plot画图没有反应
  5. 信息熵,信息增益详解
  6. GeckoFx v45浏览器控件实现文件下载出现异常的解决办法
  7. 手游服务器压力,为什么手游都是几百上千个区?真的这么多人吗?
  8. 【深度】通俗了解异构计算
  9. Windows下Boost库的安装与使用
  10. CMake调用boost库