netfilter中iptables表的实现

66 篇文章 0 订阅
本文档的Copyleft归yfydz所有,使用GPL发布,可以自由拷贝,转载,转载时请保持文档的完整性,严禁用于任何商业用途。
msn: yfydz_no1@hotmail.com
来源: http://yfydz.cublog.cn

1. 前言
 
iptables所制定的规则都是和内核中netfilter内的“表(table)”相联系的,缺省情况系统中已经自带了3个 表:filter、nat和mangle,iptables命令中的“-t”参数就是用来指定该规则是属于哪个表。和匹配和目标一样,netfilter 也提供了模块化的表功能扩展,用户可以根据需要自己编写新的表。
 
以下内核代码版本为2.4.26。
 
2. 表、规则、hook点之间的相互关系
 
netfilter的架构的基本过滤原理是网络栈中定义5个hook点,在每个hook点进行检查,就是按优先级执行挂接在该点上的所有struct nf_hook_ops结构的处理函数,只有这些函数都返回NF_ACCEPT才表示该数据包允许通过该hook点。
 
每个表中都要定义一些起效的hook点,这些hook点就对应了iptables规则中的链,如
filter表的起效hook点是NF_IP_LOCAL_IN、 NF_IP_FORWARD和NF_IP_LOCAL_OUT,对应iptables规则filter表中的INPUT、FORWARD和OUTPUT 链,在每个合法hook点都定义一个struct nf_hook_ops结构,每个struct nf_hook_ops结构都有一个基本处理函数,如filter表NF_IP_LOCAL_IN、NF_IP_FORWARD点的是 ipt_hook()函数,这些函数最终都会调用ipt_do_table()函数来进行该链中规则的遍历匹配操作,但要注意的是ipt_hook()等 基本处理函数的参数中并没有struct ipt_table结构的参数,所以目前这些表都是静态存在而不支持动态分配。
 
filter表在net/ipv4/netfilter/iptable_filter.c中定义,nat表在net/ipv4 /netfilter/ip_nat_rule.c中定义,mangle表在net/ipv4/netfilter/iptable_mangle.c中 定义.nat表和其他两个
稍有不同,其他两个表结构和hook_ops都在同一个文件中定义了,而nat的hook_ops是在net/ipv4/netfilter/ip_nat_standalone.c中定义的。
 
3. 数据结构
 
每个表都需要一个struct ipt_table结构来进行描述,建立一个新表就是要填写这样一个结构:
 
/* include/linux/netfilter_ipv4/ip_tables.h */
 
struct ipt_table
{
 struct list_head list;
 /* A unique name... */
 char name[IPT_TABLE_MAXNAMELEN];
 /* Seed table: copied in register_table */
 struct ipt_replace *table;
 /* What hooks you will enter on */
 unsigned int valid_hooks;
 /* Lock for the curtain */
 rwlock_t lock;
 /* Man behind the curtain... */
 struct ipt_table_info *private;
 /* Set this to THIS_MODULE if you are a module, otherwise NULL */
 struct module *me;
};
 
结构中包括以下参数:
struct list_head list:这是将该结构挂接到table链表中
char name[]:表名称
struct ipt_replace *table:struct ipt_replace结构定义该表基本属性
unsigned int valid_hooks:该表合法的挂接点位置
rwlock_t lock:表操作时的读写锁
struct ipt_table_info *private:这实际上是表中规则项表的索引指针,初始化为NULL
struct module *me:指向模块本身,统计模块是否被使用
 
其中struct ipt_table_info结构定义为:
 
/* include/linux/netfilter_ipv4/ip_tables.h */
 
struct ipt_table_info
{
 /* Size per table */
 unsigned int size;
 /* Number of entries: FIXME. --RR */
 unsigned int number;
 /* Initial number of entries. Needed for module usage count */
 unsigned int initial_entries;
 /* Entry points and underflows */
 unsigned int hook_entry[NF_IP_NUMHOOKS];
 unsigned int underflow[NF_IP_NUMHOOKS];
 /* ipt_entry tables: one per CPU */
 char entries[0] ____cacheline_aligned;
};
 
