探索iptables BPF模块的悲惨历程_bpf iptables-程序员宅基地

前面一篇文章提到了两个Netfilter上的新玩意儿,其中之一就是bpf match模块,另一个nftables的ball还没有放出来,即使放出来了,它的吸引力也没有bpf match大,毕竟伯克利的东西不可小觑啊!虽然nftables也是借用了BPF的思想,但是能看得出的仅在代码层面上,反之,bpf match模块却是iptables质的飞跃,综合状态机,JIT(及时编译技术),它可以在很短的时间内完成数据包的匹配判断,据作者那帮子说相比传统iptables硬编码match来讲,及时编译过基于状态机的match集合的匹配执行效率要提高X倍!我只是听说,并没有亲见。
        这东西一直没有时间仔细尝试,昨晚小小半夜就开始闹,我也就再也睡不着了,想起了iptables的bpf模块,不由想赶紧试一把,然而为了配置一条成功的使用bpf模块的iptables规则,前期工作可真不少啊,列举如下,每个步骤我会在后面详述:
1.下载一个最新的Debian 7发行版并安装(本可以在现有的版本直接升级的,但早就想有一个全新的环境,趁此夜晚网速极快,下载吧)
2.下载最新的kernel source以及最新的iptables source
3.构建编译工具套件
4.编译最新的内核以及驱动以及iptables
5.编写可以生效的使用bpf模块的iptables规则

这5个步骤中,第1步时间相对长一些,我是下载了全部的映像,一共14G左右,其实如果选择网络安装,会更加省时一些,我无所谓了,反正是深夜,下载过程中磁盘猛转,我也不闲着,昨天刚买了半套《罗马人的故事》(因为钱比较紧张,先买半套,看完了再买吧),下载过程中我看了大半本《胜者的迷思》,正沉浸在苏拉进军罗马的XX中,下载结束。第2个步骤的下载简直不是什么问题,具体的链接我就不给出了,想玩的都知道,版本通告一下:
kernel:3.9.6
iptables:1.4.19.1

接下来的事情就不能一笔带过了,但是在详述之前还是要带几笔,第3部是必要的,因为既然选择了Debian,就是喜欢它的工具集,否则随便一个发行版即可,第5步看似只是一个水到渠成的结果,然后这个步骤是我花时间最多的。

构建编译工具套件

Debian自身有一套编译kernel的工具,称为kernel-package,它可以将最终生成的kernel映像,driver,initrd映像以及开发使用的headers打包成一个deb包,可以直接安装在Debian发行版上,如果没有这个套件,你毫无疑问就要花很多时间来编译内核以及driver了,光是initrd就不一定能一次性做成功,即使你把这些都封装进了shell,你也要时刻关注shell的执行,起码不可能按下回车后去再看一段《胜者的迷思》了,由于使用了kernel-package,在编译过程中,我竟然把《胜者的迷思》看完了!Debian的工具是专门为Debian上的开发者打造的,所以即使有问题,早就被其它人通告给了Debian社区,早就改正了。构建这个工具套件很简单:
apt-get install kernel-package
另外,为了能使用menuconfig配置kernel,还要安装一个东西:
apt-get install libncurses5-dev

编译最新的内核以及驱动

必要的工具构建完毕,剩下的就是编译内核了,这次折腾的直接目的是玩bpf模块,因此切记要在menuconfig配置内核的时候使能BPF配置,它在Core Netfilter Configuration中的"bpf" match support,其它的就先别管了,直接使用Debian 7的config文件即可,然后就可以目睹kernel-package的风采了,注意上述的操作要分步骤完成:
第一步:cp /boot/config-3.2.0-4-amd64 /usr/src/linux-3.9.6/.config
第二步:make menuconfig
第三步:make-kpkg --initrd kernel-image && make-kpkg kernel-headers && find /usr/src/ -type deb -name *.deb|xargs -i dpkg -i {} &&reboot
第四步:找本书看,或者找个电影看,但是为了让电脑全速编译,还是换一台电脑心理上会得到安慰(Note:心理上!);
以上就编译完了新内核了,uname看一下,已经升级到3.9.6了,kernel-header也在/usr/src下就位,/lib/modules/3.9.6/build也就位,剩下的工作就是编译iptables了,这个十分简单,也分为几个步骤:
第一步:configure --enable-nfbpf-compiler;这个enable特别重要,其实这是我在写iptables规则屡次不成功后返回来重新加上这个选项编译的,一开始我是直接configure的,自以为耍小聪明可以过关,结果在编写iptables测试的时候悲剧了!
第二步:make && make install

