关注了一下Netfilter的最新进展,新东西还真不少哇!但是最让人心动的有两个。
一.新的bpf模块
基于Linux kernel 3.9版本的patch是xt_bpf的支持,对应的iptables模块是libxt_bpf,这个在iptables-1.4.19版本中已经支持,顾名思义,bpf其实就是伯克利包过滤的缩写,对于它的描述,参见《
BPF(BSD Packet Filter)--应用和理念扩展》。从名称上看,BPF理应就是iptables包过滤的首选技术,但是不知道什么原因,xt_tables一直维护着自己的数据结构保存rule的match和target,现在有了BPF的支持,我想内核协议栈在处理iptables规则时的效率会高很多,以往的一系列的多个match,现在封装进一个match,该match可以通过bytecode参数来指示,它是已经编译好的字节码,内核直接去执行,速度非常快。以往的match匹配基本就是遍历,现在基于bpf的不再依赖遍历了,而是去“执行”那段bytecode!
tcpdump工具一直以来都是基于BPF的,虽然它的match在语法上和iptables的极其类似,其匹配效率却比iptales高很多,类似
-i eth2 tcp port 1234 and host 1.2.3.4这一串匹配在iptables中需要建立4个entry,然而使用BPF的话,就可以编译成一段以下顺序执行的代码:
1.加载dev字段
2.判断dev字段,如果不是eth2则跳到x
3.加载协议字段
4.判断协议字段,如果不是tcp则跳到x
...
x.返回这段代码类似汇编代码,被内核解释执行。不过,我在kernel 2.6.32上开始没有编译成功,因为这个版本太老了,很多接口和新的内核都不兼容,改了好久才勉强能运行,但是不能插入复杂的bytecode,否则就panic!
不管怎样,采用这个BPF的架构,内核空间的代码执行效率会提高很多,并且代码量也会减少很多,像ipt_do_table这个巨无霸函数也能瘦身了。
二.最新的nftables项目
说到iptables内核代码的瘦身,Netfilter网站上开辟了另外一条路,那就是
nftables项目,它旨在完全替换掉既有的iptables/ebtables/arptables以及对应的v6版本。
nftables最主要的革新在于两点,其一就是命令语法的完全改变,第二就是内核代码的优化。它采取了类似BPF的过滤方式,其matches的匹配过程就是一个状态机转换的过程,最终的终止节点就是target。在代码层面,它彻底改变了iptables对match存储的混乱场面,以下是匹配的核心代码:
//更加合理的数据结构,比iptables的平坦化的数据结构布局好多了
struct nft_expr {
const struct nft_expr_ops *ops;
unsigned char data[];
};
struct nft_rule {
struct list_head list;
struct list_head dirty_list;
struct rcu_head rcu_head;
u64 handle:46,
genmask:2,
dlen:16;
unsigned char data[]
__attribute__((aligned(__alignof__(struct nft_expr))));
};
//net/netfilter/nf_tables_core.c
unsigned int
nft_do_chain_pktinfo(struct nft_pktinfo *pkt, const struct nf_hook_ops *ops)
{
const struct nft_chain *chain = ops->priv;
const struct nft_rule *rule;
const struct nft_expr *expr, *last;
struct nft_data data[NFT_REG_MAX + 1];
unsigned int stackptr = 0;
struct nft_jumpstack jumpstack[NFT_JUMP_STACK_SIZE];
int rulenum = 0;
/*
* Cache cursor to avoid problems in case that the cursor is updated
* while traversing the ruleset.
*/
unsigned int gencursor = chain->net->nft.gencursor;
do_chain:
rule = list_entry(&chain->rules, struct nft_rule, list);
next_rule:
data[NFT_REG_VERDICT].verdict = NFT_CONTINUE;
list_for_each_entry_continue_rcu(rule, &chain->rules, list) {
/* This rule is not active, skip. */
if (unlikely(rule->genmask & (1 << gencursor)))
continue;
rulenum++;
nft_rule_for_each_expr(expr, last, rule) {
if (expr->ops == &nft_cmp_fast_ops)
nft_cmp_fast_eval(expr, data);
else if (expr->ops != &nft_payload_fast_ops ||
!nft_payload_fast_eval(expr, data, pkt))
expr->ops->eval(expr, data, pkt);
if (data[NFT_REG_VERDICT].verdict != NFT_CONTINUE)
break;
}
switch (data[NFT_REG_VERDICT].verdict) {
case NFT_BREAK:
data[NFT_REG_VERDICT].verdict = NFT_CONTINUE;
/* fall through */
case NFT_CONTINUE:
continue;
}
break;
}
switch (data[NFT_REG_VERDICT].verdict) {
//结果判定
case NF_ACCEPT:
case NF_DROP:
case NF_QUEUE:
nft_chain_stats(chain, pkt, jumpstack, stackptr);
if (unlikely(pkt->skb->nf_trace))
nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RULE);
return data[NFT_REG_VERDICT].verdict;
case NFT_JUMP:
//stack结构更好地组织了rule
if (unlikely(pkt->skb->nf_trace))
nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RULE);
BUG_ON(stackptr >= NFT_JUMP_STACK_SIZE);
jumpstack[stackptr].chain = chain;
jumpstack[stackptr].rule = rule;
jumpstack[stackptr].rulenum = rulenum;
stackptr++;
/* fall through */
case NFT_GOTO:
chain = data[NFT_REG_VERDICT].chain;
goto do_chain;
case NFT_RETURN:
if (unlikely(pkt->skb->nf_trace))
nft_trace_packet(pkt, chain, rulenum, NFT_TRACE_RETURN);
/* fall through */
case NFT_CONTINUE:
break;
default:
WARN_ON(1);
}
if (stackptr > 0) {
if (unlikely(pkt->skb->nf_trace))
nft_trace_packet(pkt, chain, ++rulenum, NFT_TRACE_RETURN);
stackptr--;
chain = jumpstack[stackptr].chain;
rule = jumpstack[stackptr].rule;
rulenum = jumpstack[stackptr].rulenum;
goto next_rule;
}
nft_chain_stats(chain, pkt, jumpstack, stackptr);
if (unlikely(pkt->skb->nf_trace))
nft_trace_packet(pkt, chain, ++rulenum, NFT_TRACE_POLICY);
return nft_base_chain(chain)->policy;
}
新的nftables瘦身的原因在于大量采用了回调函数,使判定逻辑独立出来,核心的do_tables变成了一个单纯的状态机!这个抽取动作带来了的效果就是rule更加灵活了,类似BPF的思想,数据包可以根据每一步的结果在不同的rule或者不同的match之间任意跳转了。相比iptables在匹配过程中的大量判断,结果硬编码,nftables确实有一个质的飞跃,期待nftables早日出炉!
分享到:
相关推荐
netfilter/iptables(简称为iptables)组成Linux平台下的包过滤防火墙,与大多数的Linux软件一样,这个包过滤防火墙是免费的,它可以代替昂贵的商业防火墙解决方案,完成封包过滤、封包重定向和网络地址转换(NAT)...
Linux下基于Netfilter/iptables防火墙的构建.pdf
对Linux下netfilter/iptables中log日志格式探讨.pdf
Linux下基于Netfilter/Iptables防火墙的研究与应用.pdf
Netfilter/iptables与Snort联动的实现,李国栋,,各种安全技术之间的联动能够弥补各自的缺陷,实现优势互补,从而建立一个全方位的防御体系。联动是今后安全技术发展的一个方向。本�
Netfilter/iptables是Linux 2.6内核中的通用性功能框架,能够对数据包进行处理。分析了基于Linux内核的Netfilter/ iptables框架以及iptables表、链的关系与作用;应用Netfilter/iptables中的包过滤特性建立了内外网...
Netfilter-IPTables框架简介,Netfilter-IPTables框架简介,Netfilter-IPTables框架简介
在本篇文章里小编给大家整理的是关于Linux netfilter/iptables知识点详解,有兴趣的朋友们可以参考下。
传统 ipchains 的任何功能(来源与目的封包过滤、导向、伪装)。 提供 Source NAT 与 Destination NAT 的功能。 可以针对特定使用者、群组、PID 等限制网络连结的过滤存取。 可以设定封包在 Routing Table 进出前时先...
Netfilter / Iptables的CRYPT扩展允许您使用流和分组密码创建加密的通信。 它还对数据包进行身份验证。
具有图形和命令行界面的linux netfilter / iptables防火墙日志摘要程序,可帮助sysadmin日常工作。 可以更仔细地研究兴趣点以获得更多信息。 您还可以在命令行模式下运行它,
文章在 Linux 相关源码的基础上对 Linux 内核防火墙框架 Netfilter/Iptables 进行了研究, 并利用HOOK 函数, 实现了对 Land 和 Winnuke 攻击的检测。
首先介绍 Linux环境下 SYN Flood攻击 的检测方法和防范手段,重点分析基于 Netfilter/iptables的动态包过滤机制抗御 SYN Flood攻击的 原理,然后提出一种iptables与入侵检测系统( IDS)的集成解决方案,采用文件作为数据...
Linux防火墙内核中Netfilter和Iptables的分析.pdf
详细介绍了linux下的防火墙设计和原理,基于应用层的iptables和内核的Netfilter。重点讲了SNAT\DNAT\状态防火墙等,还有具体实例讲解
洞悉linux下的Netfilter&iptables; 内核中的ip_tables小觑、内核中的rule,match和target、包过滤子系统iptable_filter、如何理解连接跟踪机制、状态防火墙、DNAT、SNAT、iptables命令行工具源码解析
Netfilter/Iptables防火墙是Linux平台下的包过滤防火墙,Iptables防火墙不仅提供了强大的数据包过滤能力,而且还提供转发,NAT映射等功能,是个人及企业级Linux用户构建网络安全平台的首选工具。但是,由于种种原因...