结构参数说明如下:
unsigned int size:表的大小
unsigned int number:规则数量
unsigned int initial_entries:初始化时的规则数
unsigned int hook_entry[NF_IP_NUMHOOKS]:各hook点起始规则的偏移
unsigned int underflow[NF_IP_NUMHOOKS]:各hook点结束规则的偏移
char entries[0]:实际的规则数组
 
其中struct ipt_replace结构定义为:
 
/* include/linux/netfilter_ipv4/ip_tables.h */
struct ipt_replace
{
 /* Which table. */
 char name[IPT_TABLE_MAXNAMELEN];
 /* Which hook entry points are valid: bitmask.  You can't
           change this. */
 unsigned int valid_hooks;
 /* Number of entries */
 unsigned int num_entries;
 /* Total size of new entries */
 unsigned int size;
 /* Hook entry points. */
 unsigned int hook_entry[NF_IP_NUMHOOKS];
 /* Underflow points. */
 unsigned int underflow[NF_IP_NUMHOOKS];
 /* Information about old entries: */
 /* Number of counters (must be equal to current number of entries). */
 unsigned int num_counters;
 /* The old entries' counters. */
 struct ipt_counters *counters;
 /* The entries (hang off end: not really an array). */
 struct ipt_entry entries[0];
};
 
结构参数说明如下:
 
char name[IPT_TABLE_MAXNAMELEN]:表名称
unsigned int valid_hooks:有效hook点
unsigned int num_entries:规则数
unsigned int size:规则大小
unsigned int hook_entry[NF_IP_NUMHOOKS]:各hook点起始规则的偏移
unsigned int underflow[NF_IP_NUMHOOKS]:各hook点结束规则的偏移
unsigned int num_counters:计数器的数量,各规则都有一个
struct ipt_counters *counters:计数器
struct ipt_entry entries[0]:规则入口
 
规则的存储是相当于数组方式存储的,只是数组大小会动态修改,每个表的所有规则都形成一个数组,而且是按hook点的顺序存储,如对于 filter表,数组开始是INPUT链的规则,后面是FORWARD链规则,然后是OUTPUT链的规则,最后是处理错误的规则,这就是 iptables规则使用“-L -v -v”时看到的实际的规则存储方式。各个hook点的规则起始和结束规则是靠struct ipt_table_info结构中的hook_entry[]和underflow[]来确定的。按数组方式实现在遍历处理时会比较快,但编辑时就比较 麻烦了,会伴随大量的内存重分配和拷贝操作。
 
在具体实现表时,在初始化ipt_table结构的struct ipt_replace结构参数时,除了struct ipt_replace结构本身的参数外,还自动添加描述各条链的缺省动作的规则,也就是说制定iptables规则时用“-P”定义的链的缺省动作也是 靠规则来实现的,如对于filter表的定义如下:
 
/* net/ipv4/netfilter/iptable_filter.c */
 
struct ipt_standard
{
 struct ipt_entry entry;
 struct ipt_standard_target target;
};
struct ipt_error_target
{
 struct ipt_entry_target target;
 char errorname[IPT_FUNCTION_MAXNAMELEN];
};
struct ipt_error
{
 struct ipt_entry entry;
 struct ipt_error_target target;
};
static struct
{
 struct ipt_replace repl;
 struct ipt_standard entries[3]; // 3个hook点,各自一条缺省规则
 struct ipt_error term; // 错误处理规则
} initial_table __initdata
 
4. 相关函数
 
表的处理函数相对比较少,使用函数 int ipt_register_table(struct ipt_table *)来登记表使之生效,而使用void ipt_unregister_table(struct ipt_table *)取消表的登记。在登记时,会初始化数据中的struct ipt_replace结构的数据转化到struct ipt_table_info结构中。登记后用iptables规则就可以用“-t table_name”来配置新表中的规则了。
 
每个表通过ipt_do_table()函数(net/ipv4/netfilter/ip_tables.c)来进行表中的规则匹配最终确定对数据包的动作。
 
5. 结论
 
netfilter的表处理也可以模块化实现,新表的添加可以以当前系统自带的表为蓝本来编写,只是要确定好各个hook点处理函数的优先级来确定相对其他表的执行顺序。一般情况下不需要添加新表,但在某些特殊功能,如实现虚拟系统,多个表分开过滤会更方便处理一些。
 
后记:本文初稿在基本写完时突然掉电,没存,这是第二版了,内容少了一些。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值