亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

Chinaunix

標(biāo)題: netlink+netfilter+BloomFilter內(nèi)核態(tài)過濾URL [打印本頁]

作者: ubuntuer    時間: 2009-12-17 22:42
標(biāo)題: netlink+netfilter+BloomFilter內(nèi)核態(tài)過濾URL
利用一天的時間在各位老大dreamice godbach  platinum等大佬的指定下,終于完成了一個內(nèi)核過濾url的初級版本,只是提供一個解決方案 應(yīng)用層防火墻呵呵^_^
問題肯定還是多多的,對http協(xié)議的了解也是有限的...
   可以參考我的以下帖子
     http://linux.chinaunix.net/bbs/thread-1149479-1-1.html  這個是內(nèi)核中提取URL的
     http://linux.chinaunix.net/bbs/v ... =1134519&extra=  這個是netlink+netfilter實(shí)現(xiàn)簡單的封IP和封ICMP協(xié)議
     
   這里大致的思路是先利用netlink將需要過濾的url傳到內(nèi)核,內(nèi)核根據(jù)bloom filter的思路來實(shí)現(xiàn)內(nèi)核中提取的url是否需要過濾
   關(guān)于bloom filter可以看我blog里的這篇文章..用戶態(tài)bloom filter的使用 http://blog.chinaunix.net/u2/76292/showart_2055618.html具體的
   使用例子google下一大堆 內(nèi)核中URL過濾我借鑒了這個實(shí)現(xiàn)
   
   好了開始代碼
   用戶態(tài)url.c:
  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. #define NETLINK_TEST 21
  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.    {"help",no_argument, NULL, 'h'},
  24.    {"host",required_argument, NULL, 'H'},
  25.    {0,0,0,0}
  26.   };

  27. void print_help(char* str)
  28. {
  29. fprintf(stderr,"%s --host(-H)\n",str);
  30. fprintf(stderr,"%s --help(-h)\n",str);
  31. fprintf(stderr,"eg:\n%s --host [url]www.chinaunix.net[/url]\n",str);
  32. }
  33.       

  34. int main(int argc, char* argv[])
  35. {
  36.     int c;
  37.     char host[20]="www.baidu.com";
  38.    
  39.    while((c=getopt_long(argc, argv, "hH:", longopts, NULL))!=-1)   
  40.     {
  41.       switch(c)
  42.        {
  43.          case 'H':
  44.           {
  45.             sprintf(host,"%s",optarg);
  46.             break;
  47.           }
  48.          case 'h':
  49.            {
  50.             print_help(argv[0]);
  51.             return -1;
  52.            }
  53.         
  54.          default:
  55.           break;
  56.        }

  57.     }  

  58.    sock_fd = socket(PF_NETLINK, SOCK_RAW, NETLINK_TEST);
  59.    memset(&msg, 0, sizeof(msg));
  60.    memset(&src_addr, 0, sizeof(src_addr));
  61.    src_addr.nl_family = AF_NETLINK;
  62.    src_addr.nl_pid = getpid(); /* self pid */
  63.    src_addr.nl_groups = 0; /* not in mcast groups */
  64.    bind(sock_fd, (struct sockaddr*)&src_addr, sizeof(src_addr));
  65.    memset(&dest_addr, 0, sizeof(dest_addr));
  66.    dest_addr.nl_family = AF_NETLINK;
  67.    dest_addr.nl_pid = 0; /* For Linux Kernel */
  68.    dest_addr.nl_groups = 0; /* unicast */

  69.    nlh=(struct nlmsghdr *)malloc(NLMSG_SPACE(MAX_PAYLOAD));
  70.    /* Fill the netlink message header */
  71.    nlh->nlmsg_len = NLMSG_SPACE(MAX_PAYLOAD);
  72.    nlh->nlmsg_pid = getpid(); /* self pid */
  73.    nlh->nlmsg_flags = 0;
  74.    /* Fill in the netlink message payload */
  75.    printf("now we will filter %s\n", host);
  76.    memcpy(NLMSG_DATA(nlh),host ,sizeof(host));

  77.    iov.iov_base = (void *)nlh;
  78.    iov.iov_len = nlh->nlmsg_len;
  79.    msg.msg_name = (void *)&dest_addr;
  80.    msg.msg_namelen = sizeof(dest_addr);
  81.    msg.msg_iov = &iov;
  82.    msg.msg_iovlen = 1;

  83.    printf(" Sending message. ...\n");
  84.    sendmsg(sock_fd, &msg, 0);
  85.    close(sock_fd);
  86.    return 0;
  87. }
