免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12345下一页
最近访问板块 发新帖
查看: 15915 | 回复: 46

内核态提取URL [复制链接]

论坛徽章:
0
发表于 2009-12-17 16:15 |显示全部楼层
昨天在和dreamice大哥聊应用层防火墙的时候,问了些比较白痴的问题....比如内核态获取URL...呵呵 今天实现了下发现也不是很难...参考了ipp2p那么多协议的分析...好了不废话了....
http.c

  1. #include <linux/module.h>
  2. #include <linux/kernel.h>
  3. #include <linux/init.h>

  4. #include <linux/netfilter.h>
  5. #include <linux/skbuff.h>
  6. #include <linux/ip.h>
  7. #include <linux/netdevice.h>
  8. #include <linux/if_ether.h>
  9. #include <linux/if_packet.h>
  10. #include <net/tcp.h>
  11. #include <net/udp.h>
  12. #include <net/icmp.h>
  13. #include <linux/netfilter_ipv4.h>

  14. MODULE_LICENSE("GPL");
  15. MODULE_AUTHOR("kenthy@163.com");

  16. static struct nf_hook_ops os_attack_ops;

  17. void check_http(const unsigned char* haystack, unsigned int len)
  18. {
  19.    char  url[100];
  20.    char* host_tmp;
  21.    char* url_tmp = url;

  22.    if(len>3)
  23.     {
  24.     #if 0
  25.      printk("len is %d\n", len);
  26.      printk("%s\n", haystack);
  27.     #endif

  28.      if(memcmp(haystack, "GET", 3)==0)   
  29.        {
  30.          host_tmp = strstr(haystack,"Host:");
  31.          while(*host_tmp!='\r')
  32.              *url_tmp++ = *host_tmp++;

  33.          *url_tmp='\0';  
  34.          printk("http connect----%s\n",url);
  35.        }
  36.    }
  37. }

  38. unsigned int
  39. os_attack_detect(unsigned int hooknum,
  40.                  struct sk_buff** skb,
  41.                  const struct net_device *in,
  42.                  const struct net_device *out,
  43.                  int (*okfn)(struct sk_buff*))
  44. {
  45.     struct iphdr *iph = NULL;
  46.     struct tcphdr *tcph = NULL;
  47.     struct tcphdr _otcph;
  48.     unsigned char* haystack;
  49.     int hlen;


  50.     iph = ip_hdr(*skb);
  51.     haystack =(char*)iph+(iph->ihl*4);
  52.     hlen = ntohs(iph->tot_len)-(iph->ihl*4);

  53.     if (iph->protocol == IPPROTO_TCP) {
  54.         tcph = skb_header_pointer(*skb, ip_hdrlen(*skb), sizeof(_otcph), &_otcph);
  55.       
  56.         haystack += tcph->doff*4;
  57.         hlen -= tcph->doff*4;
  58.      
  59.         check_http(haystack, hlen);
  60.     }

  61.     return NF_ACCEPT;
  62. }

  63. static int __init init(void)
  64. {
  65.     int ret;
  66.     os_attack_ops.hook = os_attack_detect;
  67.     os_attack_ops.hooknum = NF_IP_LOCAL_OUT;
  68.     os_attack_ops.pf = PF_INET;
  69.     os_attack_ops.priority = NF_IP_PRI_FIRST;

  70.     ret = nf_register_hook(&os_attack_ops);
  71.     if (ret < 0) {
  72.         printk("http detect:can't register http detect hook!\n");
  73.         return ret;
  74.     }
  75.     printk("insmod http detect module\n");
  76.     return 0;
  77. }

  78. static void __exit fini(void)
  79. {
  80.     nf_unregister_hook(&os_attack_ops);
  81.     printk("remove http detect module.\n");
  82. }

  83. module_init(init);
  84. module_exit(fini);

复制代码


Makefile


  1. obj-m := http.o

  2. KDIR := /lib/modules/$(shell uname -r)/build/
  3. PWD := $(shell pwd)

  4. all:module

  5. module:
  6.         $(MAKE) -C $(KDIR) M=$(PWD) modules

  7. clean:
  8.         rm -rf *.ko *.mod.c *.o Module.* modules.* .*.cmd .tmp_versions

复制代码

脱掉外套ip头,在脱掉内衣tcp头,ok现在就是好色的你想要的了...也就是haystack了

  1.   haystack += tcph->doff*4;
  2.   hlen -= tcph->doff*4;
  3.   check_http(haystack, hlen);
复制代码

这里的haystack就是上层的一些数据...

用wireshark抓包看到http请求如下:

  1. "GET /u2/76292/ HTTP/1.1\r\n"
  2.      "Accept: */*\r\n"
  3.      "Accept-Language: zh-cn\r\n"
  4.      "Accept-Encoding: gzip, deflate\r\n"
  5.      "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; CIBA; TheWorld)\r\n"
  6.      "Host:blog.chinaunix.net\r\n"
  7.      "Connection: Keep-Alive\r\n\r\n";
