连接跟踪系统的初始化流程分析
有了前面的知识,我们再分析连接跟踪系统的初始化ip_conntrack_standalone_init()函数就太容易不过了。还是先上ip_conntrack_standalone_init()函数的流程图:
该函数的核心上图已经标出来了“初始化连接跟踪系统”和“注册连接跟踪的hook函数”。其他两块这里简单做个普及,不展开讲。至少让大家明白连接跟踪为什么需要两中文件系统。
1、 procfs(/proc文件系统)
这是一个虚拟的文件系统,通常挂载在/proc,允许内核以文件的形式向用户空间输出内部信息。该目录下的所有文件并没有实际存在在磁盘里,但可以通过cat、more或>shell重定向予以写入,这些文件甚至可以像普通文件那样指定其读写权限。创建这些文件的内核组件可以说明任何一个文件可以由谁读取或写入。但是:用户不能在/proc目录下新增,移除文件或目录。
2、 sysctl(/proc/sys目录)
此接口允许用户空间读取或修改内核变量的值。不能用此接口对每个内核变量进行操作:内核应该明确指出哪些变量从此接口对用户空间是可见的。从用户空间,你可以用两种方式访问sysctl输出的变量:sysctl系统调用接口;procfs。当内核支持procfs文件系统时,会在/proc中增加一个特殊目录(/proc/sys),为每个由sysctl所输出的内核变量引入一个文件,我们通过对这些文件的读写操作就可以影响到内核里该变量的值了。
除此之外还有一种sysfs文件系统,这里就不介绍了,如果你感兴趣可以去研读《Linux设备驱动程序》一书的详细讲解。
那么回到我们连接跟踪系统里来,由此我们可以知道:连接跟踪系统向用户空间输出一些内核变量,方便用户对连接跟踪的某些特性加以灵活控制,如改变最大连接跟踪数、修改TCP、UDP或ICMP协议的连接跟踪超时是时限等等。
注意一点:/proc/sys目录下的任何一个文件名,对应着内核中有一个一模一样同名的内核变量。例如,我的系统中该目录是如下这个样子:ip_conntrack_init()函数
该函数承担了连接跟踪系统初始化的绝大部分工作,其流程我们也画出来了,大家可以对照源码来一步一步分析。
第一步:连接跟踪的表大小跟系统内存相关,而最大连接跟踪数和连接跟踪表容量的关系是:最大连接跟踪数=8×连接跟踪表容量。代码中是这样的:
ip_conntrack_max = 8 × ip_conntrack_htable_size;那么从上面的图我们可以看出来,我们可以通过手工修改/proc/sys/net/ipv4/netfilter目录下同名的ip_conntrack_max文件即可动态修改连接系统的最大连接跟踪数了。
第二步:注册Netfilter所用的sockopt,先不讲,以后再说。只要知道是这里注册的就行了。
第三步:为连接跟踪hash表ip_conntrack_hash分配内存并进行初始化。并创建连接跟踪和期望连接跟踪的高速缓存。
第四步:将TCP、UDP和ICMP协议的连接跟踪协议体,根据不同协议的协议号,注册到全局数组ip_ct_protos[]中,如下所示:最后再做一些善后工作,例如注册DROP这个target所需的功能函数,为其他诸如NAT这样的模块所需的参数ip_conntrack_untracked做初始化,关于这个参数我们在NAT模块中再详细讨论它。
这样,我们连接跟踪系统的初始化工作就算彻底完成了。有了前几篇关于连接跟踪的基础知识,再看代码是不是有种神清气爽,豁然开朗的感觉。
至于连接跟踪系统所提供的那五个hook函数的注册,我想现在的你应该连都不用看就知道它所做的事情了吧。
未完,待续…