基于netfilter通过iptables过滤http请求使用netlink通知用户空间构造发送http响应(一)

来源:互联网 发布:js new操作符 编辑:程序博客网 时间:2024/04/29 19:12

1. 目标
基于Netfilter架构,通过Iptables过滤数据包,将符合条件的数据包,交由自己实现的HOOK函数进行解包处理,解析到HTTP协议之后,通过Netlink通知用户空间程序,经由用户空间程序进行HTTP响应包的封装,封装完毕后,对HTTP进行响应。

2. 参考资料
http://blog.chinaunix.net/uid/23069658/cid–1-list-4.html 文章(一)到(十六)
http://www.searchtb.com/2012/05/using-tcpcopy-to-simulate-traffic.html 利用tcpcopy引流做模拟在线测试
http://blog.chinaunix.net/uid-10167808-id-25974.html Linux内核发送构造数据包的方式
https://www.frozentux.net/iptables-tutorial/cn/iptables-tutorial-cn-1.1.19.html#PREROUTINGCHAIN Iptables 指南 1.1.19
http://blog.csdn.net/lickylin/article/details/38092091 Linux netfilter 学习笔记 之十五 netfilter模块添加一个match

3. 环境说明
VMware安装debian虚拟机作为编译机,程序执行机,安装内核源码,iptables、wget命令,IP为192.168.121.132,网络设置为仅主机模式
在PC上设置虚拟网卡VMnet1 IP为192.168.121.1,并安装nginx服务器(http://nginx.org/download/nginx-1.8.0.tar.gz)
在PC上安装wireshark工具

4. 测试示例
debian上配置”iptables -t filter -A OUTPUT -p tcp –source-port 23: -m pktsize –size 1:111 -j ACCEPT”
在debian虚拟机上执行”wget 192.168.121.1” 命令做http请求PC上的nginx服务器响应,iptables过滤到此http请求,netlink通知用户空间程序构造http响应并发送出响应。

5. 源码结构
第一部分:
libipt_pktsize.c 放到iptables源码extensions目录下编译,生成.so文件在用户空间解析iptables命令
ipt_pktsize.c 过滤http请求的ko内核模块
(源码基于http://blog.chinaunix.net/uid-23069658-id-3230608.html (十四)洞悉linux下的Netfilter&iptables:开发一个match模块【实战】)
第二部分:
kernel_nl4http.c 实现netlink通信NETLINK_HTTP的内核模块
第三部分:
http_agent.c 接收(发送)NETLINK_HTTP消息,构造并发送http响应

6. 遇到的问题
Q. 在”insmod ipt_pktsize.ko”时遇到”insmod unknown symbol in module”
A. iptables的x_tables.ko内核模块总是在系统崩溃后自动丢失,只需手动”insmod x_tabales.ko”即可

Q. 解包printk出来的内容跟实际值不符合
A. 注意ip头、tcp头后面都有可能跟着optional data

    ip_len = iph->ihl << 2;
    tcp_len = tcph->doff << 2;

Q. http请求内容找不到
A. 到skb_shinfo里去找,即使tcp的payload很小也有可能分包

    info_ptr = skb_shinfo(skb);    for (loop = 0; loop < info_ptr->nr_frags; loop++) {        page_ptr = info_ptr->frags[loop].page.p;        page_offset = info_ptr->frags[loop].page_offset;        page_size = info_ptr->frags[loop].size;        page_data_ptr = (unsigned char*)(page_address(page_ptr) + page_offset);

Q. 解析不出mac地址
A. 因为是在OUTPUT点,mac还没有填充,所以找不到

Q. 直接操作skb的具体字段可能会崩
A. TMD
比如:

        /*         * NOT DO THIS!!! WILL CRASH, AND WHY?         */        //memset((void*)skb->tail, 0, (size_t)((unsigned char*)skb->end - (unsigned char*)skb->tail));

7. 未完待续

0 0