1. 程式人生 > >利用netfilter機制,實現核心防火牆把http請求和迴應的資料包截獲後,解釋出其中的http層資料

利用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");