復(fù)制代碼



內(nèi)核態(tài)urlfilter.c:
  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. #define NETLINK_TEST 21
  15. #define TABLE_SIZE   13
  16. #define SETBIT(a, n) (a[n/32] |= (1<<(n%32)))
  17. #define GETBIT(a, n) (a[n/32] & (1<<(n%32)))

  18. unsigned int a[5];

  19. static struct nf_hook_ops nfho;
  20. struct sock *nl_sk = NULL;
  21. EXPORT_SYMBOL_GPL(nl_sk);

  22. static char* host = NULL;

  23. unsigned int sax_hash(const char *key)
  24. {
  25.         unsigned int h=0;

  26.         while(*key) h^=(h<<5)+(h>>2)+(unsigned char)*key++;

  27.         return h%TABLE_SIZE;
  28. }

  29. unsigned int sdbm_hash(const char *key)
  30. {
  31.         unsigned int h=0;
  32.         while(*key) h=(unsigned char)*key++ + (h<<6) + (h<<16) - h;
  33.         return h%TABLE_SIZE;
  34. }

  35. void input (struct sock* sk, int len)
  36. {
  37.   struct sk_buff* skb = NULL;
  38.   struct nlmsghdr* nlh = NULL;

  39.   printk("net_link: data is ready to read.\n");
  40.   while((skb = skb_dequeue(&sk->sk_receive_queue))!=NULL)
  41.    {
  42.     nlh = (struct nlmsghdr*)skb->data;
  43.     host = (char *)NLMSG_DATA(nlh);
  44.    }

  45.   printk("host is %s\n", host);
  46.   if(host!=NULL)
  47.           {
  48.                   SETBIT(a, sax_hash(host));
  49.                   SETBIT(a, sdbm_hash(host));
  50.           }
  51.          
  52.   return;
  53. }

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

  56.   if (!nl_sk) {
  57.     printk(KERN_ERR "net_link: Cannot create netlink socket.\n");
  58.     return -EIO;
  59.   }
  60.   printk("net_link: create socket ok.\n");
  61.   return 0;
  62. }

  63. int check_http(const unsigned char* haystack, unsigned int len)
  64. {
  65.    char  url[100];
  66.    char* host_tmp;
  67.    char* url_tmp = url;
  68.    
  69.    if(len>4)
  70.     {
  71.     #if 1
  72.      printk("len is %d\n", len);
  73.      //printk("%s\n", haystack);
  74.     #endif
  75.      if(memcmp(haystack, "GET", 3)==0||memcmp(haystack,"POST", 4)==0)   
  76.        {
  77.          host_tmp = strstr(haystack,"Host:");
  78.          host_tmp += 5;
  79.          if(*host_tmp==' ')
  80.              host_tmp++;

  81.          while(*host_tmp!='\r')
  82.              *url_tmp++ = *host_tmp++;

  83.          *url_tmp='\0';  
  84.          printk("http connect----Host:%s\n",url);
  85.          if(GETBIT(a, sax_hash(url))&&GETBIT(a, sdbm_hash(url)))
  86.                  {
  87.              printk("we drop packet of host:%s", url);
  88.              return 1;
  89.             }
  90.        }
  91.    }
  92.    return 0;
  93. }

  94. unsigned int hook_func(unsigned int hooknum,
  95.                        struct sk_buff **skb,
  96.                        const struct net_device *in,
  97.                        const struct net_device *out,
  98.                        int (*okfn)(struct sk_buff *))
  99. {
  100.   struct iphdr *iph = NULL;
  101.     struct tcphdr *tcph = NULL;
  102.     struct tcphdr _otcph;
  103.     unsigned char* haystack;
  104.     int hlen;


  105.     iph = ip_hdr(*skb);
  106.     haystack =(char*)iph+(iph->ihl*4);
  107.     hlen = ntohs(iph->tot_len)-(iph->ihl*4);

  108.     if (iph->protocol == IPPROTO_TCP) {
  109.         tcph = skb_header_pointer(*skb, ip_hdrlen(*skb), sizeof(_otcph), &_otcph);
  110.       
  111.         haystack += tcph->doff*4;
  112.         hlen -= tcph->doff*4;
  113.      
  114.      if(check_http(haystack, hlen))
  115.              return NF_DROP;
  116.     }

  117.     return NF_ACCEPT;
  118. }

  119. static int __init hook_init(void)
  120. {
  121.              int i =0;
  122.        printk("insmod url filter!\n");
  123.        test_netlink();
  124.        nfho.hook      = hook_func;
  125.        nfho.hooknum   = NF_IP_LOCAL_OUT;
  126.        nfho.pf        = PF_INET;
  127.        nfho.priority  = NF_IP_PRI_FIRST;
  128.    
  129.        nf_register_hook(&nfho);

  130.        for(;i<5;i++)
  131.          a[i]=0;
  132.        return 0;
  133. }

  134. static void __exit hook_exit(void)
  135. {
  136.     printk("rmmod url filter!\n");
  137.     nf_unregister_hook(&nfho);
  138.     if (nl_sk != NULL){
  139.       sock_release(nl_sk->sk_socket);
  140.      }
  141. }

  142. module_init(hook_init);
  143. module_exit(hook_exit);
