昨天在和dreamice大哥聊应用层防火墙的时候,问了些比较白痴的问题....比如内核态获取URL...呵呵 今天实现了下发现也不是很难...参考了ipp2p那么多协议的分析...好了不废话了....
http.c
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
MODULE_LICENSE("GPL");
MODULE_AUTHOR("kenthy@163.com");
static struct nf_hook_ops os_attack_ops;
void check_http(const unsigned char* haystack, unsigned int len)
{
char url[100];
char* host_tmp;
char* url_tmp = url;
if(len>3)
{
#if 0
printk("len is %d\n", len);
printk("%s\n", haystack);
#endif
if(memcmp(haystack, "GET", 3)==0)
{
host_tmp = strstr(haystack,"Host:");
while(*host_tmp!='\r')
*url_tmp++ = *host_tmp++;
*url_tmp='\0';
printk("http connect----%s\n",url);
}
}
}
unsigned int
os_attack_detect(unsigned int hooknum,
struct sk_buff** skb,
const struct net_device *in,
const struct net_device *out,
int (*okfn)(struct sk_buff*))
{
struct iphdr *iph = NULL;
struct tcphdr *tcph = NULL;
struct tcphdr _otcph;
unsigned char* haystack;
int hlen;
iph = ip_hdr(*skb);
haystack =(char*)iph+(iph->ihl*4);
hlen = ntohs(iph->tot_len)-(iph->ihl*4);
if (iph->protocol == IPPROTO_TCP) {
tcph = skb_header_pointer(*skb, ip_hdrlen(*skb), sizeof(_otcph), &_otcph);
haystack += tcph->doff*4;
hlen -= tcph->doff*4;
check_http(haystack, hlen);
}
return NF_ACCEPT;
}
static int __init init(void)
{
int ret;
os_attack_ops.hook = os_attack_detect;
os_attack_ops.hooknum = NF_IP_LOCAL_OUT;
os_attack_ops.pf = PF_INET;
os_attack_ops.priority = NF_IP_PRI_FIRST;
ret = nf_register_hook(&os_attack_ops);
if (ret < 0) {
printk("http detect:can't register http detect hook!\n");
return ret;
}
printk("insmod http detect module\n");
return 0;
}
static void __exit fini(void)
{
nf_unregister_hook(&os_attack_ops);
printk("remove http detect module.\n");
}
module_init(init);
module_exit(fini);
Makefile
obj-m := http.o
KDIR := /lib/modules/$(shell uname -r)/build/
PWD := $(shell pwd)
all:module
module:
$(MAKE) -C $(KDIR) M=$(PWD) modules
clean:
rm -rf *.ko *.mod.c *.o Module.* modules.* .*.cmd .tmp_versions
脱掉外套ip头,在脱掉内衣tcp头,ok现在就是好色的你想要的了...也就是haystack了
haystack += tcph->doff*4;
hlen -= tcph->doff*4;
check_http(haystack, hlen);
这里的haystack就是上层的一些数据...
用wireshark抓包看到http请求如下:
"GET /u2/76292/ HTTP/1.1\r\n"
"Accept: */*\r\n"
"Accept-Language: zh-cn\r\n"
"Accept-Encoding: gzip, deflate\r\n"
"User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; CIBA; TheWorld)\r\n"
"Host:blog.chinaunix.net\r\n"
"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 编辑 ]