免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 8259 | 回复: 3

netlink+netfilter实例 [复制链接]

论坛徽章:
0
发表于 2009-09-09 20:20 |显示全部楼层
再次见识了内核的伟大,大半年不碰,忘记的一干二净!!!写netfilter,netlink不得不提的就是九贱和duanjigang了...
   Linux 用户态与内核态的交互——netlink 篇
       http://bbs.chinaunix.net/viewthread.php?tid=822500
  netlink socket 编程之 why & how
          http://linux.chinaunix.net/bbs/viewthread.php?tid=1031932&extra=page%3D1%26amp%3Bfilter%3Ddigest

  有了上面两篇文章加kernel source基本上你可以干许多事了...
  环境:
       centos5.2 2.6.18
  作用:
       ./user -i 禁止ping
       ./user -d ipaddr 禁止指定ip的tcp连接
       iptables+netfilter这一套以前一直是限于理论层面,今天就自己实践了下.

  我这里只是写我写程序的过程中遇到的问题,一些概念上的东东,上面两位大师已经写得很好了,我就不班门弄斧了.
      

  1.           struct sock* netlink_kernel_create(int unit, unsigned int groups,
  2.                       void (*input)(struct sock *sk, int len),
  3.                       struct module *module)
  4.       
复制代码

       why&how那篇是:
     

  1.         struct sock * netlink_kernel_create(int unit, void (*input)(struct sock *sk, int len));
  2.       
复制代码


    取数据我这里传的是结构体
   

  1.          nlh = (struct nlmsghdr*)skb->data;
  2.          icmp_off = ((OWN *)NLMSG_DATA(nlh))->icmp_off;
  3.          drop_ip = ((OWN *)NLMSG_DATA(nlh))->drop_ip;
  4.      
复制代码

      netlink主要就是create和取数据那个地方,我这里是看kernel source追寻到了,不同的版本可能不一样.


   

  1.         nfho.hook      = hook_func;
  2.         nfho.hooknum   = NF_IP_LOCAL_IN;
  3.         nfho.pf        = PF_INET;
  4.         nfho.priority  = NF_IP_PRI_FIRST;
  5.        nf_register_hook(&nfho);
  6.      
复制代码

      想挂多个hook的话可以
   

  1.           nf_register_hook(&nfho);
  2.           nf_register_hook(&nfho1);   
  3.   
复制代码

      也可以
   

  1.           nf_register_hooks(opts, ARRAY_SIZE(opts));
  2.       
复制代码

      
    取头,可以去ip.h tcp.h等去找
   

  1.         skb_header_pointer
  2.      
