免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3260 | 回复: 8
打印 上一主题 下一主题

[网络子系统] 请教一个问题,Netfilter过滤URL,遇到视频类网站内核崩溃 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2014-06-02 10:05 |只看该作者 |倒序浏览
如题,用Netfilter写了一段代码来打印HOST和URI信息,编译后可正常打印出URL,当浏览器打开腾讯视频等一些内容的时候,内核就崩溃了,麻烦各位大牛帮忙分析一下,谢谢!
  1. #ifndef __KERNEL__
  2. #define __KERNEL__
  3. #endif
  4. #ifndef MODULE
  5. #define MODULE
  6. #endif

  7. #include   <linux/module.h>
  8. #include   <linux/kernel.h>
  9. #include   <linux/skbuff.h>
  10. #include   <linux/in.h>
  11. #include   <linux/ip.h>
  12. #include   <linux/tcp.h>
  13. #include   <linux/icmp.h>
  14. #include   <linux/netdevice.h>
  15. #include   <linux/netfilter.h>
  16. #include   <linux/netfilter_ipv4.h>
  17. #include   <linux/if_arp.h>
  18. #include   <linux/if_ether.h>
  19. #include   <linux/if_packet.h>
  20. #include   <linux/mm.h>
  21. #include   <linux/fs.h>
  22. #include   <linux/uaccess.h>
  23. #include   <asm/uaccess.h>

  24. //#define    DEBUG

  25. MODULE_LICENSE("GPL");

  26. char* h_tmp ;           //HOST
  27. char* u_tmp ;           //URI


  28. static struct nf_hook_ops nfho;


  29. //获取HOST
  30. void print_host(const unsigned char* start,unsigned int len)
  31. {
  32.         char* host_tmp ;
  33.         char* url_tmp ;
  34.         int i = 0;
  35.         int j = 0;
  36.         if (len > 4)
  37.         {
  38.            if (0 == strncmp(start, "GET", 3) || 0 == strncmp(start, "POST", 4))
  39.            {
  40.                 /*获取HOST的值*/
  41.                    host_tmp = strstr(start,"Host:");
  42.                    if(memcmp(host_tmp,"Host:",5) == 0)
  43.                    {
  44.                            host_tmp = host_tmp + 6;               // 跳过HOST: 这6个字符
  45.                            while(*host_tmp!='\r')
  46.                            {
  47.                                    host_tmp++;
  48.                                    i++;
  49.                            }
  50.                                 host_tmp -= i;
  51.                                 h_tmp = kmalloc((i + 1)*sizeof(char),GFP_KERNEL);
  52.                                 memcpy(h_tmp,host_tmp,i);
  53.                                 *(h_tmp+i) ='\0';
  54.                                 printk(">>>Host:%s",h_tmp);
  55.                                 kfree(h_tmp);
  56.                    }
  57.                 /*获取GET后面的参数*/
  58.                            url_tmp = strstr(start,"/");            /*从/开始获取GET后面的URI部分*/
  59.                            while(*url_tmp!=' ')                                /*到空格的地方结束*/
  60.                                 {
  61.                                    url_tmp++;
  62.                                    j++;
  63.                                 }
  64.                            url_tmp -=j;
  65.                            u_tmp = kmalloc((j + 1)*sizeof(char),GFP_KERNEL);
  66.                            memcpy(u_tmp,url_tmp,j);
  67.                            *(u_tmp+j) ='\0';
  68.                            printk("%s\n",u_tmp);
  69.                            kfree(u_tmp);
  70.                    }
  71.          }
  72. }

  73. /* HOOK函数 */
  74. unsigned int hook_func(unsigned int hooknum,
  75.                                            struct sk_buff *skb,
  76.                                            const struct net_device *in,
  77.                                            const struct net_device *out,
  78.                                            int (*okfn)(struct sk_buff *))
  79. {
  80.         char * payload = NULL;
  81.         struct sk_buff* sb = skb;                                                                                        //定义一个Linux网络数据包缓存
  82.         struct iphdr *iph = ip_hdr(sb);                                                                        //定义一个ip报文的数据报头

  83. /*读取文件结束,过滤掉skb_buf为空以及iph为空的数据包*/
  84.         if(sb == NULL)
  85.           return NF_ACCEPT;
  86.         if(iph == NULL)
  87.           return NF_ACCEPT;

  88. /*判断是否为TCP协议,不是TCP协议的数据包直接return NF_ACCEPT*/
  89.         if (iph && iph->protocol && (iph->protocol == IPPROTO_TCP)) {
  90.                 //struct tcphdr* tcph = (void *)iph + iph->ihl*4;                           //TCP报文的头部
  91.                 struct tcphdr* tcph =(void *)iph +(iph->ihl<<2);
  92.                 unsigned int srcport = tcph->source;                                                 //源端口
  93.                 unsigned int dstport = tcph->dest;                                                   //目的端口
  94.                 unsigned int ack_seq_num = tcph->ack_seq;                                                   //ACK-SEQ的值
  95.                 unsigned int seq_num = tcph->seq;                                                              //SEQ的值
  96.                 unsigned int ip_saddr = ntohl(iph->saddr);                                                  //源IP
  97.                 unsigned int ip_daddr = ntohl(iph->daddr);                                                  //目的IP
  98.                 unsigned int len_tot = ntohs(iph->tot_len);                                                  //包总长度
  99.                 unsigned int len_tcp = len_tot - iph->ihl*4 - tcph->doff*4;         //TCP包的长度

  100. /*判断tcph是否为空,为空直接返回NF_ACCEPT*******/
  101.             if(tcph == NULL)
  102.                return NF_ACCEPT;
  103. /*判断目的端口是否为80************************/
  104.                 if (ntohs(dstport) == 80 )                                                                                   //筛选远端口或者目的
  105.                 {
  106.                         if (0 != skb_linearize(sb))
  107.                            return NF_ACCEPT;

  108. //                   payload = (char*)iph+(iph->ihl*4) + tcph->doff*4;
  109.                    payload = (void *)tcph + (tcph->doff<<2);
  110.                    print_host(payload,len_tcp);                                                                                     //DEBUG模式下打印HOST 和 URL

  111.                     if (0 == strncmp(payload, "GET", 3) || 0 == strncmp(payload, "POST", 4))
  112.                          {

  113.                                          printk("**************Request**************\n");
  114.                                          printk("In-Device :%s         Out-Device:%s\n",in->name,out->name);
  115.                                          printk("Src IP    :%d.%d.%d.%d \n", (ip_saddr & 0xff000000) >> 24,
  116.                                                                                                                   (ip_saddr & 0x00ff0000) >> 16,
  117.                                                                                                                   (ip_saddr & 0x0000ff00) >> 8,
  118.                                                                                                                   (ip_saddr & 0x000000ff));
  119.                                          printk("Dst IP    :%d.%d.%d.%d \n", (ip_daddr & 0xff000000) >> 24,
  120.                                                                                                                  (ip_daddr & 0x00ff0000) >> 16,
  121.                                                                                                                 (ip_daddr & 0x0000ff00) >> 8,
  122.                                                                                                                  (ip_daddr & 0x000000ff));
  123.                                          printk("ID        :%u\n",ntohs(iph->id));
  124.                                          printk("Src-Port  :%d         Dst-Port:%d\n", ntohs(srcport), ntohs(dstport));
  125.                                          printk("Seq       :0x%2x\n", ntohl(seq_num));
  126.                                          printk("Ack_Seq   :0x%2x\n", ntohl(ack_seq_num));
  127.                                          printk("Tcp len   :%u\n",len_tcp);
  128.                                          printk("Next ack  :%u\n",ntohl(seq_num + len_tcp ));
  129.                                          printk("*******************************\n");
  130.                                          return NF_ACCEPT;
  131.                          }
  132.                          return NF_ACCEPT;
  133.                 }
  134.         }

  135.         return NF_ACCEPT;
  136. }

  137. /* 加载模块 */
  138. int init_module() {
  139.         nfho.hook = hook_func;                                     //钩子函数指针
  140.         nfho.hooknum = NF_INET_POST_ROUTING;    //hook类型
  141.         nfho.pf = PF_INET;                                            //协议簇,对于ipv4而言,是PF_INET
  142.         nfho.priority = NF_IP_PRI_FIRST;              //优先级
  143.         nf_register_hook(&nfho);

  144.         pr_info("Filter add into kernel!\r\n");
  145.         return 0;
  146. }
  147. /* 清除模块 */
  148. void cleanup_module() {
  149.         nf_unregister_hook(&nfho);
  150.         pr_info("Filter removed from kernel!\r\n");
  151. }
