ip_conntrack为无状态无连接的IP增加了一个流记录机制,你可以把任何和一个流相关的东西放进去,但是放在哪里呢?原则上ip_conntrack应该是一个可以无限扩展的东西,但事实上,内核的设计者或者说Netfilter的ip_conntrack设计者并没有给用户程序员留下任何可以扩展它的接口和机制,你只能用现有的连接跟踪机制,虽然可以通过nf_ct_extend_register接口注册一个nf_ct_ext_type,但是这个接口也只是内核源码树自己使用的,你无法从外部定义一个心的nf_ct_ext_type。
既然有一个nf_ct_extend_register,为何不让从外部定一个nf_ct_ext_type,然后注册进去呢?除了C语言定义的数据结构不能自己解释自己实现反序列化之外,我觉得这是ip_conntrack代码树的一个缺陷,但是也许是内核开发模式和应用开发模式的不同导致的。一般的,内核API非常不稳定,对于应用来讲,内核的系统调用接口尽可能保持稳定就可以了,至于内部则完全是一个黑盒子。再者,内核开发需要一定的功底,不仅仅是你熟悉一些编程技巧和熟读API文档就能搞得定的。以上的原因,或者说是我的个人猜测,导致了不允许对ip_conntrack的结构体本身进行任何修改,你能改的仅仅是实现逻辑。Linux内核怎么做到这种限制的呢?很简单啊,把相关的头文件放到内核开发的头文件目录就可以了,事实上,只要是那个目录的头文件,你就别指望修改任何结构体和声明,因为那些是要参与符号CRC计算的。
理解了ip_conntrack的extend实际上并不能扩展之后,下面就展示一下老湿是怎么扩展它的。首先看一下ip_conntrack的extend结构是怎么组织的。实际上,我觉得这种组织非常好,非常紧凑,不容易产生内存碎片,它之所以如此紧凑是因为所有的extend相关的内容在内存中全部都是连续的。连续的内存当然没有指针寻址不连续内存方便,但是使用偏移也是不错的,更大的优势是申请/拷贝/释放比较方面,不用考虑深拷贝浅拷贝的问题。类似的数据结构还有iptables的rule在内核中的表示。
连续内存的表示法的最大好处就是可以任意扩展,因为它完全是靠偏移来定位位置的,如果你知道C++和JAVA这类OO语言,就会知道,一个普通类的内存布局中,处在开头的总是基类,所谓的扩展正是处在紧接着基类的内存位置,从而构成了一个子类,当然这只是从实现上来讲的,这里不谈思想!当然这也不是一种有性生殖行为,因为有性生殖从来都不是连续的,你不能说孩子是一个爸爸(是爸爸的一部分...),但是在内存连续的世界里,我们可以说:
struct B {
struct A a;
....
char *privatedata
};
是一个struct A,毕竟我可以把struct B从a字段往后的字段切掉。知道了这一切之后,我就可以对任意Linux预定义好的所有的nf_ct_ext_type进行任意的扩展了!事实上,我只需要扩展一个指针!虽然我很崇尚连续内存的布局,但是在我还是比较喜欢灵活,毕竟现在的内存价格已经不贵了,干嘛那么在乎内存啊。仅仅扩展一个指针,你想把它解释成一个什么机构都行!我们以一幅图来做解释:
理解了上面的那个图,就明白下面的定义了,不需要改变nf_conn_counter的结构体,只改变它的大小即可,即:
struct nf_conn_counter {
u_int64_t packets;
u_int64_t bytes;
};
的大小不是sizeof(struct nf_conn_counter),而是sizeof(struct nf_conn_counter)+sizeof(char *),定义为:
struct nf_conn_counter {
u_int64_t packets;
u_int64_t bytes;
char *p;
};
但是这样便改变了nf_conn_counter结构体的定义,但是考虑以上结构体, 在内存结构上,等价于:
struct my_st {
struct nf_conn_counter nfc;
char *p;
};
这样没有改变结构体的定义,结构体my事实上真的就“是一个”结构体nf_conn_counter,在这之后,需要修改的地方真的就不多了,仅仅是一个nf_ct_ext_type的len字段的修改。剩下的工作就是,在需要设置或者取出自己自定义的结构体的时候,按照下面这样:
struct my_st *ms = (struct my_st *)a_instance_of_struct_of_nf_conn_counter;
取出my_st的指针即可。接下来就可以访问my_st里面的p了,至于p是什么,自有作者解释。为何我不提倡连续内存而是用一个指针,关键是我觉得并不是每个conntrack都需要这个字段,为了节省内存只为需要的结构体分配内存,只能用指针。
这就是老湿的做法,JAVA编程思想,真的有思想。老湿很低级,不怎么懂编程,不符合编程高手的口味,但是老湿懂湿想,老湿知道这个机器奴役人的世界是多么的残酷,一个数字化的世界是多么的可悲,而是是编程的人特别是以编程为命的人所很难理解的...
分享到:
相关推荐
离线安装包,亲测可用
conntrack将信息存在内存结构中,包括IP,端口,协议类型,状态以及超时时间。 而且conntrack不仅可以对TCP这种有状态的会话进行状态跟踪,还可以对UDP进行状态跟踪。 conntrack本身并不会对包进行过滤,而是...
官方离线安装包,亲测可用。使用rpm -ivh [rpm完整包名] 进行安装
官方离线安装包,亲测可用
官方离线安装包,亲测可用
官方离线安装包,亲测可用
官方离线安装包,亲测可用
官方离线安装包,亲测可用
官方离线安装包,亲测可用。使用rpm -ivh [rpm完整包名] 进行安装
# 载入相关模块 PATH=/sbin:/bin:/usr/sbin:/usr/bin ...modprobe ip_conntrack_ftp > /dev/null 2>&1 modprobe ip_conntrack_irc > /dev/null 2>&1 modprobe ipt_MASQUERADE > /dev/null 2>&1
ConnView是conntrack表查看器。 这是php脚本-ip_conntrack表的前端。 您可以选择过滤,连接排序。 脚本可识别conntrack表中的常见服务。您可以查看连接列表或每个IP的详细信息列表等。
IPv4 support for nf_conntrack.
This is a module which is used for setting up fake conntracks on packets so that they are not seen by the conntrack/NAT code for linux.
you can redistribute it and or modify it under the terms of the GNU General Public License version 2.
Deleting the dummy variable which kicks off garbage collection.
Print out the per-protocol part of the tuple.
Print out the per-protocol part of the tuple.
Actually only need first 8 bytes.
Print out the per-protocol part of the tuple.