Linux协议栈-netfilter(5)-iptables

iptables是用户态的配置工具,用于实现网络层的防火墙,用户可以通过iptables命令设置一系列的过滤规则,来截获特定的数据包并进行过滤或其他处理。

iptables命令通过与内核中的netfilter交互来起作用。我们知道netfilter通过挂在每个hook点上的hook函数来过滤数据包,并且将过滤规则存放在几个表中供hook函数使用。相应的,iptables工具也定义了同样的几张规则表来对应netfilter中的表,以及定义了不同的链(chain)来对应netfilter中的hook点。这样,通过iptables命令生成的规则可以很容易的作用到内核中的netfilter模块,netfilter根据这些规则做真正的过滤工作。

netfilter模块中,不同的协议族定义了各自的一套hook点,例如,IPv4、IPv6、ARP、BRIDGE等协议族都分别定义了各自的netfilter处理流程以及各自的hook点,我们比较常见的就是IPv4协议定义的5个hook点(PRE_ROUTING,LOCAL_IN,LOCAL_OUT,FORWARD和POST_ROUTING)。同样的,为了和netfilter交互,在用户态分别有iptables、ip6tables、arptables、ebtables等命令来定义各协议族的过滤规则。

要使用iptables命令,则必须将netfilter模块编进内核。本文内容基于内核版本2.6.31。

1. 数据结构

netfilter中的每个表都定义成一个struct xt_table类型的结构体。例如下面定义的表:

   struct xt_table       *iptable_filter;

   struct xt_table      *iptable_mangle;

   struct xt_table      *iptable_raw;

   struct xt_table      *nat_table;

xt_table结构定义如下,表中的实际规则就放在其中的private成员中

struct xt_table
{
	struct list_head list;
	/* 在哪些hook点上注册了hook函数,是一个位图 */
	unsigned int valid_hooks;
	/*表的实际数据 */
	struct xt_table_info *private;
	struct module *me;
	/* 所属协议族 */
	u_int8_t af;
	/*表名,供用户空间设置iptables规则,或者内核匹配iptables规则 */
	const char name[XT_TABLE_MAXNAMELEN];
};

而private里的内容是:

/* The table itself */
struct xt_table_info
{
	/* 表的大小 */
	unsigned int size;
	/* Number of entries,即规则的数量 */
	unsigned int number;
	/* Initial number of entries,一般为上一次修改规则时的number */
	unsigned int initial_entries;

	/* 在每个hook点作用的entry的偏移(注意是相对于最后一个参数entry的偏移,即第一个hook的第一个ipt_entry的hook_entry为0) */
	unsigned int hook_entry[NF_INET_NUMHOOKS];

        /* 规则表的最大下界 */
	unsigned int underflow[NF_INET_NUMHOOKS];

	/* 规则表入口,即真正的规则存储结构. 在遍历一个规则表时,以此作为表的起始(即第一个ipt_entry)。由定义可知这是一个数组,每个元素对应每个CPU上的规则 入口。 */
	void *entries[1];
};

所以,通过private就可以定位到规则的实际内容了。

例如NAT表的定义如下,可知在定义时初始化好了下面4个成员。而在注册时会赋值list成员,在添加新规则时会给private赋值。
static struct xt_table nat_table = {
	.name		= "nat",
	.valid_hooks	= (1 << NF_INET_PRE_ROUTING) | \
			 (1 << NF_INET_POST_ROUTING) | \
			 (1 << NF_INET_LOCAL_OUT),
	.me		= THIS_MODULE,
	.af		= AF_INET,
};

一条iptables规则包括三个部分:ipt_entry、ipt_entry_matches、ipt_entry_target。

ipt_entry_matches由多个ipt_entry_match组成,ipt_entry结构主要保存标准匹配的内容,ipt_entry_match 结构主要保存扩展匹配的内容,ipt_entry_target结构主要保存规则的动作。

struct ipt_entry
{
	/* ipt_ip结构:将要进行匹配动作的IP数据报报头的描述 */
	struct ipt_ip ip;
/* 经过这个规则后数据报的状态:未改变,已改变,不确定 */
	unsigned int nfcache;
	/* Size of ipt_entry + matches,target在matches的后面 */
	u_int16_t target_offset;
/* Size of ipt_entry + matches + target,即下一个ipt_entry的开始 */
	u_int16_t next_offset;
/* 指向数据报所经历的上一个规则地址。还可以作为hook mask表示规则作用于那个
hook点上 */
	unsigned int comefrom;
/* 匹配这个规则的数据报的计数以及字节计数 */
	struct xt_counters counters;
/* 存放matches(一条规则可有0到多个match)和一个target */
	unsigned char elems[0];
};

结构体中的elems成员用于定位规则的matches,target_offset用于定位规则的target,next_offset指向下一条规则入口即下一个ipt_entry。这样,只要定位到一个表中第一个规则的ipt_entry,就可以找到这个表中的所有规则了。

一个表中可以有多条规则,下图以IPV4上注

  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值