复制代码



    好了废话了这么多,上代码了
   内核态程序
  

  1.       #include <linux/module.h>
  2. #include <linux/kernel.h>
  3. #include <linux/skbuff.h>
  4. #include <linux/ip.h>
  5. #include <linux/in.h>
  6. #include <net/tcp.h>
  7. #include <net/icmp.h>
  8. #include <linux/netfilter.h>
  9. #include <linux/netfilter_ipv4.h>
  10. #include <linux/types.h>
  11. #include <linux/sched.h>
  12. #include <net/sock.h>
  13. #include <net/netlink.h>
  14. #include "hook.h"

  15. static struct nf_hook_ops nfho;
  16. struct sock *nl_sk = NULL;
  17. EXPORT_SYMBOL_GPL(nl_sk);

  18. static int icmp_off = 0;
  19. static unsigned int drop_ip = 0;

  20. void input (struct sock* sk, int len)
  21. {
  22.   struct sk_buff* skb = NULL;
  23.   struct nlmsghdr* nlh = NULL;

  24.   printk("net_link: data is ready to read.\n");
  25.   while((skb = skb_dequeue(&sk->sk_receive_queue))!=NULL)
  26.    {
  27.     nlh = (struct nlmsghdr*)skb->data;
  28.     icmp_off = ((OWN *)NLMSG_DATA(nlh))->icmp_off;
  29.     drop_ip = ((OWN *)NLMSG_DATA(nlh))->drop_ip;
  30.    }

  31.   return;
  32. }

  33. static int test_netlink(void) {
  34.   nl_sk = netlink_kernel_create(NETLINK_TEST, 0, input, THIS_MODULE);

  35.   if (!nl_sk) {
  36.     printk(KERN_ERR "net_link: Cannot create netlink socket.\n");
  37.     return -EIO;
  38.   }
  39.   printk("net_link: create socket ok.\n");
  40.   return 0;
  41. }

  42. unsigned int hook_func(unsigned int hooknum,
  43.                        struct sk_buff **skb,
  44.                        const struct net_device *in,
  45.                        const struct net_device *out,
  46.                        int (*okfn)(struct sk_buff *))
  47. {
  48.    struct sk_buff *sb = *skb;
  49.    struct iphdr     *iph ;

  50.    iph = ip_hdr(sb);
  51.    switch(iph->protocol)
  52.     {
  53.      case IPPROTO_ICMP:{
  54.          struct icmphdr _icmph;
  55.          struct icmphdr* ich;

  56.          ich = skb_header_pointer(sb, iph->ihl*4, sizeof(_icmph), &_icmph);
  57.          printk("icmp type %u\n", ich->type);
  58.          if(icmp_off == 1)
  59.           {
  60.             printk("now we drop icmp from %d.%d.%d.%d\n", NIPQUAD(iph->saddr));
  61.             return NF_DROP;
  62.           }
  63.          break;
  64.        }
  65.      case IPPROTO_TCP:{
  66.          struct tcphdr* th = NULL;
  67.          struct tcphdr _tcph;
  68.          th = skb_header_pointer(sb, iph->ihl*4, sizeof(_tcph), &_tcph);
  69.          if(th == NULL)
  70.           {
  71.             printk("get tcp header error\n");
  72.             return NF_DROP;
  73.           }
  74.          //unsigned int sip = ntohs(th->source);
  75.          printk("saddr:%d.%d.%d.%d,sport:%u\n", NIPQUAD(iph->saddr),ntohs(th->source));
  76.          printk("daddr:%d.%d.%d.%d,dport:%u\n", NIPQUAD(iph->daddr),ntohs(th->dest));
  77.          if(iph->saddr ==drop_ip)
  78.           {
  79.             printk("now we drop tcp from %d.%d.%d.%d\n", NIPQUAD(iph->saddr));
  80.              return NF_DROP;
  81.           }
  82.          break;
  83.        }
  84.      default:
  85.          break;
  86.     }
  87.   return NF_ACCEPT;
  88. }

  89. static int __init hook_init()
  90. {
  91.        printk("insmod hook test!\n");
  92.        test_netlink();
  93.        nfho.hook      = hook_func;
  94.        nfho.hooknum   = NF_IP_LOCAL_IN;
  95.        nfho.pf        = PF_INET;
  96.        nfho.priority  = NF_IP_PRI_FIRST;
  97.    
  98.        nf_register_hook(&nfho);

  99.        return 0;
  100. }

  101. static void __exit hook_exit()
  102. {
  103.     printk("rmmod hook test!\n");
  104.     nf_unregister_hook(&nfho);
  105.     if (nl_sk != NULL){
  106.       sock_release(nl_sk->sk_socket);
  107.   }
  108. }

  109. module_init(hook_init);
  110. module_exit(hook_exit);

  111.    
