打开APP
userphoto
未登录

开通VIP,畅享免费电子书等14项超值服

开通VIP
netfilter中iptables表的实现
netfilter中iptables表的实现

本文档的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点处理函数的优先级来确定相对其他表的执行顺序。一般情况下不
需要添加新表,但在某些特殊功能,如实现虚拟系统,多个表分开过滤会更方便处理一些。

后记:本文初稿在基本写完时突然掉电,没存,这是第二版了,内容少了一些。 
 
 
本站仅提供存储服务,所有内容均由用户发布,如发现有害或侵权内容,请点击举报
打开APP,阅读全文并永久保存 查看更多类似文章
猜你喜欢
类似文章
【热】打开小程序,算一算2024你的财运
Linux中Netfilter的原理介绍
iptables ipt_do_table
netfilter: Linux 防火墙在内核中的实现
LINUX2.4.x网络安全框架
iptc library HOWTO
linux实现流量监控的几种方法
更多类似文章 >>
生活服务
热点新闻
分享 收藏 导长图 关注 下载文章
绑定账号成功
后续可登录账号畅享VIP特权!
如果VIP功能使用有故障,
可点击这里联系客服!

联系客服