复制代码

论坛徽章:
36
IT运维版块每日发帖之星
日期:2016-04-10 06:20:00IT运维版块每日发帖之星
日期:2016-04-16 06:20:0015-16赛季CBA联赛之广东
日期:2016-04-16 19:59:32IT运维版块每日发帖之星
日期:2016-04-18 06:20:00IT运维版块每日发帖之星
日期:2016-04-19 06:20:00每日论坛发贴之星
日期:2016-04-19 06:20:00IT运维版块每日发帖之星
日期:2016-04-25 06:20:00IT运维版块每日发帖之星
日期:2016-05-06 06:20:00IT运维版块每日发帖之星
日期:2016-05-08 06:20:00IT运维版块每日发帖之星
日期:2016-05-13 06:20:00IT运维版块每日发帖之星
日期:2016-05-28 06:20:00每日论坛发贴之星
日期:2016-05-28 06:20:00
2 [报告]
发表于 2014-06-02 22:52 |只看该作者
回复 1# smillers
其实如果内核 oops 了,应该有一些有用的新的。

简单看了一下你解析 TCP 报文的问题,首先一个问题没有考虑,就是分片包的问题。如果是 TCP 的分片报文,那么根本就没有所谓的 tcp header 让你解引用了。

此外,一个吹毛求疵的小问题:
        if(iph == NULL)
          return NF_ACCEPT;

