利用netfilter机制,实现内核防火墙把http请求和回应的数据包截获后,解释出其中的http层数据

#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");


阅读更多
文章标签: linux 防火墙 ipv4
个人分类: linux 网络
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