- 🐚作者简介:花神庙码农(专注于Linux、WLAN、TCP/IP、Python等技术方向)
- 🐳博客主页:花神庙码农 ,地址:https://blog.csdn.net/qxhgd
- 🌐系列专栏:TCP/IP协议
- 📰如觉得博主文章写的不错或对你有所帮助的话,还望大家三连支持一下呀!!! 👉关注✨、点赞👍、收藏📂、评论。
- 如需转载请参考转载须知!!
丢包、流不通、错包等问题查证手段系列之三——Netfiler hook函数
Netfilter hook点概述
Netfilter全景图
二层hook示意图
三层hook示意图
hook调用示意图
Netfilter hook函数的应用场景
- 如果仅需判断报文是否经过了某个hook点,则采用【TCP/IP】【调试】丢包、流不通、错包等问题查证手段系列之二——防火墙这一节的方式即可,没有必要单独写钩子函数。
- 有时需要查看报文的内容,如需确认报文内容是否正确,或希望匹配特定报文做些动作(如截取dns报文、dhcp报文等),此时,可以考虑使用hook函数的方式。
具体开发过程
- 此处,仅以一个二层的hook点为例来说明。
Linux的module
- 编写一个Linux的module,可以编译为独立的ko,也可直接编入内核;
- 这部分可参考网上其他资料,类似下面的模式:
#ifndef __KERNEL__
#define __KERNEL__
#endif
#ifndef MODULE
#define MODULE
#endif
#include <linux/module.h>
#include <linux/kernel.h>
static int __init pkt_process_init(void) {
printk(KERN_ALERT "pkt_process_init called.\n");
return 0;
}
static void __exit pkt_process_exit(void) {
printk(KERN_ALERT "pkt_process_exit called\n");
}
module_init(pkt_process_init);
module_exit(pkt_process_exit);
编写钩子函数
- 此处,可根据需要在br_pkt_hook_handle函数中,做一些报文的识别及处理工作。
static unsigned int br_pkt_hook_handle(const struct nf_hook_ops *ops, struct sk_buff *skb, const struct nf_hook_state *state) {
struct ethhdr *eth;
struct iphdr *iph; /* IPv4 header */
struct tcphdr *tcph; /* TCP header */
struct udph *udph;
if (!skb) {
return NF_ACCEPT;
}
eth = (struct ethhdr *) skb->data;
iph = ip_hdr(skb);
if (iph->protocol == IPPROTO_TCP) {
tcph = tcp_hdr(skb);
}
else if (iph->protocol == IPPROTO_UDP) {
udph= udp_hdr(skb);
}
/* other process */
}
注册钩子函数
static struct nf_hook_ops br_nf_ops_hooks[] = {
{
.hook = br_pkt_hook_handle,
.owner = THIS_MODULE,
.pf = PF_BRIDGE,
.hooknum = NF_BR_FORWARD,
.priority = NF_BR_PRI_BRNF,
},
};
static int __init pkt_process_init(void) {
printk(KERN_ALERT "pkt_process_init called.\n");
for (i = 0; i < ARRAY_SIZE(br_nf_ops_hooks); i++) {
if ((nf_register_hook(&br_nf_ops_hooks[i])) < 0) {
printk("[%s:%d] nf_register_hook register failed!\n", __FUNCTION__, __LINE__);
}
}
return 0;
}
去注册钩子
static void __exit pkt_process_exit(void) {
printk(KERN_ALERT "pkt_process_exit called\n");
for (i = 0; i < ARRAY_SIZE(br_nf_ops_hooks); i++) {
if ((nf_unregister_hook(&br_nf_ops_hooks[i])) < 0) {
printk("[%s:%d] nf_register_hook register failed!\n", __FUNCTION__, __LINE__);
}
}
}
如本文对你有些许帮助,欢迎大佬支持我一下,您的支持是我持续创作的不竭动力
支持我的方式