玩转高性能超猛防火墙nf-HiPAC
中华国学,用英文讲的,稀里糊涂听了个大概,不得不佩服西方人的缜密的逻辑思维,竟然把玄之又玄的道家思想说的跟牛顿定律一般,佩服。归家,又收到了邮件,还是关于nf-hipac的,不知不觉就想彻底整理一篇文章说个明白,可是哪有个够啊哪有个够。
匆匆吃完晚饭,碗也没刷,餐桌狼藉,家人都在看电视,玩手机,小小依然捧着iPad...我的摊子如下:
如果说理论分析不足以镇住人,或者说一上来就讲理论可能把人吓跑,还是先来点感官上的体验吧。
0.感官感受
执行下面的命令:
for((i=1;i<100;i++));do for((j=1;j<100;j++)); do iptables -A INPUT -s $i.10.193.$j -j DROP;done; done
for((i=1;i<100;i++));do for((j=1;j<100;j++)); do iptables -A INPUT -s $i.11.192.$j -j DROP;done; done
系统中添加了将近20000条的iptables规则,iperf的测试结果如下:
下面我来试一下nf-hipac,由于nf-hipac的命令语法和iptables基本兼容,因此按照下面的命令执行:
for((i=1;i<100;i++));do for((j=1;j<100;j++)); do nf-hipac -A INPUT -s $i.10.193.$j -j DROP;done; done
for((i=1;i<100;i++));do for((j=1;j<100;j++)); do nf-hipac -A INPUT -s $i.11.192.$j -j DROP;done; done
如此一来,系统中添加了将近2000条nf-hipac规则,iperf的测试结果如下:
二者的对比相当明显,最后我们来看一下既没有iptables又没有nf-hipac规则的时候,iperf的结果:
显而易见,nf-hipac加载20000个条目的结果和裸奔的结果是几乎一致的,这是多么令人兴奋的一件事啊!
1.如何使用nf-hipac
1.0.确认内核版本
很 不幸,nf-hipac并非以一个可加载的内核模块存在,它是内核的一个patch。需要重新配置内核和重新编译内核才能使用它。除此之外,它对内核版本 特别挑剔,官网可下载的最新版本早在2005年就终结了,因此它只是在2.6.13内核版本上可用(说是14,15,16,18都可以,我没有试)。因此 我不得不退回到Debian4上去,然后在kernel.org上下载一个2.6.13版本的内核并着手nf-hipac的编译工作。
幸运的是,我已经决定将其做成一个可以加载的内核模块了,并且支持2.6.32以及以上的内核。今晚开始了移植工作,基本分为几块的工作量:
a.适配match/target内核API
b.适配netlink内核API
在 还没有完成模块化之前,只能在2.6.13上打patch了。能我相当信心的是,nf-hipac的内核补丁事实上是在net/ipv4 /netfilter目录下的一个子目录nf-hipac,所有的文件全部在里面,并未对任何内核关键的数据结构打补丁,因此nf-hipac完全可以作 为一个模块进行编译。
1.1.下载它
在网站http://www.hipac.org/上下载最新的nf-hipac-0.9.1.tar.bz2,这个版本是个终结版,此后再也没有更新,不知道作者哪去了。
1.2.编译它
解压缩nf-hipac-0.9.1.tar.bz2,进入user目录,执行make install PREFIX=/usr/local IPT_LIB_DIR=/usr/local/lib/iptables,很容易就编译成功了。
1.3.为内核打patch
进入新下载的2.6.13内核的根目录:
cd /home/kernel/linux-2.6.13
为内核打上patch:
patch -p1 -F3 < /home/kernel/nf-hipac-0.9.1/nf-hipac-0.9.1.patch
配置.config文件,我使用了Debian GNU/Linux 3.1的config文件:
cp /boot/config-2.6.8-4-686-smp /home/kernel/linux-2.6.13/.config
然后make menuconfig:
加入一个版本后缀
General setup ---> (hipac) Local version - append to kernel release
选中nf-HiPAC
Networking ---> Networking options --->
[*] Network packet filtering (replaces ipchains) --->
IP: Netfilter Configuration --->
<M> nf-HiPAC support (High Performance Packet Classification)
[*] Single path optimization
保存.config
1.4.编译内核
直接编译:
cd /home/kernel/linux-2.6.13
make -j4
make modules_install
mkinitrd -o /boot/initrd.img-2.6.13hipac /lib/modules/2.6.13hipac
depmod -a 2.6.13hipac
修改/boot/grub/menu.lst,使用新的vmlinuz-2.6.13hipac启动系统
系统启动完成
1.5.执行命令
除 了iptables换成nf-hipac之外没有任何别的区别,但是要注意,所有的iptables的match都被nf-hipac支持,但是并不意味 着iptables的match可以内置到nf-hipac的dimtree中实现高效匹配,只有nf-hipac内置的match才可以实现高效 dimtree匹配,这些match的共同特点就是它们的值域可以“区间化”。下面是一个nf-hipac支持的列表:
Options:
--proto -p [!] proto protocol: by number or name, eg. `tcp'
--source -s [!] address[/mask] or
address[:address]
source(s) specification
--destination -d [!] address[/mask] or
address[:address]
destination(s) specification
--in-interface -i [!] devname
network interface name
--jump -j target
target for rule
--numeric -n numeric output of addresses and ports
--out-interface -o [!] devname
network interface name
--verbose -v verbose mode
--line-numbers print line numbers when listing
[!] --fragment -f match second or further fragments only
--version -V print package version.
----------
TCP options:
--syn match when only SYN flag set
--not-syn match when not only SYN flag set
--source-port [!] port[:port]
--sport ...
match source port(s)
--destination-port [!] port[:port]
--dport ...
match destination port(s)
----------
UDP options:
--source-port [!] port[:port]
--sport ...
match source port(s)
--destination-port [!] port[:port]
--dport ...
match destination port(s)
----------
ICMP options:
--icmp-type typename match icmp type
(or numeric type or type/code)
see also: nf-hipac -h icmp
----------
STATE options:
--state [!] [INVALID|ESTABLISHED|NEW|RELATED|UNTRACKED|ESTABLISHED,RELATED]
State to match
----------
TTL options:
--ttl value[:value] match time to live value(s)
----------
如 果nf-hipac命令中出现了iptables的match,比如从/lib/iptables目录加载的libipt_set.so中的ipset match以及任何iptables的match模块,最终都要排在dimtree的叶子节点进行独立的iptables匹配过程。代码里面已经很清晰的 表明了这一点。nf-hipac的HOOK函数是hipac_match,该函数首先进行例行的高效的HiPAC算法匹配,然后找到一个叶子节点,该叶子 节点可能体现出两种行为:
a.它就是纯粹的nf-hipac的rule,此时叶子指示一个target:
if (likely(IS_RULE(t))) {return ((struct dt_rule *) t)->spec.action;
}
b.它在nf-hipac规则中夹杂了iptables的match(这些match从/lib/iptables/目录下加载),此时需要进行iptables的例行匹配,这种匹配不是按照HiPAC算法高效执行的,而是使用iptables的算法慢速遍历的:
/* initialization required to prevent compiler warning */
action = 0;for (i = 0; i < ((struct dt_elem *) t)->ntm_rules.len; i++) {rule = ((struct dt_elem *) t)->ntm_rules.p[i];if (HAS_EXEC_MATCH(rule)) {for (j = 0; j < rule->exec_match->len; j += 2) {// 此处的match_fn就是常规的在一条iptables规则中遍历匹配所有的// match,iptables中拥有很多不可区间化的match这是可以理解的action = match_fn(packet,rule->exec_match->p[j],rule->exec_match->p[j + 1]);if (action != MATCH_YES) {break;}}if (action == MATCH_NO) {continue;}if (action == MATCH_HOTDROP) {return TARGET_DROP;}
...}
}
1.6.procfs中的统计信息
nf-hipac模块加载了之后,会在procfs的net目录***册自己,其中的/proc/net/nf-hipac下的info文件中有下面一行:
nf-hipac is invoked before iptables
如果你想让iptables首先进行匹配,那么请执行:
echo iptables-first> /proc/net/nf-hipac/info
其/proc/net/nf-hipac/statistics目录下有关于hipac规则树的一些统计信息,目前只有3个链被支持。
2.nf-hipac是怎么做到的
nf-hipac相比较iptables,性能那叫一个帅!相比ipset则不相上下,然而nf-hipac在综合效果上则是介于iptables和ipset之间的一个being。它是怎么做到的。
iptables的规则在内存中是线性排列的,内核的HOOK通过遍历这些规则链进行逐一匹配,这个逐一匹配的顺序内含了优先级的概念,首先加入的 rule首先被匹配到。但是除了这个顺序的排列之外,规则之间再也没有了别的关联,因此很难将它们作为一个整体来进行优化。
ipset将ip地址,端口等统一进行管理,但是同一个集合中的元素只能采取统一的动作,即target,虽然在ip地址的匹配中极端高效,但是使用起来 很不灵活,很难做到比如同在set中的ip1和ip2执行不同的-j target动作。ipset是将单一的match统一管理进行优化的,和多条iptables规则没有必然的关系,即它没有将多条iptables规则 关联起来。
除了傻傻的线性排列,除了单一match的hash/tree统一管理,iptables和match,target之间还能有别的关系吗?即它们之间还 能有别的排列方式吗?当然有,这就是nf-hipac的方式。nf-hipac采用了另一种排列方式,即将固定的match进行排序,也就是说将每一条规 则拆开来,这就就可以化不确定为确定。确定的是match的总的种类,不确定的是规则的数量,最终确定的match的数量决定了树的高度,而这个不确定的 规则数量影响的仅仅是树的广度,仅此而已。
下面的一幅图非常复杂,是我听完嘉定中华国学后在我的餐桌上画的,已经很晚了,无所事事,睡不着,也没喝酒,所以就兴奋了。图示如下:
拆 散了一条条的rule之后,剩下的就是将match和target组成一棵树了,事实上rule并没有被拆散,所谓的rule就是若干的match和一个 target,在右边这棵树中体现的就是每一个树节点的match层次,最下层的优先级最高,这就体现了rule的配置顺序,rule的配置顺序体现的就 是优先级。
nf-hipac不更新了,没人维护了,难道是作者因此找到好的工作了,难道是作者结婚了,难道是作者生孩子了...这种判断也太中国化了,反正就是不更 新了...单单谈效率,ipset完全可以让nf-hipac下课,但是谈点别的之后,nf-hipac的优势就显现出来了。
3.破除超猛nf-hipac的神话
有破有立,方可不败。
如果我们结合上面的图仔细分析为何添加了20000条左右的nf-hipac,性能依然不受任何影响,就会发现,nf-hipac的匹配过程最多经过n层 的树深度,而n是match的数量,在这20000条规则中,match的数量只有1个!!注意了,这就是关键,1个!如果使用iptables,那么匹 配的过程最多经过m个rule。也就是说,nf-hipac将m个rule拆散了之后,将其中所有的match压缩成了n层的树,每一层拥有m个层的区间 交集匹配,这些交集仅仅决定其下层树节点的rule交集。照此说来,很多的数据包从第一个match集合(所有rule的第一个match组成的集合)树 根开始匹配,一旦rule的match交集变成空,就可以直接下决断“没有匹配的rule”了,所以即便是少数种类的match集合节点,一个数据包也不 一定能从树根匹配到最后一个match集合。这就是nf-hipac超猛的根本原因。
对于nf-hipac树的查找,需要注意的是,如果不是叶子节点,执行流只会碰触到最先配置的那条rule,即最下面的那条,其余的rule被隐藏在该最 下面rule的上面,它们的作用仅仅是告诉执行流,该区间的下面的分支树节点是所有这些rule的交集,仅此而已。
从iptables到nf-hipac的变化是:从遍历m*n次(m为rule的数量,n为每一个rule的match的数量)简化为了遍历n次(n为所 有rule中最多match的那一条rule的match的数量)。之所以如此就是因为nf-hipac将所有的rule作为一个整体来优化。那么代价是 什么?代价就是插入rule,删除rule的开销。插入一条rule,首先需要将其所有的match拆分开来,然后找出每一个树节点的位置,即rule的 插入位置,然后准备将这些match分别插入到那些位置中,是否插入取决于那个位置有没有对应rule的match交集,如果没有,则不予插入,删除的过 程类似,也需要进行比较复杂的计算。
那么有没有什么办法让nf-hipac变得低效呢?很显然,当你了解了nf-hipac的dimtree的构造之后,你就会明白,n的数量越大,效率越 低,n是什么?n是match的种类的数量。整个tree的深度就是n,如果自己构造20000种左右的match,那么试试看,仅仅配置一条nf- hipac规则,整个tree的构造将变成深度为2000的倒立的链表...我之所以仅仅设置一条nf-hipac规则是因为如果设置了多条,反而可能由 于中途rule的match交集为空而提前退出遍历树。但是幸运的是,对于一个数据包那么多种的match是不必要的。
转载于:https://blog.51cto.com/dog250/1579804
相关文章:

ios 沙盒 plist 数据的读取和存储
plist 只能存储基本的数据类型 和 array 字典 [objc] view plaincopy - (void)saveArray { // 1.获得沙盒根路径 NSString *home NSHomeDirectory(); // 2.document路径 NSString *docPath [home stringByAppendingPathComponent:"Document…

FFmpeg实现获取USB摄像头视频流测试代码
通过USB摄像头(注:windows7/10下使用内置摄像头,linux下接普通的usb摄像头(Logitech))获取视频流用到的模块包括avformat和avdevice。头文件仅include avdevice.h即可,因为avdevice.h中会include avformat.h。libavdevice库是libavformat的一…

重磅!明略发布数据中台战略和三大解决方案
11月15日,明略科技在上海举办以“FASTER 聚变增长新动力”为主题的2019数据智能峰会,宣布“打造智能时代的企业中台”新战略,同时推出了两大新产品“新一代数据中台”和“营销智能平台”,以及三大行业解决方案,分别是“…

Android程序完全退出的三种方法
1. Dalvik VM的本地方法 android.os.Process.killProcess(android.os.Process.myPid()) //获取PID,目前获取自己的也只有该API,否则从/proc中自己的枚举其他进程吧,不过要说明的是,结束其他进程不一定有权限,不然就…

FFmpeg通过摄像头实现对视频流进行解码并显示测试代码(旧接口)
这里通过USB摄像头(注:windows7/10下使用内置摄像头,linux下接普通的usb摄像头(Logitech))获取视频流,然后解码,最后再用opencv显示。用到的模块包括avformat、avcodec和avdevice。libavdevice库是libavformat的一个补充库(comple…

IOS数据存储之文件沙盒存储
前言: 之前学习了数据存储的NSUserDefaults,归档和解档,对于项目开发中如果要存储一些文件,比如图片,音频,视频等文件的时候就需要用到文件存储了。文件沙盒存储主要存储非机密数据,大的数据。 …
剖析Focal Loss损失函数: 消除类别不平衡+挖掘难分样本 | CSDN博文精选
作者 | 图像所浩南哥来源 | CSDN博客论文名称:《 Focal Loss for Dense Object Detection 》论文下载:https://arxiv.org/pdf/1708.02002.pdf论文代码:https://github.com/facebookresearch/Detectron/tree/master/configs/12_2017_baselines…

windows下mysql开启慢查询
mysql在windows系统中的配置文件一般是my.ini,我的路径是c:\mysql\my.ini,你根据自己安装mysql路径去查找[mysqld]#The TCP/IP Port the MySQL Server will listen onport3306#开启慢查询log-slow-queries E:\Program Files\MySQL\MySQL Server 5.5\mysql_slow_query.loglong_…

FFmpeg通过摄像头实现对视频流进行解码并显示测试代码(新接口)
在https://blog.csdn.net/fengbingchun/article/details/93975325 中给出了通过旧接口即FFmpeg中已废弃的接口实现通过摄像头获取视频流然后解码并显示的测试代码,这里通过使用FFmpeg中的新接口再次实现通过的功能,主要涉及到的接口函数包括:…

iOS经典讲解之获取沙盒文件路径写入和读取简单对象
#import "RootViewController.h" interface RootViewController () end 实现文件: implementation RootViewController - (void)viewDidLoad { [super viewDidLoad]; [self path]; [self writeFile]; [self readingFi…
Google最新论文:Youtube视频推荐如何做多目标排序
作者 | 深度传送门来源 | 深度传送门(ID:deep_deliver)导读:本文是“深度推荐系统”专栏的第十五篇文章,这个系列将介绍在深度学习的强力驱动下,给推荐系统工业界所带来的最前沿的变化。本文主要介绍下Google在RecSys …

Jmeter 笔记
Apache JMeter是Apache组织开发的基于Java的压力测试工具。用于对软件做压力测试,它最初被设计用于Web应用测试但后来扩展到其他测试领域。 它可以用于测试静态和动态资源例如静态文件、Java 小服务程序、CGI 脚本、Java 对象、数据库, FTP 服务器&#…
王贻芳院士:为什么中国要探究中微子实验?
演讲嘉宾 | 王贻芳(中国科学院院士、中科院高能物理研究所所长)整理 | 德状出品 | AI科技大本营(ID:rgznai100)日前,在2019腾讯科学WE大会期间,中国科学院院士、高能物理研究所所长王贻芳分享了中微子与光电…
一个苹果证书供多台电脑开发使用——导出p12文件
摘要 在苹果开发者网站申请的证书,是授权mac设备的开发或者发布的证书,这意味着一个设备对应一个证书,但是99美元账号只允许生成3个发布证书,两个开发证书,这满足不了多mac设备的使用,使用p12文件可以解决这…

FFmpeg中AVDictionary介绍
FFmpeg中的AVDictionary是一个结构体,简单的key/value存储,经常使用AVDictionary设置或读取内部参数,声明如下,具体实现在libavutil模块中的dict.c/h,提供此结构体是为了与libav兼容,但它实现效率低下&…

RocketMQ3.2.2生产者发送消息自动创建Topic队列数无法超过4个
问题现象RocketMQ3.2.2版本,测试时尝试发送消息时自动创建Topic,设置了队列数量为8:producer.setDefaultTopicQueueNums(8);同时设置broker服务器的配置文件broker.properties:defaultTopicQueueNums16但实际创建后从控制台及后台…

iOS各种宏定义
#ifndef MacroDefinition_h #define MacroDefinition_h //************************ 获取设备屏幕尺寸********************************************** //宽度 #define SCREEN_WIDTH [UIScreen mainScreen].bounds.size.width //高度 #define SCREENH_HEIGHT [UIScree…

开源库libuuid简介及使用
libuuid是一个开源的用于生成UUID(Universally Unique Identifier,通用唯一标识符)的库,它的源码可从https://sourceforge.net/projects/libuuid/ 下载,最新版本为1.0.3,更新于2013年4月27日,此库仅支持在类Linux下编译…

深度学习会议论文不好找?这个ConfTube网站全都有
BDTC大会官网:https://t.csdnimg.cn/q4TY作者 | 刘畅 出品 | AI科技大本营(ID:rgznai1000)最近跟身边的硕士生、博士生聊天,发现有一个共同话题,大家都想要知道哪款产品能防止掉头发?养发育发已经成了茶余饭…

Java用for循环Map
为什么80%的码农都做不了架构师?>>> 根据JDK5的新特性,用For循环Map,例如循环Map的Key for(String dataKey : paraMap.keySet()) { System.out.println(dataKey ); } 注意的是,paraMap 是怎么样定义的,如果是简单的Map paraMap new …

iOS 应用发布到AppStore流程
iOS开发者,把开发出来的App上传到App Store是必须的。下面就来详细介绍下具体流程。 方法/步骤 1打开苹果开发者中心 打开后点击:Member Center 2如果你的电脑没有保存密码,则会提示你输入开发者帐号和密码,因为我的电脑已经保存了…

FFmpeg中编码类型为rawvideo无须解码直接显示测试代码
在 https://blog.csdn.net/fengbingchun/article/details/93975325 中介绍过通过FFmpeg可以直接获取usb视频流并解码显示的测试代码,当时通过usb获取到的视频流编码类型为AV_CODEC_ID_RAWVIDEO,像素格式为AV_PIX_FMT_YUYV422,其实编码类型为r…

一场高质量的技术盛会怎样炼成?「2019中国大数据技术大会」蓄势待发,还不快上车?...
2019年12月,一场轰动国内产业界、学术界、科研界及投资领域的顶级科技盛会即将拉开帷幕,它涵盖大数据、人工智能、云计算、AIoT、金融科技、智能制造等十几个前沿领域的热门话题。在过去十二年里,这场盛会从最初仅 60 余人参加的技术沙龙到如…

融合应用11.1.8安装,一步一步的引导
融合应用11.1.8安装,一步一步的引导 融合应用11.1.8 安装并不是简单的与电子商务套件11 i / R12安装。 所以我们需要安装划分为许多步骤。 请注意,11.1.8 11.1.7总统发布供应是几乎相同的。 在同一时间的步骤和一些组件11.1.6和11.1.5相比有所不同。 这里我们有实际使用同一个…

FFmpeg中一个线程获取视频流一个线程执行scale测试代码
在https://blog.csdn.net/fengbingchun/article/details/94712986 中介绍过如果usb视频流编码类型为rawvideo则无需进行解码,可直接通过av_read_frame获取视频流然后再通过sws_scale进行像素格式转换,当在高分辨率情况下,有时达不到实时显示&…

医疗影像处理:去除医疗影像中背景的影响2D/3D【numpy-code】| CSDN博文精选
BDTC大会官网:https://t.csdnimg.cn/q4TY作者 | chestnut--来源 | CSDN博客在医疗影像中特别是CT影像,包含大量的背景,在进行器官分割时,首先去除背景对分割的效果有很好的提升。本博客使用Python处理医疗影像并去除背景的影像。使…

iOS APP提交上架最新流程
iOS APP提交上架最新流程 反复提交的过程中对上架流程熟悉了好多,写篇帖子送给同为菜鸟的你,如果里面有很菜的东西,大牛请自动忽略,毕竟这也是还为菜鸟的我的备忘录呢! 首先得描述一下各个证书的定位,作…

Spring mvc Data Redis—Pub/Sub(附Web项目源码)
一、发布和订阅机制 当一个客户端通过 PUBLISH 命令向订阅者发送信息的时候,我们称这个客户端为发布者(publisher)。 而当一个客户端使用 SUBSCRIBE 或者 PSUBSCRIBE 命令接收信息的时候,我们称这个客户端为订阅者(subscriber)。 为了解耦发布者(publish…

iOS分析崩溃日志
前言 iOS分析定位崩溃问题有很多种方式,但是发布到AppStore的应用如果崩溃了,我们该怎么办呢?通常我们都会在系统中接入统计系统,在系统崩溃的时候记录下崩溃日志,下次启动时将日志发送到服务端,比较好的第…

海思3559A上编译FFmpeg源码操作步骤
1. 从https://github.com/FFmpeg/FFmpeg/releases 下载你需要的版本; 2. 因为ffmpeg编译选项较多,为了更方便的了解有哪些选项,可将编译选项写入到一个文本文件configure_help.txt中,执行: ./configure --help > …