復(fù)制代碼


Makefile:
  1. obj-m += urlfilter.o
  2. KDIR := /lib/modules/$(shell uname -r)/build

  3. all:
  4.         make -C $(KDIR) M=$(shell pwd) modules
  5.         gcc -Wall -o url url.c
  6. clean:
  7.         make -C $(KDIR) M=$(shell pwd) clean
  8.         rm -f *odule* user
復(fù)制代碼


使用的話
./url --host www.chinaunix.net過濾[url]www.chianunix.net[/url]
./url  默認(rèn)過濾www.baidu.com

實(shí)際效果貌似不是很好^_^ 可能跟數(shù)據(jù)包的分片等有關(guān)系  希望大家能給出點(diǎn)完善的思路  我自己也將繼續(xù)學(xué)習(xí)
也不知道思路對不對,自己瞎整的,還望各位指點(diǎn)


[ 本帖最后由 ubuntuer 于 2009-12-17 22:43 編輯 ]
作者: ubuntuer    時間: 2009-12-17 22:44
從圖中可以看出是drop了部分包的,可能由于分片等之類結(jié)果可能不盡人意,希望大家給點(diǎn)思路
作者: dreamice    時間: 2009-12-17 22:58
標(biāo)題: 回復(fù) #2 ubuntuer 的帖子
其實(shí)你過濾的是www.chinaunix.net這個域名的包,呵呵,URL是什么東東,概念有點(diǎn)混啊
作者: ubuntuer    時間: 2009-12-18 13:03
恩  這個要考慮的問題太多了....
一般這應(yīng)用層防火墻是這么做的嗎?  在內(nèi)核中千辛萬苦的抓包分析DEBUG.....   太難了^_^
作者: ubuntuer    時間: 2009-12-18 13:09
姜哥看看這個
http://blog.chinaunix.net/u/12313/showart_148073.html
九賤大哥寫的DNS過濾 vs URL過濾  受益匪淺   
研究下DNS協(xié)議
作者: T-Bagwell    時間: 2009-12-18 13:58
樓主是做這個工作吧?
作者: duanjigang    時間: 2009-12-18 14:02
偶做的是基于DNS過濾URL的,效果比較明顯。
如果基于http報文來過濾的話,感覺比較麻煩:wink:
作者: Godbach    時間: 2009-12-18 14:04
原帖由 duanjigang 于 2009-12-18 14:02 發(fā)表
偶做的是基于DNS過濾URL的,效果比較明顯。
如果基于http報文來過濾的話,感覺比較麻煩:wink:


相當(dāng)于是在源頭做處理了, 通過DNS也請求不到域名對應(yīng)的IP
作者: duanjigang    時間: 2009-12-18 14:28
原帖由 Godbach 于 2009-12-18 14:04 發(fā)表


相當(dāng)于是在源頭做處理了, 通過DNS也請求不到域名對應(yīng)的IP

yes,但是他如果通過IP來訪問的話,就沒治了,正如九賤說的
作者: ubuntuer    時間: 2009-12-18 15:01
原帖由 T-Bagwell 于 2009-12-18 13:58 發(fā)表
樓主是做這個工作吧?

我還沒畢業(yè),呵呵!!  今年研三剛找完工作,現(xiàn)在是出于無聊中!
作者: wendaozhe    時間: 2009-12-18 16:30
學(xué)習(xí),學(xué)習(xí)!
作者: Godbach    時間: 2009-12-18 17:19
原帖由 duanjigang 于 2009-12-18 14:28 發(fā)表

yes,但是他如果通過IP來訪問的話,就沒治了,正如九賤說的


就是,如果本地緩存有DNS的相關(guān)信息,這個方法就沒辦法了。 應(yīng)該說還是有局限性的
作者: Godbach    時間: 2009-12-18 17:21
如果基于http報文來過濾的話,感覺比較麻煩

但是這種方式應(yīng)該是更常用的。
作者: kinglongno1    時間: 2009-12-21 20:40
iptables -I FORWARD -p tcp --dport 80 -m string --algo bm --string "www.chinaunix" -j DROP
一句命令搞定。。。
作者: platinum    時間: 2009-12-21 20:57
原帖由 kinglongno1 于 2009-12-21 20:40 發(fā)表
iptables -I FORWARD -p tcp --dport 80 -m string --algo bm --string "www.chinaunix" -j DROP
一句命令搞定。。。

如果你用 webmail 收郵件,而恰好郵件里有一封標(biāo)題是 www.chinaunix.net,那會怎樣?
如果你訪問 www.chinaunix.net 網(wǎng)站時,恰好里面所有敏感信息都是圖片,那又會怎樣?
如果 www.chinaunix.net 的服務(wù)端口不是 80 而是 81,那又會怎樣?
如果你訪問 163 門戶網(wǎng)站,而恰好 163 又與 chinaunix 有合作,互加了對方連接,那又會怎樣呢?

技術(shù)無絕對,所謂的“一句命令搞定”實(shí)在不敢恭維……
作者: Godbach    時間: 2009-12-21 21:20
標(biāo)題: 回復(fù) #15 platinum 的帖子
呵呵,這條命令是將數(shù)據(jù)包內(nèi)容中有string的也進(jìn)行drop了。那是有點(diǎn)粗暴
作者: ubuntuer    時間: 2009-12-21 22:56
原帖由 kinglongno1 于 2009-12-21 20:40 發(fā)表
iptables -I FORWARD -p tcp --dport 80 -m string --algo bm --string "www.chinaunix" -j DROP
一句命令搞定。。。

不發(fā)表任何意見




歡迎光臨 Chinaunix (http://72891.cn/) Powered by Discuz! X3.2