复制代码

  
  用户态:


  1. #include <sys/stat.h>
  2. #include <unistd.h>
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <sys/socket.h>
  6. #include <netinet/in.h>
  7. #include <arpa/inet.h>
  8. #include <sys/types.h>
  9. #include <string.h>
  10. #include <asm/types.h>
  11. #include <linux/netlink.h>
  12. #include <linux/socket.h>
  13. #include <getopt.h>
  14. #include "hook.h"

  15. #define MAX_PAYLOAD 1024 /* maximum payload size*/

  16. struct sockaddr_nl src_addr, dest_addr;
  17. struct nlmsghdr *nlh = NULL;
  18. struct iovec iov;
  19. int sock_fd;
  20. struct msghdr msg;
  21. struct option longopts[] =
  22. {
  23.    {"icmp",no_argument, NULL, 'i'},
  24.    {"help",no_argument, NULL, 'h'},
  25.    {"drop",required_argument, NULL, 'd'},
  26.    {0,0,0,0}
  27.   };

  28. void print_help(char* str)
  29. {
  30. fprintf(stderr,"%s --icmp(-i)\n",str);
  31. fprintf(stderr,"%s --drop(-d)\n",str);
  32. fprintf(stderr,"eg:\n%s -i -d 202.114.85.105\n",str);
  33. }

  34. void init_own(OWN** own)
  35. {
  36. *own = (OWN*)malloc(sizeof(OWN));
  37. (*own)->icmp_off = 0;
  38. (*own)->drop_ip = 0;
  39. }        

  40. int main(int argc, char* argv[])
  41. {
  42.    int c;
  43.    OWN* own = NULL;
  44.    init_own(&own);

  45.    while((c=getopt_long(argc, argv, "hid:", longopts, NULL))!=-1)   
  46.     {
  47.       switch(c)
  48.        {
  49.          case 'i':
  50.           {
  51.             own->icmp_off = 1;
  52.             break;
  53.           }
  54.          case 'd':
  55.           {
  56.             own->drop_ip = inet_addr(optarg);
  57.             break;
  58.           }
  59.          case 'h':
  60.            {
  61.             print_help(argv[0]);
  62.             return -1;
  63.            }
  64.         
  65.          default:
  66.           break;
  67.        }

  68.     }  

  69.    sock_fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_TEST);
  70.    memset(&msg, 0, sizeof(msg));
  71.    memset(&src_addr, 0, sizeof(src_addr));
  72.    src_addr.nl_family = AF_NETLINK;
  73.    src_addr.nl_pid = getpid(); /* self pid */
  74.    src_addr.nl_groups = 0; /* not in mcast groups */
  75.    bind(sock_fd, (struct sockaddr*)&src_addr, sizeof(src_addr));
  76.    memset(&dest_addr, 0, sizeof(dest_addr));
  77.    dest_addr.nl_family = AF_NETLINK;
  78.    dest_addr.nl_pid = 0; /* For Linux Kernel */
  79.    dest_addr.nl_groups = 0; /* unicast */

  80.    nlh=(struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_PAYLOAD));
  81.    /* Fill the netlink message header */
  82.    nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);
  83.    nlh->nlmsg_pid = getpid(); /* self pid */
  84.    nlh->nlmsg_flags = 0;
  85.    /* Fill in the netlink message payload */
  86.    printf("%d, %d\n", own->icmp_off, own->drop_ip);
  87.    memcpy(NLMSG_DATA(nlh),own ,sizeof(OWN));

  88.    iov.iov_base = (void *)nlh;
  89.    iov.iov_len = nlh->nlmsg_len;
  90.    msg.msg_name = (void *)&dest_addr;
  91.    msg.msg_namelen = sizeof(dest_addr);
  92.    msg.msg_iov = &iov;
  93.    msg.msg_iovlen = 1;

  94.    printf(" Sending message. ...\n");
  95.    sendmsg(sock_fd, &msg, 0);
  96.    close(sock_fd);
  97.    free(own);
  98.    return 0;
  99. }
复制代码

  
Makefile  头文件

  1. hook.h
  2. #define NETLINK_TEST 21

  3. typedef struct my
  4. {
  5.   int icmp_off;
  6.   unsigned int drop_ip;
  7. }OWN;

  8. makefile:
  9.   obj-m += hook.o
  10. KDIR := /lib/modules/$(shell uname -r)/build

  11. all:
  12.         make -C $(KDIR) M=$(shell pwd) modules
  13.         gcc -Wall -o user user.c
  14. clean:
  15.         make -C $(KDIR) M=$(shell pwd) clean
  16.         rm -f *odule* user

复制代码


usage:
         1.make
         2. insmod hook.ko (建议tail -f /var/log/messages查看是否success尤其是netlink create是否成功)
         3.默认你是可以ping, 和tcp得(我实验室只有两台机子A 202.114.85.105)
         4. ./user -i  -d 202.114.85.105 (A机不能ping和ftp B)
         5../user (取消限制了,可以ping和ftp B)

再次试验成功上传代码:

[ 本帖最后由 ubuntuer 于 2009-9-9 20:23 编辑 ]

netlink+netfilter.rar

2.71 KB, 下载次数: 241

论坛徽章:
0
发表于 2009-09-09 20:26 |显示全部楼层
半天的劳动成果,累!!!不是为了找工作也不会重新捡这让人掉头发的内核^_^

论坛徽章:
0
发表于 2009-09-09 23:48 |显示全部楼层
不错的总结

但是 netlink 有时也会丢包,出现 kernel -> user 但 user 收不到的情况,如果能解决这个问题就好了

论坛徽章:
0
发表于 2009-09-10 16:51 |显示全部楼层
对啊。
这个内核态发向用户态的丢包问题很郁闷、、、、
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP