3. iptables

iptables实现对规则的管理和访问。它里面有几个重要的数据结构ipt_entry,ipt_match,ipt_target,ipt_table,用于构造规则表。还有一个重要的函数ipt_do_table,用于遍历规则表并处理规则表上的结构。

ipt_entry是规则的数据结构,如下:

struct ipt_entry

{

struct ipt_ip ip;

unsigned int nfcache;

u_int16_t target_offset;/* target在规则中的偏移 */

u_int16_t next_offset; /* 下一条规则的偏移 */

unsigned int comefrom;

struct ipt_counters counters;/* 匹配规则的数据包的统计计数 */

unsigned char elems[0];

};

在ipt_entry中ipt_ip是一个基本的match,它是固定的,用于匹配数据包的源地址/源端口、目的地址/目的端口、协议等。其他的match按需要添加,个数并不固定,所以在ipt_entry有一个变长的字符数组保存规则中match的指针,这些指针指向系统中注册的match。每个规则有一个target,决定数据包完全匹配规则后怎样处理这个数据包,它也是一个指向系统注册的target的指针,并且也放在前面提到的变长字符数组中。ipt_entry中的target_offset是target在规则中的偏移,偏移是从规则的起始地址到target所在位置的长度,还有一个变量next_offset指示下一条规则偏移,它其实就是本条规则的长度。

前面提到在iptables中沿用了LINUX2.2.x中的chain和rule的概念,那么在ipt_entry中如何区分chain和rule的哪?

我们知道chain是某个检查点上检查的规则的集合。除了默认的chain外,还可以创建新的chain。在iptables中,同一个chain里的规则是连续存放的。默认的chain的最后一条规则的target是chain的policy。用户创建的chain的最后一条规则的target的调用返回值是NF_RETURN,遍历过程将返回原来的chain。规则中的target也可以指定跳转到某个用户创建的chain上,这时它的target是ipt_stardard_target,并且这个target的verdict值大于0。如果在用户创建的chain上没有找到匹配的规则,遍历过程将返回到原来chain的下一条规则上。

ipt_match用于匹配数据包的参数,如TCP数据包中的标志位,ICMP协议中的类型等,每个match所感兴趣的参数都不一样,所以一条规则可能有多个match。ipt_target决定在数据包完全匹配规则后应做什么样的处理。这两个在使用之间都必须先注册到系统的链表中才能被规则引用。对这两个数据结构不做过多分析,读者可以自行参考源代码。

ipt_table是规则表的数据结构,如下:

struct ipt_table

{

struct list_head list;

char name[IPT_TABLE_MAXNAMELEN];

struct ipt_replace table;/* 用户空间传递的规则表 */

unsigned int valid_hooks; /* 有效的检查点置位*/

rwlock_t lock;

struct ipt_table_info private; /* 规则表在内核中的存储结构 */

struct module *me;

};

在ipt_table中,ipt_replace是用户空间配置程序传递给内核的规则表,这个规则表不能直接使用,必须先根据它里面包含的match和target的名称将match和target转换成在内核注册的match和target的指针,还有一项重要的工作是检查规则表中是否有循环,如果有循环,要给用户空间的配置程序报告错误。转换之后的规则表存储在ipt_table_info中。valid_hooks指示与这个表相关的检查点,并把相应的位置为1。一个table中可以有多个chain,chain分为系统默认的chain(与table注册的检查点对应)和用户创建的chain。所有的table都注册放在一个链表中,而chain和rule则用偏移值next_offset连接成一个单向链表。

  1. 关于Linux操作系统的NTFS和内核分析
  2. Linux内核完全剖析---数学协处理器
  3. Linux内核完全剖析---math_emulate.c程序


相关内容