开发者社区> binarydady> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

Linux中netfilter模块编程实践

简介:
+关注继续查看


 上篇我们看了netfilter的实现机制,这篇来实现下netfilter模块实操一把。

为了注册一个钩子,需要填充nf_hook_ops结构体,包括优先级,钩子地点和钩子函数。然后调用nf_register_hook()函数。

1.   数据结构

 

 

struct nf_hook_ops {

        /* 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;                

};

定义在include/linux/netfilter.h

 

2.   模块代码一丢弃所有UDP输入包

本DEMO实现将所有输入的UDP包丢弃。钩子函数为hook_func,通过ip头的协议来指定,协议17就是表示此包是UDP包,如果将17改成1就会丢弃icmp包了。

.hooknum = 1表示是入口点过滤 NF_IP_LOCAL_IN ,如果改成3就是NF_IP_LOCAL_OUT了,这个定在内核文件include/uapi/linux/netfilter_ipv4.h,如下:

/* IP Hooks */           

/* After promisc drops, checksum checks. */

#define NF_IP_PRE_ROUTING       0

/* If the packet is destined for this box. */

#define NF_IP_LOCAL_IN          1

/* If the packet is destined for another interface. */

#define NF_IP_FORWARD           2

/* Packets coming from a local process. */

#define NF_IP_LOCAL_OUT         3

/* Packets about to hit the wire. */

#define NF_IP_POST_ROUTING      4

#define NF_IP_NUMHOOKS          5

编写源码netmod.c如下:

#include <linux/module.h>

#include <linux/kernel.h>

#include <linux/netfilter_ipv4.h>

#include <linux/skbuff.h>

#include <linux/udp.h>

#include <linux/ip.h>

 

/* This function to be called by hook. */

static 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 *))

{

  struct udphdr *udp_header;

  struct iphdr *ip_header = (struct iphdr *) skb_network_header (skb);

 

  if (ip_header->protocol == 17)

    {

      udp_header = (struct udphdr *) skb_transport_header (skb);

      printk (KERN_INFO "Drop udp packet.\n");

 

      return NF_DROP;

    }

 

  return NF_ACCEPT;

}

 

static struct nf_hook_ops nfho = {

  .hook = hook_func,

  .hooknum = 1,             /* NF_IP_LOCAL_IN */

  .pf = PF_INET,

  .priority = NF_IP_PRI_FIRST,

};

 

static int __init

init_nf (void)

{

  printk (KERN_INFO "Register netfilter module.\n");

  nf_register_hook (&nfho);

 

  return 0;

}

 

static void __exit

exit_nf (void)

{

  printk (KERN_INFO "Unregister netfilter module.\n");

  nf_unregister_hook (&nfho);

}

 

module_init (init_nf);

module_exit (exit_nf);

MODULE_LICENSE ("GPL");

编写Makefile如下:

obj-m := netmod.o

modules-objs:= netmod.o

 

KDIR := /lib/modules/`uname -r`/build

PWD := $(shell pwd)

 

default:

              make -C $(KDIR) M=$(PWD) modules

 

clean:

            rm -rf *.o .* .cmd *.ko *.mod.c .tmp_versions

       编译后即可使用insmod将模块插入到系统中。

       测试完毕后,记得卸载模块,不然后来的同学可能需要去定位网络问题了。

3.   模块代码二丢弃指定IP的TCP输入包

关于模块参数的导入,使用module_param。

module_param的定义可以在include/linux/moduleparam.h文件里面查看到,它的原型为:

module_param(name, type, perm);

module_param_array(name, type, nump, perm);

       其中module_param是用来传递变量参数的,module_param_array是用来传递数组参数的。

name是在模块中定义的变量名称,type是变量的类型,perm是权限掩码。

权限在include/linux/stat.h中有定义

#define S_IRWXU 00700

#define S_IRUSR 00400

#define S_IWUSR 00200

#define S_IXUSR 00100

#define S_IRWXG 00070

#define S_IRGRP 00040

#define S_IWGRP 00020

#define S_IXGRP 00010

#define S_IRWXO 00007

#define S_IROTH 00004

#define S_IWOTH 00002

#define S_IXOTH 00001

另外nump是传入数组的数目,是一个int指针。参数可以是以下类型:

byte、short、ushort、int、uint、long、ulong、char(字符指针)、bool、invbool(布尔的反,invbool 类型颠倒了值, 所以真值变成 false,)

可以在导入的时候修改模块参数值:

insmod netmod.ko name=hello

       源码如下:

#include <linux/module.h>

#include <linux/kernel.h>

#include <linux/netfilter_ipv4.h>

#include <linux/skbuff.h>

#include <linux/udp.h>

#include <linux/ip.h>

#include <net/ip.h>

#include <linux/inet.h> /*in_aton()*/

 

/* This function to be called by hook. */

MODULE_LICENSE("Dual BSD/GPL"); 

 

static char* n_ip = "192.168.1.63"; //ip=192.168.1.61

