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

时间: 2024-12-07 06:38:42

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

Linux 内核防火墙的工作原理一

Linux的内核提供的防火墙功能通过netfiter框架实现,并提供iptables工具配置和修改防火墙的规则 netfilter的通用框架不依赖于具体的协议,而是为每种网络协议定义一套钩子函数.这些钩子函数在 数据包经过协议栈的几个关键点时被调用,在这几个点中,协议栈将数据包及钩子函数作为参数,传递 netfilter框架 对于每种网络协议定义的钩子函数,任何内核模块可以对每种协议的一个或多个钩子函数进行注册, 实现挂接.这样当某个数据包被传递给netfilter框架时,内核能检测到是否有有关

Linux数据包路由原理、Iptables/netfilter入门学习

相关学习资料 https://www.frozentux.net/iptables-tutorial/cn/iptables-tutorial-cn-1.1.19.html http://zh.wikipedia.org/wiki/Netfilter http://www.netfilter.org/projects/iptables/ http://linux.vbird.org/linux_server/0250simple_firewall.php http://linux.vbird.o

Linux内核中网络数据包的接收-第一部分 概念和框架

与网络数据包的发送不同,网络收包是异步的的,因为你不确定谁会在什么时候突然发一个网络包给你,因此这个网络收包逻辑其实包含两件事:1.数据包到来后的通知2.收到通知并从数据包中获取数据这两件事发生在协议栈的两端,即网卡/协议栈边界以及协议栈/应用边界:网卡/协议栈边界:网卡通知数据包到来,中断协议栈收包:协议栈栈/应用边界:协议栈将数据包填充socket队列,通知应用程序有数据可读,应用程序负责接收数据.本文就来介绍一下关于这两个边界的这两件事是怎么一个细节,关乎网卡中断,NAPI,网卡poll,

linux 内核网络数据包接收流程

转:https://segmentfault.com/a/1190000008836467 本文将介绍在Linux系统中,数据包是如何一步一步从网卡传到进程手中的. 如果英文没有问题,强烈建议阅读后面参考里的两篇文章,里面介绍的更详细. 本文只讨论以太网的物理网卡,不涉及虚拟设备,并且以一个UDP包的接收过程作为示例. 本示例里列出的函数调用关系来自于kernel 3.13.0,如果你的内核不是这个版本,函数名称和相关路径可能不一样,但背后的原理应该是一样的(或者有细微差别) 网卡到内存 网卡需

Linux内核--网络栈实现分析(二)--数据包的传递过程(上)

本文分析基于Linux Kernel 1.2.13 原创作品,转载请标明http://blog.csdn.net/yming0221/article/details/7492423 更多请看专栏,地址http://blog.csdn.net/column/details/linux-kernel-net.html 作者:闫明 注:标题中的”(上)“,”(下)“表示分析过程基于数据包的传递方向:”(上)“表示分析是从底层向上分析.”(下)“表示分析是从上向下分析. 上一篇博文中我们从宏观上分析了L

【转】Netfilter机制

转自http://ycnian.org/blog/archives/628 Netfilter是Linux内核网络子系统中的一个模块,这个模块可以拦截系统中的报文进行处理.Linux系统中的防火墙iptables就是构建在netfilter模块之上的.报文在一台Linux主机中的流通过程如下图所示:假设一台Linux主机的eth0端口接收到了一个报文,Linux主机首先会查找路由表,判断这个报文的目的地址是否是自己.如果是自己,那么就逐层剥掉报文头,然后提交给应用程序处理.如果目的地址不是自己,

利用nf_conntrack机制存储路由,省去每包路由查找

IP是无连接的,因此IP路由是每包一路由的,数据包通过查找路由表获取路由,这是现代操作协议协议栈IP路由的默认处理方式.可是假设协议栈具有流识别能力,是不是能够基于流来路由呢?答案无疑是肯定的. 设计思想 在Linux的实现中,nf_conntrack能够做到基于流的IP路由,大致思想就是,仅仅针对一个流的第一个正向包和第一个反向包查找标准的IP路由表,将结果保存在conntrack项中,兴许的属于同一流的数据包直接取出路由项来使用.背后的思想是:这能够省去查找路由表的开销,是这样吗?也不全是!

利用反射机制,获取类的字段、方法、并实现简单调用

这篇文章是为之后要介绍Android的ICO框架做预备的,所以,如果想最近学习Android的ICO框架的同学,可以稍微看一下. 首先,简单介绍一下Java里面的反射. JAVA反射机制是在运行状态中,对于任意一个类,都能够知道这个类的所有属性和方法:对于任意一个对象,都能够调用它的任意一个方法和属性:这种动态获取的信息以及动态调用对象的方法的功能称为java语言的反射机制. 不知道这样的一段解释,你能否看懂.如果更简单的说,反射就是能够根据你给出类名实例化出一个实实在在的对象.所以,对象的实例

java中利用反射机制绕开编译器对泛型的类型限制

首先看下面这个例子 public static void main(String[] args) { ArrayList<Integer> al1 = new ArrayList<Integer>(); al1.add(1); ArrayList<String> al2 = new ArrayList<String>(); al2.add("hello"); //int型链表和string型链表,结果为true System.out.pr