自己寫 Netfilter 匹配器


轉自:http://blog.csdn.net/xsckernel/article/details/8173340

原文鏈接:
http://www.linuxfocus.org/ChineseGB/February2005/article367.shtml

看了Nicolas寫的netfilter寫匹配器,自己嘗試編譯測試,發現iptables 以及內核版本升級很多數據結構和函數接口都改變了,需要做大量的修改才能運行。


運行 iptables/netfilter

1)iptables

從 ftp://ftp.netfilter.org/pub/iptables/ 下載iptables 的源碼然後拷貝libipt_ipaddr.c 到 iptables-1.4.10/extensions.

拷貝ipt_ipaddr.h 到 ./include/linux/netfilter_ipv4/

然後 

  1. $./configure   
  2. $make && make install  


2)ipaddr.ko

編譯這個內核模塊需用到3個文件:

ipt_ipaddr.h  ipt_ipaddr.c  Makefile



編譯完內核模塊之後用

  1. $ sudo modprobe x_tables  
  2. $ sudo insmod ipaddr.ko  
加載內核模塊,然後iptables命令:

  1. sudo iptables -I OUTPUT -m ipaddr --ipsrc ipaddr --ipdst  ipaddr  
設置規則。

修改後的源碼:

ipt_ipaddr.c :
  1. #include <linux/module.h>  
  2. #include <linux/kernel.h>  
  3.   
  4. #include <linux/netfilter_ipv4.h>  
  5.   
  6. #include <linux/netfilter_ipv4/ip_tables.h>  
  7.   
  8. #include "ipt_ipaddr.h"  
  9.   
  10.   
  11. #define NIPQUAD(addr) \  
  12.     ((unsigned char *)&addr)[0], \  
  13.     ((unsigned char *)&addr)[1], \  
  14.     ((unsigned char *)&addr)[2], \  
  15.     ((unsigned char *)&addr)[3]  
  16.   
  17.   
  18. #define NF_IP_LOCAL_IN          1  
  19. #define NF_IP_LOCAL_OUT         3  
  20.   
  21.   
  22.   
  23. static int ipt_match(const struct sk_buff *skb,struct xt_action_param *param)  
  24. {  
  25.    const struct net_device *in = param->in;  
  26.    const struct net_device *out = param->out;      
  27.    const struct ipt_ipaddr_info *info  = param->matchinfo;  
  28.   
  29.    struct iphdr *iph = ip_hdr(skb);  
  30.    printk("entered ipt_match !\n");  
  31.    printk(KERN_INFO "ipt_ipaddr: IN=%s OUT=%s TOS=0x%02X "  
  32.                     "TTL=%x SRC=%u.%u.%u.%u DST=%u.%u.%u.%u "  
  33.                     "ID=%u IPSRC=%u.%u.%u.%u IPDST=%u.%u.%u.%u\n",  
  34.   
  35.                     in ? (char *)in : "", out ? (char *)out : "", iph->tos,  
  36.                     iph->ttl, NIPQUAD(iph->saddr), NIPQUAD(iph->daddr),  
  37.                     ntohs(iph->id), NIPQUAD(info->ipaddr.src), NIPQUAD(info->ipaddr.dst)  
  38.          );  
  39.   
  40.    if (info->flags & IPADDR_SRC) {  
  41.       if ( (ntohl(iph->saddr) != ntohl(info->ipaddr.src)) ^ !!(info->flags & IPADDR_SRC_INV) ) {  
  42.            
  43.          printk(KERN_NOTICE "src IP %u.%u.%u.%u is not matching %s.\n",  
  44.                             NIPQUAD(info->ipaddr.src),  
  45.                             info->flags & IPADDR_SRC_INV ? " (INV)" : "");  
  46.          return 0;  
  47.       }  
  48.    }  
  49.   
  50.    if (info->flags & IPADDR_DST) {  
  51.       if ( (ntohl(iph->daddr) != ntohl(info->ipaddr.dst)) ^ !!(info->flags & IPADDR_DST_INV) )  {  
  52.   
  53.          printk(KERN_NOTICE "dst IP %u.%u.%u.%u is not matching%s.\n",  
  54.                             NIPQUAD(info->ipaddr.dst),  
  55.                             info->flags & IPADDR_DST_INV ? " (INV)" : "");  
  56.          return 0;  
  57.       }  
  58.    }  
  59.      
  60.    return 1;  
  61. }  
  62.   
  63. static int ipaddr_checkentry(const struct xt_mtchk_param *param)  
  64. {  
  65.    printk("entered ipaddr_checkentry\n");  
  66.    const struct ipt_ipaddr_info *info = param->matchinfo;  
  67.    unsigned int hook_mask = param->hook_mask;  
  68.    unsigned int matchsize = param->match->matchsize;  
  69.    char tablename[XT_TABLE_MAXNAMELEN];  
  70.    const struct ipt_ip *ip = (struct ipt_ip *)param->entryinfo;      // this is specified by param->family.  
  71.   
  72.    if (hook_mask & ~((1 << NF_IP_LOCAL_IN) | (1 << NF_IP_LOCAL_OUT))) {  
  73.       printk(KERN_WARNING "ipt_ipaddr: only valid with the FILTER table.\n");  
  74.       return 0;  
  75.    }  
  76.   
  77.    if (matchsize != XT_ALIGN(sizeof(struct ipt_ipaddr_info))) {  
  78.       printk(KERN_ERR "ipt_ipaddr: matchsize differ, you may have forgotten to recompile me.\n");  
  79.       return 0;  
  80.    }  
  81.   
  82.    strcpy(tablename,param->match->table);  
  83.    printk(KERN_INFO "ipt_ipaddr: Registered in the %s table, hook=%x, proto=%u\n",  
  84.                     tablename, hook_mask, ip->proto);  
  85.   
  86.    return 1;  
  87. }  
  88.   
  89. static struct xt_match ipaddr_match  = {   
  90.         .match  = ipt_match,  
  91.     .matchsize = XT_ALIGN(sizeof(struct ipt_ipaddr_info)),  /// without this may cause invalid size 0 != 12  
  92.     .name   = "ipaddr",  
  93.     .checkentry = ipaddr_checkentry,   
  94.     .me     = THIS_MODULE   
  95. };  
  96.   
  97.   
  98. static int __init init(void)  
  99. {  
  100.    printk(KERN_INFO "ipt_ipaddr: init!\n");  
  101.    return xt_register_match(&ipaddr_match);  
  102. }  
  103.   
  104. static void __exit fini(void)  
  105. {  
  106.    printk(KERN_INFO "ipt_ipaddr: exit!\n");  
  107.    xt_unregister_match(&ipaddr_match);  
  108. }  
  109.   
  110. module_init(init);  
  111. module_exit(fini);  
  112.   
  113. MODULE_LICENSE("GPL");  
  114. MODULE_AUTHOR("Nicolas Bouliane && Samuel Jean");  
  115. MODULE_DESCRIPTION("netfilter module skeleton");  