module_param(n_ip, charp, S_IRUGO);

 

static 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 *))

{

  struct tcphdr *tcph = tcp_hdr (skb);

  struct iphdr *iph = ip_hdr (skb);

  struct tcphdr *modtcph;

  unsigned char *tail;

  unsigned char *user_data;

  unsigned char *it;

  struct sk_buff *modskb;

  char *tempPay;

  char *payload;       //Char array to store original payload before modifications

  int lenOrig;

  int lenNew;

  u16 sport, dport;

  u32 saddr, daddr;

  int i1,i2,i3,i4;

 

  //tempPay = kmalloc (1500, GFP_KERNEL);

  //payload = kmalloc (1500, GFP_KERNEL);

  if (!skb)

    return NF_ACCEPT;

  saddr = ntohl (iph->saddr);

  daddr = ntohl (iph->daddr);

  sport = ntohs (tcph->source);

  dport = ntohs (tcph->dest);

  tail = skb_tail_pointer (skb);

 

  user_data = (unsigned char *) ((unsigned char *) tcph + (tcph->doff * 4));

//3232235837 = 192.168.1.61

  if (iph->saddr == in_aton(n_ip) ) //判断ip地址

    {                 

      i1 = saddr>>24;

      i2 = (saddr>>16) & 0x000000ff;

      i3 = (saddr>>8) & 0x000000ff;

      i4 = saddr & 0x000000ff;

 

      printk ("saddr == %d.%d.%d.%d\n ",i1,i2,i3,i4);

      //printk ("saddr == %s\n",iph->saddr);

     

      ip_send_check (iph);

      for (it=user_data;it!=tail;it++)

      {

        *it++;

          printk("%x",*it);

      }

      printk ("\n");

    }

  return NF_ACCEPT;

}

 

static struct nf_hook_ops nfho = {

  .hook = hook_func,

  .hooknum = 3,             /* NF_IP_LOCAL_IN */

  .pf = PF_INET,

  .priority = NF_IP_PRI_FIRST,

};

 

static int __init

init_nf (void)

{

  printk (KERN_INFO "Register netfilter module.\n");

  nf_register_hook (&nfho);

  printk (" n_ip:%s\n",n_ip);

 

  return 0;

}

 

static void __exit

exit_nf (void)

{

  printk (KERN_INFO "Unregister netfilter module.\n");

  nf_unregister_hook (&nfho);

}

 

module_init (init_nf);

module_exit (exit_nf);

MODULE_LICENSE ("GPL");

4.   参考

Writing a Module For netfilter

 

 

 

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
全志 A64开发板Linux内核定时器编程
开发平台 芯灵思Sinlinx A64内存: 1GB 存储: 4GB 开发板详细参数 https://m.tb.cn/h.3wMaSKm开发板交流群 641395230 Linux 内核定时器是内核用来控制在未来某个时间点(基于jiffies)调度执行某个函数的一种机制,其实现位于 和 kernel/timer.c 文件中。
984 0
后台(25)——Filter(2)
探索Android软键盘的疑难杂症 深入探讨Android异步精髓Handler 详解Android主流框架不可或缺的基石 站在源码的肩膀上全解Scroller工作机制 Android多分...
858 0
输入过滤器——InputFilter
一般情况下我们通过请求体读取器InputStreamInputBuffer获取的仅仅是源数据,即未经过任何处理发送方发来的字节。但有些时候在这个读取的过程中希望做一些额外的处理,并且这些额外处理可能是根据不同条件做不同的处理,考虑到程序解耦与扩展,于是引入过滤器(过滤器模式)——输入过滤器InputFilter。
959 0
ASP.NET-FineUI开发实践-5
1.tree的右键事件和单击事件 页面就不写了,准备一个树和一个菜单控件,随便写点啥 JS:注意注释 var menuSettings = F('menuSettings'); var tree = F(IDS.
601 0
linux内核netfilter连接跟踪的hash算法
linux内核netfilter连接跟踪的hash算法   linux内核中的netfilter是一款强大的基于状态的防火墙,具有连接跟踪(conntrack)的实现。conntrack是netfilter的核心,许多增强的功能,例如,地址转换(NAT),基于内容的业务识别(l7, layer-7 module)都是基于连接跟踪。
877 0
Linux防火墙之netfilter/ptables
时间:2018.2.5作者:李强参考:man,info,magedu讲义,万能的internet实验环境:VMware® Workstation 12 Pro ,Centos 6.9,Centos 7.4,SecureCRT Version 8.1.4声明:以下英文纯属个人翻译,英文B级,欢迎纠正,以下内容纯属个人理解,并没有对错,只是参考,盗版不纠,才能有限,希望不误人子弟为好。
879 0
+关注
binarydady
深入底层,挖掘应用 Problem Shooter/Performance Analyzer
99
文章
0
问答
文章排行榜
最热
最新
相关电子书
更多
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
冬季实战营第三期:MySQL数据库进阶实战
立即下载