复制代码

我这里只是提取了Host你可以根据自己需要提取别的...

if(memcmp(haystack, "GET", 3)==0) //这里并没有使用端口判断...直接看头三个char是不是GET,这里也可以||memcmp(haystack, "POST", 4)   
       {
/*就是找到Host,所以Accept  Accept-Language Host的顺序不是固定的,所以别根据第几行,也就是多少个'\n'来找
   至于strstr函数这个不是这里考虑的,我也没看strstr的源码,你们自己也可以写kmp来找到Host*/
     host_tmp = strstr(haystack,"Host:");

       /*这里就是将Host:blog.chinaunix.net赋给url_tmp了*/
         while(*host_tmp!='\r')
             *url_tmp++ = *host_tmp++;

         *url_tmp='\0';  
         printk("http connect----%s\n",url);
       }



ok其实也蛮简单的,弄清楚了的话...   有个帖子是url过滤的..   今天先休息下,明天基于这个url提取再做个URL过滤的....
代码在CentOS5.3 2.6.18上测试通过了

图片是测试结果

[ 本帖最后由 ubuntuer 于 2009-12-17 16:19 编辑 ]
http.JPG

评分

参与人数 1可用积分 +15 收起 理由
dreamice + 15 原创内容,继续努力,多完善一下

查看全部评分

论坛徽章:
0
发表于 2009-12-17 16:18 |显示全部楼层

  1.     if (iph->protocol == IPPROTO_TCP) {
  2.         tcph = skb_header_pointer(*skb, ip_hdrlen(*skb), sizeof(_otcph), &_otcph);
  3.       
  4.         haystack += tcph->doff*4;
  5.         hlen -= tcph->doff*4;
  6.      
  7.         check_http(haystack, hlen);
复制代码

这样,当 IP 头和 TCP 头都带有 options 的话,算出来的 haystack 会不会有问题?

论坛徽章:
0
发表于 2009-12-17 16:21 |显示全部楼层
原帖由 platinum 于 2009-12-17 16:18 发表

    if (iph->protocol == IPPROTO_TCP) {
        tcph = skb_header_pointer(*skb, ip_hdrlen(*skb), sizeof(_otcph), &_otcph);
      
        haystack += tcph->doff*4;
        hlen -= tcph->do ...

恩  谢谢版主指点,我再研究研究,因为我看ipp2p就是这么写的^_^

[ 本帖最后由 ubuntuer 于 2009-12-17 16:23 编辑 ]

论坛徽章:
3
金牛座
日期:2014-06-14 22:04:062015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:49:45
发表于 2009-12-17 17:01 |显示全部楼层

回复 #2 platinum 的帖子

肯定会有问题的,所以要判断http协议头部的一些字段,否则指针很可能就跑飞了

论坛徽章:
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
发表于 2009-12-17 17:03 |显示全部楼层
对啊,另外IP头和TCP头的长度都可以计算得出的。
ipheadlen = iph->ihl*4
tcpheadlen = tcp->doff *4

论坛徽章:
3
金牛座
日期:2014-06-14 22:04:062015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:49:45
发表于 2009-12-17 17:03 |显示全部楼层

回复 #3 ubuntuer 的帖子

他这个应该问题不大,主要是check GET包,呵呵

论坛徽章:
0
发表于 2009-12-17 17:06 |显示全部楼层
原帖由 dreamice 于 2009-12-17 17:01 发表
肯定会有问题的,所以要判断http协议头部的一些字段,否则指针很可能就跑飞了

我是这样做的

  1. iph = ip_hdr(skb);
  2. if (iph->protocol == IPPROTO_TCP) {
  3.     tcph = (void *)iph + (iph->ihl << 2);
  4.     payload = (void *)tcph + (tcph->doff << 2);
  5. }
复制代码

论坛徽章:
3
金牛座
日期:2014-06-14 22:04:062015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:49:45
发表于 2009-12-17 17:20 |显示全部楼层
原帖由 platinum 于 2009-12-17 17:06 发表

我是这样做的

iph = ip_hdr(skb);
if (iph->protocol == IPPROTO_TCP) {
    tcph = (void *)iph + (iph->ihl doff  


白金兄的移位操作用得好,这个才是效率,哈哈,学习了!

论坛徽章:
0
发表于 2009-12-17 17:41 |显示全部楼层
向你们学习!

论坛徽章:
0
发表于 2009-12-17 17:44 |显示全部楼层
dreamice大哥,我在这个的基础上正在写url过滤的...  
发现怎么有的时候GET不起作用?? 刚修改成strstr(,"HTTP/1.1")直接把内核搞挂了^_^
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP