利用netfilter机制,实现内核防火墙把http请求和回应的数据包截获后,解释出其中的http层数据
2014-11-04 12:44
344 查看
#include<linux/init.h>
#include<linux/kernel.h>
#include<linux/module.h>
#include<linux/netfilter_ipv4.h>
#include<linux/skbuff.h>
#include<linux/ip.h>
#include<linux/tcp.h>
#include<linux/if_ether.h>
#include<linux/if_packet.h>
unsigned int change(int aChar,int hex)
{
int ch;
ch = aChar - hex;
return ch;
}
unsigned char HexToAsc(int aChar)
{
/*if(aChar>=0x20&&aChar<=0x7E)
{
return ' '+(aChar-0x20);
}*/
/*if((aChar>=0x0)&&(aChar<=0x9))
return 0+change(aChar,0x0);
if((aChar>=0xA)&&(aChar<=0xF))
return 0+change(aChar,0xA);
if((aChar>=0x10)&&(aChar<=0x19))
return 16+change(aChar,0x10);
if((aChar>=0x1A)&&(aChar<=0x1F))
return 26+change(aChar,0x1A);*/
if(aChar == 0x20)
return 32;
/*if(aChar == 0x7F)
return 127;*/
if(aChar == 0xA)
return 10;
if(aChar == 0xD)
return 13;
if((aChar>=0x21)&&(aChar<=0x2F))
{
int ch = change(aChar,0x21);
return '!'+ch;
}
if((aChar>=0x30)&&(aChar<=0x39))
{
int ch = change(aChar,0x30);
return '0'+ch;
}
if((aChar>=0x3A)&&(aChar<=0x40))
{
int ch = change(aChar,0x3A);
return ':'+ch;
}
if((aChar>=0x41)&&(aChar<=0x5A))
{
int ch = change(aChar,0x41);
return 'A'+ch;
}
if((aChar>=0x5B)&&(aChar<=0x60))
{
int ch = change(aChar,0x5B);
return '['+change;
}
if((aChar>=0x61)&&(aChar<=0x7A))
{
int ch = change(aChar,0x61);
return 'a'+ch;
}
if((aChar>=0x7B)&&(aChar<=0x7E))
{
int ch = change(aChar,0x7B);
return '{'+ch;
}
return NULL;
}
//nf_in钩子执行函数hf_hook_in
static unsigned int nf_hook_in(unsigned int hooknum,struct sk_buff **skb,const struct net_device *in,const struct net_device *out,int (*okfn)(struct sk_buff*))
{
int i;
struct sk_buff *sk = NULL;
sk = skb_copy(skb,GFP_ATOMIC);
struct iphdr *iph = ip_hdr(sk);//获取ip头指针
struct tcphdr *tcph;//tcp头指针
tcph = (void*)iph + iph->ihl*4;//获取tcp开始位置
//int char_int1,char_int2;
//char c1 = NULL;
//char c2 = NULL;
if(iph->protocol == IPPROTO_TCP)//截获的是TCP类型的包
{
if((tcph->source == htons(8080)||tcph->source == htons(80))&&(sk->len > 40))//接收的包源地址端口是8080或80端口的并且包长度大于40个字节
{
if(tcph->source == htons(8080))//源地址端口号是8080,接收的8080端口的包
{
printk("receive package starting:this is a http 8080 package!\n");
for(i=40;i<sk->len;i++)//从第40个字节以后开始获取数据data部分
{
printk("%x ",*(sk->data+i));
}
printk("\n");
for(i=40;i<sk->len;i++)//从第40个字节以后开始获取数据data部分
{
printk("%c",HexToAsc(*(sk->data+i)));
}
printk("\nreceive ended!\n");
}
else//源地址端口号是80,接收的是80端口的包
{
printk("receive package starting:this is a http 80 package!\n");
for(i=40;i<sk->len;i++)//从第40个字节以后开始获取数据data部分
{
printk("%x ",*(sk->data+i));
}
printk("\n");
for(i=40;i<sk->len;i++)//从第40个字节以后开始获取数据data部分
{
printk("%c",HexToAsc(*(sk->data+i)));
}
printk("\nreceive ended!\n");
}
}
}
return NF_ACCEPT;
}
//nf_out钩子执行函数hf_hook_out
static unsigned int nf_hook_out(unsigned int hooknum,struct sk_buff **skb,const struct net_device *in,const struct net_device *out,int (*okfn)(struct sk_buff*))
{
int i;
struct sk_buff *sk = NULL;
sk = skb_copy(skb,GFP_ATOMIC);
struct iphdr *iph = ip_hdr(sk);//获取ip头指针
struct tcphdr *tcph;//tcp头指针
tcph = (void*)iph + iph->ihl*4;//获取tcp开始位置
//int char_int1,char_int2;
//char c1 = NULL;
//char c2 = NULL;
if(iph->protocol == IPPROTO_TCP)//发送的是TCP类型的包
{
if((tcph->dest == htons(8080)||tcph->dest == htons(80))&&(sk->len > 40))//发送的包目的地址端口是8080或80端口的并且包长度大于40个字节
{
if(tcph->dest == htons(8080))//目的地址端口号是8080,发送的是前往8080端口的包
{
printk("send package starting:this is a http 8080 package!\n");
for(i=40;i<sk->len;i++)//从第40个字节以后开始获取数据data部分
{
printk("%x ",*(sk->data+i));
}
printk("\n");
for(i=40;i<sk->len;i++)//从第40个字节以后开始获取数据data部分
{
printk("%c",HexToAsc(*(sk->data+i)));
}
printk("\nsend ended!\n");
}
else//目的地址端口号是80,发送的是前往80端口的包
{
printk("send package starting:this is a http 80 package!\n");
for(i=40;i<sk->len;i++)//从第40个字节以后开始获取数据data部分
{
printk("%x ",*(sk->data+i));
}
printk("\n");
for(i=40;i<sk->len;i++)//从第40个字节以后开始获取数据data部分
{
printk("%c",HexToAsc(*(sk->data+i)));
}
printk("\nsend ended!\n");
}
}
}
return NF_ACCEPT;
}
//初始化nf_in钩子,在钩子LOCAL_IN上
static struct nf_hook_ops nf_in =
{
.hook = nf_hook_in,//绑定执行函数nf_hook_in()
.hooknum = NF_INET_LOCAL_IN,//钩子类型
.pf = PF_INET,//指定IPv4协议族
.priority = 0//指定在执行的顺序中,这个hook函数应当在被放在什么地方
};
//初始化nf_out钩子,在钩子LOCAL_OUT上
static struct nf_hook_ops nf_out =
{
.hook = nf_hook_out,//绑定执行函数nf_hook_out()
.hooknum = NF_INET_LOCAL_OUT,//钩子类型
.pf = PF_INET,//指定IPv4协议族
.priority = 0//指定在执行的顺序中,这个hook函数应当在被放在什么地方
};
static int __init nf_init(void){//模块入口
nf_register_hook(&nf_in);//注册nf_in钩子函数
nf_register_hook(&nf_out);//注册nf_out钩子函数
return 0;
}
static void __exit//模块退出
nf_exit(void){
nf_unregister_hook(&nf_in);//注销nf_in钩子函数
nf_unregister_hook(&nf_out);//注销nf_out钩子函数
}
module_init(nf_init);
module_exit(nf_exit);
MODULE_LICENSE("GPL");
#include<linux/kernel.h>
#include<linux/module.h>
#include<linux/netfilter_ipv4.h>
#include<linux/skbuff.h>
#include<linux/ip.h>
#include<linux/tcp.h>
#include<linux/if_ether.h>
#include<linux/if_packet.h>
unsigned int change(int aChar,int hex)
{
int ch;
ch = aChar - hex;
return ch;
}
unsigned char HexToAsc(int aChar)
{
/*if(aChar>=0x20&&aChar<=0x7E)
{
return ' '+(aChar-0x20);
}*/
/*if((aChar>=0x0)&&(aChar<=0x9))
return 0+change(aChar,0x0);
if((aChar>=0xA)&&(aChar<=0xF))
return 0+change(aChar,0xA);
if((aChar>=0x10)&&(aChar<=0x19))
return 16+change(aChar,0x10);
if((aChar>=0x1A)&&(aChar<=0x1F))
return 26+change(aChar,0x1A);*/
if(aChar == 0x20)
return 32;
/*if(aChar == 0x7F)
return 127;*/
if(aChar == 0xA)
return 10;
if(aChar == 0xD)
return 13;
if((aChar>=0x21)&&(aChar<=0x2F))
{
int ch = change(aChar,0x21);
return '!'+ch;
}
if((aChar>=0x30)&&(aChar<=0x39))
{
int ch = change(aChar,0x30);
return '0'+ch;
}
if((aChar>=0x3A)&&(aChar<=0x40))
{
int ch = change(aChar,0x3A);
return ':'+ch;
}
if((aChar>=0x41)&&(aChar<=0x5A))
{
int ch = change(aChar,0x41);
return 'A'+ch;
}
if((aChar>=0x5B)&&(aChar<=0x60))
{
int ch = change(aChar,0x5B);
return '['+change;
}
if((aChar>=0x61)&&(aChar<=0x7A))
{
int ch = change(aChar,0x61);
return 'a'+ch;
}
if((aChar>=0x7B)&&(aChar<=0x7E))
{
int ch = change(aChar,0x7B);
return '{'+ch;
}
return NULL;
}
//nf_in钩子执行函数hf_hook_in
static unsigned int nf_hook_in(unsigned int hooknum,struct sk_buff **skb,const struct net_device *in,const struct net_device *out,int (*okfn)(struct sk_buff*))
{
int i;
struct sk_buff *sk = NULL;
sk = skb_copy(skb,GFP_ATOMIC);
struct iphdr *iph = ip_hdr(sk);//获取ip头指针
struct tcphdr *tcph;//tcp头指针
tcph = (void*)iph + iph->ihl*4;//获取tcp开始位置
//int char_int1,char_int2;
//char c1 = NULL;
//char c2 = NULL;
if(iph->protocol == IPPROTO_TCP)//截获的是TCP类型的包
{
if((tcph->source == htons(8080)||tcph->source == htons(80))&&(sk->len > 40))//接收的包源地址端口是8080或80端口的并且包长度大于40个字节
{
if(tcph->source == htons(8080))//源地址端口号是8080,接收的8080端口的包
{
printk("receive package starting:this is a http 8080 package!\n");
for(i=40;i<sk->len;i++)//从第40个字节以后开始获取数据data部分
{
printk("%x ",*(sk->data+i));
}
printk("\n");
for(i=40;i<sk->len;i++)//从第40个字节以后开始获取数据data部分
{
printk("%c",HexToAsc(*(sk->data+i)));
}
printk("\nreceive ended!\n");
}
else//源地址端口号是80,接收的是80端口的包
{
printk("receive package starting:this is a http 80 package!\n");
for(i=40;i<sk->len;i++)//从第40个字节以后开始获取数据data部分
{
printk("%x ",*(sk->data+i));
}
printk("\n");
for(i=40;i<sk->len;i++)//从第40个字节以后开始获取数据data部分
{
printk("%c",HexToAsc(*(sk->data+i)));
}
printk("\nreceive ended!\n");
}
}
}
return NF_ACCEPT;
}
//nf_out钩子执行函数hf_hook_out
static unsigned int nf_hook_out(unsigned int hooknum,struct sk_buff **skb,const struct net_device *in,const struct net_device *out,int (*okfn)(struct sk_buff*))
{
int i;
struct sk_buff *sk = NULL;
sk = skb_copy(skb,GFP_ATOMIC);
struct iphdr *iph = ip_hdr(sk);//获取ip头指针
struct tcphdr *tcph;//tcp头指针
tcph = (void*)iph + iph->ihl*4;//获取tcp开始位置
//int char_int1,char_int2;
//char c1 = NULL;
//char c2 = NULL;
if(iph->protocol == IPPROTO_TCP)//发送的是TCP类型的包
{
if((tcph->dest == htons(8080)||tcph->dest == htons(80))&&(sk->len > 40))//发送的包目的地址端口是8080或80端口的并且包长度大于40个字节
{
if(tcph->dest == htons(8080))//目的地址端口号是8080,发送的是前往8080端口的包
{
printk("send package starting:this is a http 8080 package!\n");
for(i=40;i<sk->len;i++)//从第40个字节以后开始获取数据data部分
{
printk("%x ",*(sk->data+i));
}
printk("\n");
for(i=40;i<sk->len;i++)//从第40个字节以后开始获取数据data部分
{
printk("%c",HexToAsc(*(sk->data+i)));
}
printk("\nsend ended!\n");
}
else//目的地址端口号是80,发送的是前往80端口的包
{
printk("send package starting:this is a http 80 package!\n");
for(i=40;i<sk->len;i++)//从第40个字节以后开始获取数据data部分
{
printk("%x ",*(sk->data+i));
}
printk("\n");
for(i=40;i<sk->len;i++)//从第40个字节以后开始获取数据data部分
{
printk("%c",HexToAsc(*(sk->data+i)));
}
printk("\nsend ended!\n");
}
}
}
return NF_ACCEPT;
}
//初始化nf_in钩子,在钩子LOCAL_IN上
static struct nf_hook_ops nf_in =
{
.hook = nf_hook_in,//绑定执行函数nf_hook_in()
.hooknum = NF_INET_LOCAL_IN,//钩子类型
.pf = PF_INET,//指定IPv4协议族
.priority = 0//指定在执行的顺序中,这个hook函数应当在被放在什么地方
};
//初始化nf_out钩子,在钩子LOCAL_OUT上
static struct nf_hook_ops nf_out =
{
.hook = nf_hook_out,//绑定执行函数nf_hook_out()
.hooknum = NF_INET_LOCAL_OUT,//钩子类型
.pf = PF_INET,//指定IPv4协议族
.priority = 0//指定在执行的顺序中,这个hook函数应当在被放在什么地方
};
static int __init nf_init(void){//模块入口
nf_register_hook(&nf_in);//注册nf_in钩子函数
nf_register_hook(&nf_out);//注册nf_out钩子函数
return 0;
}
static void __exit//模块退出
nf_exit(void){
nf_unregister_hook(&nf_in);//注销nf_in钩子函数
nf_unregister_hook(&nf_out);//注销nf_out钩子函数
}
module_init(nf_init);
module_exit(nf_exit);
MODULE_LICENSE("GPL");
相关文章推荐
- Linux内核防火墙Netfilter实现机制
- 利用科来数据包播放器实现网络数据回放
- 利用proc 实现内核和用户态交换数据
- 利用 js-xlsx 实现 Excel 文件导入并解析Excel数据成json格式的数据并且获取其中某列数据
- 利用netfilter的hook来实现数据包的过滤(For Kernel2.4)
- 自己在项目中的学习总结:利用工厂模式+反射机制+缓存机制,实现动态创建不同的数据层对象接口
- 利用内核cgroup机制轻松实现类似docker的系统资源管控
- 利用消息机制实现.NET AOP(面向方面编程)--利用ServerContextSink实现多截获
- 利用proc 实现内核和用户态交换数据
- 利用MongoDB中oplog机制实现准实时数据的操作监控
- netfilter: Linux 防火墙在内核中的实现
- netfilter: Linux 防火墙在内核中的实现(“钓鱼”)
- netfilter:Linux 防火墙在内核中的实现
- 利用反射机制实现简单数据查询
- netfilter:Linux 防火墙在内核中的实现
- 利用proc 实现内核和用户态交换数据