准备工作到此就做完了,此时的时间是上午8点半,吃完早饭因为要去买菜做午饭(由于今天老婆带女儿上早教去了,我留守做饭,由于我做事比较分步有条理,所以就比较慢,做个简单的午饭也要一个步骤一个步骤的从早晨八点开始...),iptables测试工作放在午后进行...

编写可以生效的使用bpf模块的iptables规则

终于可以写规则了,下意识的写下以下的规则:
iptables -A INPUT -m bpf --bytecode '傻眼了' -j DROP
其实我的要求很简单,就是想将bytecode设置为icmp,可是又不知道bpf的具体语法以及指令,原理是再明白不过了,可是到了实际操作,又懒得查手册,既然不想查手册,也就很难自己写一个翻译程序出来,比如将tcp port 1234之类的翻译成符合bpf语法的bytecode,于是想到从tcpdump里面把代码抠出来,然而那种行为有点巧夺天工了,一向不太在意代码的我,如今被代码折腾了。其实啊,像tcpdump这样成熟的程序,一定有什么参数可以将bpf的code打印出来的,这真的就是我的直觉,大多数玩过GNU代码的都知道,作者在写这段代码的时候,肯定print过这些东西,最终发布时,就作为一种调试信息留下了,既然代码都开源了,为何不让用代码的人更方便呢?事实也确实如是,man一下tcpdump,就会发现其d,dd,ddd选项,正是做这个的,以下就是这些东西,我还是以匹配icmp为例:
@首先看一下十进制的code
root@zhaoya:/usr/src/linux-3.9.6/net/netfilter# tcpdump -i any icmp  -ddd
40 0 0 14
21 0 3 2048
48 0 0 25
21 0 1 1
6 0 0 65535
6 0 0 0
@虽然没有意义,也看一下16进制的code吧,起码知道每行是个4元组{操作码,匹配判读,匹配判断,参数}
root@zhaoya:/usr/src/linux-3.9.6/net/netfilter# tcpdump -i any icmp  -dd
{ 0x28, 0, 0, 0x0000000e },
{ 0x15, 0, 3, 0x00000800 },
{ 0x30, 0, 0, 0x00000019 },
{ 0x15, 0, 1, 0x00000001 },
{ 0x6, 0, 0, 0x0000ffff },
{ 0x6, 0, 0, 0x00000000 },
@最后领略一下它的助记码,类似汇编的指令
root@zhaoya:/usr/src/linux-3.9.6/net/netfilter# tcpdump -i any icmp  -d
(000) ldh      [14]
(001) jeq      #0x800           jt 2    jf 5  #IP协议
(002) ldb      [25]
(003) jeq      #0x1             jt 4    jf 5    #ICMP协议
(004) ret      #65535
(005) ret      #0
既然有了这个,我当然喜出望外了,于是赶紧测试,google了一下bytecode的语法,还算简单:
code=$(tcpdump -i any icmp  -ddd| tr '\n' ',')
即可,于是上述的“傻眼了”被code填充,拍下回车,ping网关,竟然是通的!dmesg也没有任何报错,于是我想得到,是bytecode有问题!然而到哪里去找正确的呢?失望之余,真心有种自己写一个解析器的欲望了,厨房打开抽油烟机稳定了一下情绪,还是google吧,别人做好的东西为何自己再做一遍呢!google发现iptables本来就有一个叫做nfbpf-compiler的工具,在utils里面,于是我就重新编译了它,其实在iptables的bpf模块的help中就明确写出了一个格式,那就是:
--bytecode `nfbpf_compiler RAW <filter>`
过于激动,文档都没有看仔细,真是罪过!于是按照这个格式,将<filter>替换为'icmp',果真成功了,ping不通了,于是我想看看通过nfbpf_compiler生成的code和tcpdump生成的code有何不同,以下是工具生成的:
root@zhaoya:/usr/src/linux-3.9.6/net/netfilter# nfbpf_compile RAW 'icmp'
7,48 0 0 0,84 0 0 240,21 0 3 64,48 0 0 9,21 0 1 1,6 0 0 65535,6 0 0 0
太大不同了啊,到底怎么回事?我注意到了RAW参数,我隐约记得RAW是一个linktype,当时研究tcpdump时好像注意过,因为有人问我EN10MB是什么类型,我当时也不知道,查资料时发现了它其实就是一个链路层类型,和它并列的还是ATM等(这些曾经网络层的协议在TCP/IP的天下都退化成了链路层),那么RAW是什么,其实和socket的RAW差不多,都是指裸IP,也就是说它没有链路层或者说忽略链路层。到此,我终于明白,tcpdump的eth系列网卡翻译过来的code明确就是EN10MB,也就是以太网协议,通过tcpdump -i eth0 -L看一下它都可以使用哪些linktype,令人失望!于是想用lo做实验,可是lo也是和eth0一样,lo怎么会模拟以太网卡啊啊啊啊!在Mac上,lo0明确就是NULL,这才合理啊!具体参见 http://www.tcpdump.org/linktypes.html吧,反正即使看了也得不到什么有用的,我们大多接触到的都是EN10MB!看一下nfbpf_compiler使用EN10MB的结果:
root@zhaoya:/usr/src/linux-3.9.6/net/netfilter# nfbpf_compile EN10MB 'icmp'
6,40 0 0 12,21 0 3 2048,48 0 0 23,21 0 1 1,6 0 0 65535,6 0 0 0
和tcpdump的结果及其类似!
        反过来思考一下,bpf match为何不能使用NE10MB code呢?我看了xt_bpf patch的跟帖,作者的例子就是EN10MB的啊!为何发布版不行了呢?难道是怕linktype太多,如果没有处理就容易panic??看来沙漏细腰部位的IP代码好写啊!不管怎样,事情总算是搞定了,总结一下有几点教训:
1.玩新东西之前一定要看文档,看手册,现在不再一头扎进代码里了,这是进步,但是在有了问题的时候也别指望仅仅看代码就能解决。
2.编译时的参数选项一定要注意,有时候并不是程序的bug,只是因为你在编译的时候就自动放弃了那个你想要的功能。
3.还是那句话,别人已经做好的东西,自己就别再做了(bpf编译程序写了一半...),已经不是10年前那个把排序算法写一遍的青春期晚期了,现在要惜时如金,想练手就练别人没人练过的!

        最后,其实不像本文题目所说的那样,这个历程并不悲惨,这是因为大家普遍都喜欢悲剧罢了,一部悲剧看完以后,你会发现,可能它就是一部带有黑色幽默的喜剧。当然,大半夜被女儿吵闹的声音吵醒看似挺悲惨的,但是有孩子的知道,真的悲惨吗?可能也是一种幸福吧,没孩子的,将来会懂得...

        《胜者的迷思》,今日完结,明日早晨五点《条条大道通罗马》!另,还有一个好玩的,那就是Debian上的ufw!

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/dog250/article/details/9103817

智能推荐

攻防世界_难度8_happy_puzzle_攻防世界困难模式攻略图文-程序员宅基地

文章浏览阅读645次。这个肯定是末尾的IDAT了,因为IDAT必须要满了才会开始一下个IDAT,这个明显就是末尾的IDAT了。,对应下面的create_head()代码。,对应下面的create_tail()代码。不要考虑爆破,我已经试了一下,太多情况了。题目来源:UNCTF。_攻防世界困难模式攻略图文

达梦数据库的导出(备份)、导入_达梦数据库导入导出-程序员宅基地

文章浏览阅读2.9k次,点赞3次,收藏10次。偶尔会用到,记录、分享。1. 数据库导出1.1 切换到dmdba用户su - dmdba1.2 进入达梦数据库安装路径的bin目录,执行导库操作  导出语句:./dexp cwy_init/[email protected]:5236 file=cwy_init.dmp log=cwy_init_exp.log 注释:   cwy_init/init_123..._达梦数据库导入导出

js引入kindeditor富文本编辑器的使用_kindeditor.js-程序员宅基地

文章浏览阅读1.9k次。1. 在官网上下载KindEditor文件,可以删掉不需要要到的jsp,asp,asp.net和php文件夹。接着把文件夹放到项目文件目录下。2. 修改html文件,在页面引入js文件:<script type="text/javascript" src="./kindeditor/kindeditor-all.js"></script><script type="text/javascript" src="./kindeditor/lang/zh-CN.js"_kindeditor.js

STM32学习过程记录11——基于STM32G431CBU6硬件SPI+DMA的高效WS2812B控制方法-程序员宅基地

文章浏览阅读2.3k次,点赞6次,收藏14次。SPI的详情简介不必赘述。假设我们通过SPI发送0xAA,我们的数据线就会变为10101010,通过修改不同的内容,即可修改SPI中0和1的持续时间。比如0xF0即为前半周期为高电平,后半周期为低电平的状态。在SPI的通信模式中,CPHA配置会影响该实验,下图展示了不同采样位置的SPI时序图[1]。CPOL = 0,CPHA = 1:CLK空闲状态 = 低电平,数据在下降沿采样,并在上升沿移出CPOL = 0,CPHA = 0:CLK空闲状态 = 低电平,数据在上升沿采样,并在下降沿移出。_stm32g431cbu6