/*判断是否为TCP协议,不是TCP协议的数据包直接return NF_ACCEPT*/
        if (iph && iph->protocol && (iph->protocol == IPPROTO_TCP)) {

最后那个条件判断,可以简化了为

if (iph->protocol == IPPROTO_TCP)

你 iph 都判断过了,没必要多两个冗余的条件。

   

论坛徽章:
15
射手座
日期:2014-02-26 13:45:082015年迎新春徽章
日期:2015-03-04 09:54:452015年辞旧岁徽章
日期:2015-03-03 16:54:15羊年新春福章
日期:2015-02-26 08:47:552015年亚洲杯之卡塔尔
日期:2015-02-03 08:33:45射手座
日期:2014-12-31 08:36:51水瓶座
日期:2014-06-04 08:33:52天蝎座
日期:2014-05-14 14:30:41天秤座
日期:2014-04-21 08:37:08处女座
日期:2014-04-18 16:57:05戌狗
日期:2014-04-04 12:21:33技术图书徽章
日期:2014-03-25 09:00:29
3 [报告]
发表于 2014-06-03 08:38 |只看该作者
具体可能还得通过kdump,或者串口抓点信息来看。
也可能是printk打印太频繁导致?

论坛徽章:
0
4 [报告]
发表于 2014-06-03 10:42 |只看该作者
Godbach 发表于 2014-06-02 22:52
回复 1# smillers
其实如果内核 oops 了,应该有一些有用的新的。


版主说的这个,可以线性化一下

论坛徽章:
0
5 [报告]
发表于 2014-06-05 19:12 |只看该作者
本帖最后由 huangbanban 于 2014-06-05 19:17 编辑

host_tmp = strstr(start,"Host:");
url_tmp = strstr(start,"/");
strstr函数的使用让我有些不安,没有限制查找的范围,因为是网络数据包
要是能够实现这样一个函数再使用,也许更安心一些吧
strnstr(char* s1, char*s2, int pos)

论坛徽章:
0
6 [报告]
发表于 2014-06-09 10:18 |只看该作者
本帖最后由 smillers 于 2014-06-09 10:23 编辑

好像是strstr()函数的问题,重写了一个函数,解决了,现在已经不崩溃了回复 5# huangbanban


   

论坛徽章:
0
7 [报告]
发表于 2014-06-09 10:23 |只看该作者
好像是strstr()函数的问题你,重写了一个,解决了,现在已经不崩溃了回复 5# huangbanban


   

论坛徽章:
0
8 [报告]
发表于 2014-06-09 10:41 |只看该作者
恭喜恭喜,呵呵

论坛徽章:
0
9 [报告]
发表于 2015-03-25 09:25 |只看该作者
大哥,strstr是什么问题呀?
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP