连接跟踪的一些设想

chenjiawei 2011-01-10

本文档的Copyleft归yfydz所有,使用GPL发布,可以自由拷贝,转载,转载时请保持文档的完整性,严禁用于任何商业用途。

msn:yfydz_no1@hotmail.com

来源:http://yfydz.cublog.cn

现在netfilter中数据包进入防火墙后如果是新连接的包,就分配内存建立连接,然后才是是后续mangle、nat、 filter等,如果该包是禁止通过的,则丢包,然后释放连接。这样也就是说对于丢弃的包,netfilter实际都为它们建立过连接,因此大量新连接包来的时候,实际进行了大量的内存分配又释放的多余操作,虽然连接分配用的是kmem_cache_alloc而不是普通的kmalloc,相对来说速度会快一些,但还是挺浪费的。

为提高效率应该先检查规则然后再建立连接,这样对于每个进来的数据包,先查是否属于某个已经存在的连接,是则正常存在;否则是新连接,然后继续用数据包中的tuple值查找是否属于某主连接,如果确认是子连接,则分配连接的内存建立连接;否则这个包属于一个新主连接,这时先不分配连接空间,而是先检查规则,如果规则允许通过后再建立连接,这样就可以减少内存的分配释放次数。

对于NAT,对于SNAT还比较容易,因为可以在FORWARD最后再新建连接,但对DNAT这个就比较麻烦,NAT信息是记录在连接里的,如果连接不存在,那信息写哪呢?一般规则加在FORWARD链,这里的规则都是进行了目的地址转换了。

conntrack应该分两个节点,第一节点查连接,如果是ESTABLISHED的则数据和连接捆绑上就返回;如果是新连接这设置相关标志,然后进行规则过滤,规则是只对NEW的数据包进行过滤,其他的直接通过,也就是FORWARD点的规则挂到PREROUTING点进行,通过的再建立连接,然后进行DNAT处理。不过这样就无法匹配“-o”出网卡位置了。

如果是明显的新包,如TCP的SYN包,ICMP的ping包等,可以省略连接表查找这一步,直接进入规则点,并设相关标志,规则通过后再查连接是否是重发的,否则建立新连接,这样也可以提高效率。

如果这么作对现在的netfilter架构的改动就比较大了,任何调用了ip_conntrack_get()的模块都要重新处理,具体是否可行还要进一步论证。

相关推荐