ipt_ipaddr.h
  1. #ifndef _IPT_IPADDR_H  
  2. #define _IPT_IPADDR_H  
  3.   
  4.   
  5. #include <linux/types.h>  
  6.   
  7. #define IPADDR_SRC   0x01     /* Match source IP addr */  
  8. #define IPADDR_DST   0x02     /* Match destination IP addr */  
  9.   
  10. #define IPADDR_SRC_INV  0x10  /* Negate the condition */  
  11. #define IPADDR_DST_INV  0x20  /* Negate the condition */  
  12.   
  13. struct ipt_ipaddr {  
  14.    __u32 src, dst;  
  15. };  
  16.   
  17. struct ipt_ipaddr_info {  
  18.   
  19.    struct ipt_ipaddr ipaddr;  
  20.      
  21.    /* Flags from above */  
  22.    __u8 flags;  
  23.      
  24. };  
  25.   
  26. #endif    


libipt_ipaddr.c:
  1. #include <stdbool.h>  
  2. #include <stdio.h>  
  3. #include <netdb.h>  
  4. #include <string.h>  
  5. #include <stdlib.h>  
  6. #include <getopt.h>  
  7.   
  8. #include <iptables.h>  
  9.   
  10. #include <xtables.h>  
  11. #include <linux/netfilter_ipv4/ipt_ipaddr.h>  
  12.   
  13.   
  14. //./configure --prefix= ./install   
  15. /*  
  16.  *  ./install/sbin/iptables -m ipaddr -h 
  17.  */  
  18. static void ipaddr_help(void)  
  19. {  
  20.    printf (  
  21.             "IPADDR  options:\n"  
  22.             "[!] --ipsrc <ip>\t\t The incoming ip addr matches.\n"  
  23.             "[!] --ipdst <ip>\t\t The outgoing ip addr matches.\n"  
  24.             "\n"  
  25.          );  
  26. }  
  27.   
  28. static struct option ipaddr_opts[] = {  
  29.    { .name = "ipsrc",   .has_arg = 1,   .flag = 0,   .val = '1' },  
  30.    { .name = "ipdst",   .has_arg = 1,   .flag = 0,   .val = '2' },  
  31.    { .name = 0 }  
  32. };  
  33.   
  34. static void ipaddr_init(struct xt_entry_match *m)  
  35. {  
  36.    /* Can't cache this  
  37.    *nfcache |= NFC_UNKNOWN;*/  
  38. }  
  39.   
  40.   
  41. __be32 in_aton(const char *str)  
  42. {  
  43.     unsigned long l;  
  44.     unsigned int val;  
  45.     int i;  
  46.   
  47.     l = 0;  
  48.     for (i = 0; i < 4; i++)  
  49.     {  
  50.         l <<= 8;  
  51.         if (*str != '\0')  
  52.         {  
  53.             val = 0;  
  54.             while (*str != '\0' && *str != '.' && *str != '\n')  
  55.             {  
  56.                 val *= 10;  
  57.                 val += *str - '0';  
  58.                 str++;  
  59.             }  
  60.             l |= val;  
  61.             if (*str != '\0')  
  62.                 str++;  
  63.         }  
  64.     }  
  65.     return htonl(l);  
  66. }  
  67.   
  68.   
  69. struct in_addr* dotted_to_addr(const char *arg)  
  70. {  
  71.     struct in_addr * p;  
  72.     p = malloc(sizeof(struct in_addr));  
  73.     printf("%x\n",p);  
  74.     p->s_addr = in_aton(arg);  
  75.     return p;     
  76. }  
  77.   
  78. static void parse_ipaddr(const char *arg, __u32 *ipaddr)  
  79. {  
  80.    struct in_addr *ip;  
  81.    printf("in parse_ipaddr arg is %s",arg);  
  82.    ip = dotted_to_addr(arg);  
  83.    if (!ip)  
  84.       xtables_error(PARAMETER_PROBLEM, "ipt_ipaddr: Bad IP address `%s'\n", arg);  
  85.   
  86.    *ipaddr = ip->s_addr;  
  87. }  
  88.   
  89. static int ipaddr_parse(int c, char **argv, int invert, unsigned int *flags,  
  90.                  const struct ipt_entry *entry,  
  91.                  struct ipt_entry_match **match)  
  92. {  
  93.    struct ipt_ipaddr_info *info = (struct ipt_ipaddr_info *)(*match)->data /*NULL*/;  
  94.    printf("entered ipaddr_parse\n");  
  95.    switch(c) {  
  96.       case '1':  
  97.          if (*flags & IPADDR_SRC)  
  98.             xtables_error(PARAMETER_PROBLEM, "ipt_ipaddr: Only use --ipsrc once!");  
  99.          *flags |= IPADDR_SRC;  
  100.   
  101.          info->flags |= IPADDR_SRC;  
  102.          if (invert)  
  103.             info->flags |= IPADDR_SRC_INV;  
  104.   
  105.          parse_ipaddr(argv[optind-1], &info->ipaddr.src);  
  106.          break;  
  107.   
  108.       case '2':  
  109.          if (*flags & IPADDR_DST)  
  110.             xtables_error(PARAMETER_PROBLEM, "ipt_ipaddr: Only use --ipdst once!");  
  111.          *flags |= IPADDR_DST;  
  112.   
  113.          info->flags |= IPADDR_DST;  
  114.          if (invert)  
  115.             info->flags |= IPADDR_DST_INV;  
  116.   
  117.          parse_ipaddr(argv[optind-1], &info->ipaddr.dst);  
  118.          break;  
  119.   
  120.       default:  
  121.          return 0;  
  122.    }  
  123.   
  124.    return 1;  
  125. }  
  126.   
  127. static void ipaddr_final_check(unsigned int flags)  
  128. {  
  129.    if (!flags)  
  130.       xtables_error(PARAMETER_PROBLEM, "ipt_ipaddr: Invalid parameters.");  
  131. }  
  132.   
  133. /*  
  134.  * Can't call it ipaddr, because 
  135.  * the main structure is already 
  136.  * called like that. 
  137.  */  
  138. static void print_ipaddr(__u32 *ip_addr)  
  139. {  
  140.    printf(  "%u.%u.%u.%u ",   
  141.             ((unsigned char *)ip_addr)[0],  
  142.             ((unsigned char *)ip_addr)[1],  
  143.             ((unsigned char *)ip_addr)[2],  
  144.             ((unsigned char *)ip_addr)[3]  
  145.          );  
  146. }  
  147.   
  148. static void ipaddr_print(const struct ipt_ip *ip,  
  149.                   const struct ipt_entry_match *match,  
  150.                   int numeric)  
  151. {  
  152.    const struct ipt_ipaddr_info *info = (const struct ipt_ipaddr_info *)match->data;  
  153.    printf("entered ipaddr_print\n");  
  154.    if (info->flags & IPADDR_SRC) {  
  155.          printf("src IP ");  
  156.       if (info->flags & IPADDR_SRC_INV)  
  157.          printf("! ");  
  158.       print_ipaddr((__u32 *)&info->ipaddr.src);  
  159.    }  
  160.   
  161.    if (info->flags & IPADDR_DST) {  
  162.       printf("dst IP ");  
  163.       if (info->flags & IPADDR_DST_INV)  
  164.          printf("! ");  
  165.       print_ipaddr((__u32 *)&info->ipaddr.dst);  
  166.    }  
  167. }  
  168.   
  169. /*  
  170.  * iptables-saves 
  171.  */  
  172. static void ipaddr_save(const struct ipt_ip *ip, const struct ipt_entry_match *match)  
  173. {  
  174.    const struct ipt_ipaddr_info *info = (const struct ipt_ipaddr_info *)match->data;  
  175.    printf("entered ipaddr_save\n");  
  176.    if (info->flags & IPADDR_SRC) {  
  177.       if (info->flags & IPADDR_SRC_INV)  
  178.          printf("! ");  
  179.       printf("--ipsrc ");  
  180.       print_ipaddr((__u32 *)&info->ipaddr.src);  
  181.    }  
  182.   
  183.    if (info->flags & IPADDR_DST) {  
  184.       if (info->flags & IPADDR_DST_INV)  
  185.          printf("! ");  
  186.       printf("--ipdst ");  
  187.       print_ipaddr((__u32 *)&info->ipaddr.dst);  
  188.    }  
  189. }  
  190.   
  191. static struct xtables_match ipaddr = {  
  192.     .family      = NFPROTO_UNSPEC,  
  193.     .name            = "ipaddr",  
  194.     .version         = XTABLES_VERSION,  
  195.     .size            = XT_ALIGN(sizeof(struct ipt_ipaddr_info)),  
  196.     .userspacesize   = XT_ALIGN(sizeof(struct ipt_ipaddr_info)),  
  197.     .help            = ipaddr_help,  
  198.    /// .init            = ipaddr_init,  
  199.     .parse           = ipaddr_parse,  
  200.     .final_check     = ipaddr_final_check,  
  201.     .print           = ipaddr_print,  
  202.     .save            = ipaddr_save,  
  203.     .extra_opts      = ipaddr_opts  
  204. };  
  205.   
  206. void _init(void)  
  207. {  
  208.    xtables_register_match(&ipaddr);  
  209. }  



Makefile文件:
  1. EXTRA_CFLAGS    := -g -O2   ##Debug info .  
  2. KVERS = $(shell uname -r)  
  3.   
  4. ifneq ($(KERNELRELEASE),)  
  5.   
  6. obj-m           = ipaddr.o  
  7.   
  8. ipaddr-objs             := ipt_ipaddr.o  
  9. else  
  10. KDIR := /lib/modules/$(KVERS)/build  
  11.   
  12. all:  
  13.     make -C $(KDIR) M=$(PWD) modules  
  14.   
  15. clean:  
  16.     rm -f *.ko *.o *.mod.o *.mod.c *.order *~  *.symvers  
  17.   
  18. endif  





原文鏈接:
http://www.linuxfocus.org/ChineseGB/February2005/article367.shtml
發佈了15 篇原創文章 · 獲贊 9 · 訪問量 35萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章