计算机网络-数据链路层_接收方收到链路层数据后,使用crc检验后,余数为0,说明链路层的传输时可靠传输-程序员宅基地

文章浏览阅读1.2k次,点赞2次,收藏8次。数据链路层习题自测问题1.数据链路(即逻辑链路)与链路(即物理链路)有何区别?“电路接通了”与”数据链路接通了”的区别何在?2.数据链路层中的链路控制包括哪些功能?试讨论数据链路层做成可靠的链路层有哪些优点和缺点。3.网络适配器的作用是什么?网络适配器工作在哪一层?4.数据链路层的三个基本问题(帧定界、透明传输和差错检测)为什么都必须加以解决?5.如果在数据链路层不进行帧定界,会发生什么问题?6.PPP协议的主要特点是什么?为什么PPP不使用帧的编号?PPP适用于什么情况?为什么PPP协议不_接收方收到链路层数据后,使用crc检验后,余数为0,说明链路层的传输时可靠传输

软件测试工程师移民加拿大_无证移民,未受过软件工程师的教育(第1部分)-程序员宅基地

文章浏览阅读587次。软件测试工程师移民加拿大 无证移民,未受过软件工程师的教育(第1部分) (Undocumented Immigrant With No Education to Software Engineer(Part 1))Before I start, I want you to please bear with me on the way I write, I have very little gen...

随便推点

Thinkpad X250 secure boot failed 启动失败问题解决_安装完系统提示secureboot failure-程序员宅基地

文章浏览阅读304次。Thinkpad X250笔记本电脑,装的是FreeBSD,进入BIOS修改虚拟化配置(其后可能是误设置了安全开机),保存退出后系统无法启动,显示:secure boot failed ,把自己惊出一身冷汗,因为这台笔记本刚好还没开始做备份.....根据错误提示,到bios里面去找相关配置,在Security里面找到了Secure Boot选项,发现果然被设置为Enabled,将其修改为Disabled ,再开机,终于正常启动了。_安装完系统提示secureboot failure

C++如何做字符串分割(5种方法)_c++ 字符串分割-程序员宅基地

文章浏览阅读10w+次,点赞93次,收藏352次。1、用strtok函数进行字符串分割原型: char *strtok(char *str, const char *delim);功能:分解字符串为一组字符串。参数说明:str为要分解的字符串,delim为分隔符字符串。返回值:从str开头开始的一个个被分割的串。当没有被分割的串时则返回NULL。其它:strtok函数线程不安全,可以使用strtok_r替代。示例://借助strtok实现split#include <string.h>#include <stdio.h&_c++ 字符串分割

2013第四届蓝桥杯 C/C++本科A组 真题答案解析_2013年第四届c a组蓝桥杯省赛真题解答-程序员宅基地

文章浏览阅读2.3k次。1 .高斯日记 大数学家高斯有个好习惯:无论如何都要记日记。他的日记有个与众不同的地方,他从不注明年月日,而是用一个整数代替,比如:4210后来人们知道,那个整数就是日期,它表示那一天是高斯出生后的第几天。这或许也是个好习惯,它时时刻刻提醒着主人:日子又过去一天,还有多少时光可以用于浪费呢?高斯出生于:1777年4月30日。在高斯发现的一个重要定理的日记_2013年第四届c a组蓝桥杯省赛真题解答

基于供需算法优化的核极限学习机(KELM)分类算法-程序员宅基地

文章浏览阅读851次,点赞17次,收藏22次。摘要:本文利用供需算法对核极限学习机(KELM)进行优化,并用于分类。

metasploitable2渗透测试_metasploitable2怎么进入-程序员宅基地

文章浏览阅读1.1k次。一、系统弱密码登录1、在kali上执行命令行telnet 192.168.26.1292、Login和password都输入msfadmin3、登录成功,进入系统4、测试如下:二、MySQL弱密码登录:1、在kali上执行mysql –h 192.168.26.129 –u root2、登录成功,进入MySQL系统3、测试效果:三、PostgreSQL弱密码登录1、在Kali上执行psql -h 192.168.26.129 –U post..._metasploitable2怎么进入

Python学习之路:从入门到精通的指南_python人工智能开发从入门到精通pdf-程序员宅基地

文章浏览阅读257次。本文将为初学者提供Python学习的详细指南,从Python的历史、基础语法和数据类型到面向对象编程、模块和库的使用。通过本文,您将能够掌握Python编程的核心概念,为今后的编程学习和实践打下坚实基础。_python人工智能开发从入门到精通pdf