内核编程学习(2)netfilter初探

本文探讨了在Linux环境下如何利用netfilter在内核中挂载钩子以捕获数据包。实践中遇到的问题可能与内核版本有关,作者提到了在2.6.32-21-generic版本下进行此类操作。netfilter架构通过在网络路径的关键点设置检查点(HOOKs),并注册处理函数来执行各种任务,如包过滤、NAT转换,甚至允许自定义功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本次的任务是要在linux下利用netfilter往内核挂钩子,截获数据包。

这几天的练习,发现很多结构体以及技术涉及到内核版本,如果你发现有些结构体的成员什么的未定义,大多是这种问题。本机内核版本2.6.32-21-generic。查看内核版本命令uanme -r。

通俗的说,netfilter的架构就是在整个网络流程的若干位置放置了一些检测点(HOOK),而在每个检测点上登记了一些处理函数进行处理(如包过滤,NAT等,甚至可以是 用户自定义的功能)。

  IP层的五个HOOK点的位置如下所示
  [1]:NF_IP_PRE_ROUTING:刚刚进入网络层的数据包通过此点(刚刚进行完版本号,校验和等检测), 目的地址转换在此点进行;
  [2]:NF_IP_LOCAL_IN:经路由查找后,送往本机的通过此检查点,INPUT包过滤在此点进行;
  [3]:NF_IP_FORWARD:要转发的包通过此检测点,FORWORD包过滤在此点进行;
  [4]:NF_IP_POST_ROUTING:所有马上便要通过网络设备出去的包通过此检测点,内置的源地址转换功能(包括地址伪装)在此点进行;
  [5]:NF_IP_LOCAL_OUT:本机进程发出的包通过此检测点,OUTPUT包过滤在此点进行。
    进入HOOK点,执行通过nf_register_hook()登记的功能,如果我们想加入自己的代码,便要用nf_register_hook函数,其函数原型为:
  int nf_register_hook(struct nf_hook_ops *reg)。 我们考察一下struct nf_hook_ops结构:struct nf_hook_ops
{
        struct list_head list;                        //链表成员
        /* User fills in from here down. */
        nf_hookfn *hook;                        //钩子函数指针
        struct module *owner;
        int pf;                                        //协议簇,对于ipv4而言,是PF_INET
        int hooknum;                                //hook类型
        /* Hooks are ordered in ascending priority. */
        int priority;                                //优先级
};
  我们的工作便是生成一个struct nf_hook_ops结构的实例,并用nf_register_hook将其HOOK上。其中list项我们总要初始化为{NULL,NULL};由于一般在IP层工作,pf总是PF_INET;hooknum就是我们选择的HOOK点;一个HOOK点可能挂多个处理函数,谁先谁后,便要看优先级,即priority的指定了。netfilter_ipv4.h中用一个枚举类型指定了内置的处理函数的优先级:hook是提供的处理函数,也就是我们的主要工作.它的五个参数将由NFHOOK宏传进去。
本例简单地截获所有的数据包,并丢弃,这样就阻断了系统的网络链接,网页、ping等都收不到数据包。

#include <stdio.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/netfilter.h>
#include <linux/netfilter_ipv4.h>
/* 用于注册我们的函数的数据结构 */
static struct nf_hook_ops nfho;
int count=0;
/* 注册的hook函数的实现 */
unsigned int hook_func(unsigned int hooknum,
 struct sk_buff **skb,
 const struct net_device *in,
 const struct net_device *out,
int (*okfn)(struct sk_buff *))
{
        if(count==10)
        {
                FILE *fp;
                fp=fopen("text.txt","r+");
                fprintf(fp,"ip:%s",(*skb)->network_header->ihl);
                fclose(fp);
        }
        if(count<=10)
                count++;
        return NF_DROP;           /* 丢弃所有的数据包 */
}
/* 初始化程序 */
int init_module()
{
    /* 填充我们的hook数据结构 */
    nfho.hook = hook_func;         /* 该钩子对应的处理函数 */
    nfho.hooknum  = NF_INET_PRE_ROUTING; /* 使用IPv4的第一个hook */
    nfho.pf       = PF_INET;
    nfho.priority = NF_IP_PRI_FIRST;   /* 让我们的函数首先执行 */
     nf_register_hook(&nfho);  //将用户自己定义的钩子注册到内核中
    return 0;
}
/* 清除程序 */
void cleanup_module()
{
    nf_unregister_hook(&nfho); //将用户自己定义的钩子从内核中删除
}

                                                                                          
需要说明的是在钩子函数不要使用printk输出,不然系统会崩溃。还有本例想将截获的数据包保留保留部分信息写入文件,
但是编译时显示stdio.h文件未找到,估计是由于makefile中重定向了路径的问题,暂时还没有找到解决办法,钩子也很草率,现记下。







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值