Netfilter之table、rule、match、target数据结构

这篇博客详细介绍了iptables中Netfilter的table、rule、match和target的数据结构。从struct xt_table开始,深入到struct xt_table_info,揭示了table中规则的组织方式。接着,讨论了match的两种形式——struct xt_match和struct xt_entry_match,以及target的struct xt_target和struct xt_entry_target。最后,阐述了rule如何由match和target组成。内容涵盖了这些关键数据结构在内核中的定义和它们在规则管理中的作用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在使用iptables过程中,经常会提到table、rule、match和target,这些在内核都有对应的数据结构(rule并没有对应结构体),在理解内核的逻辑代码之前,非常有必要先熟悉这些数据结构,以及内核到底是如何组织它们的。

这篇笔记记录了内核对这些对象的定义,下一篇笔记记录了内核是如何管理这些数据结构的。这篇笔记涉及的核心文件有:

代码路径说明
/net/netfilter/x_tables.hnetfilter框架对table、match、target的定义

1. struct xt_table

这是框架对table的定义:

struct xt_table
{
	struct list_head list;
	//table名字,如"filter", "nat"
	const char name[XT_TABLE_MAXNAMELEN];
	//按bit使用,表示该table保存了哪些HOOK点的规则
	unsigned int valid_hooks;
	//这把锁保护的是table中private指针指向内容
	rwlock_t lock;
	//实际上指向的是struct xt_table_info对象,其定义见下方
	void *private;
	/* Set this to THIS_MODULE if you are a module, otherwise NULL */
	struct module *me;
	//该table属于哪个协议族
	int af;		/* address/protocol family */
};

可见,struct xt_table仅仅是对table的基本描述,并没有保存table中的规则,更多的table内容都在其private成员中,该成员指向的结构是struct xt_talble_info对象,其定义如下。

1.1 struct xt_table_info

struct xt_table_info
{
	//table中所有规则占用的内存大小
	unsigned int size;
	//table中当前保存的规则数目
	unsigned int number;
	//初始注册时,table中规则的数量
	/* Initial number of entries. Needed for module usage count */
	unsigned int initial_entries;
	//每个table可以保存多个HOOK点的规则(由table的valid_hook决定),
	//从某个HOOK点进入后,检查规则时应该只检查该HOOK点上的规则,因此
	//为了给table中的规则按照HOOK点定界,有了下面两个成员:
	//hook_entry[]记录了各个HOOK点第一条规则距离entries的偏移;
	//underflow[]记录了各个HOOK点最后一条规则距离entries的偏移
	unsigned int hook_entry[NF_INET_NUMHOOKS];
	unsigned int underflow[NF_INET_NUMHOOKS];
	//table中的规则实际上是每个CPU都有一份拷贝,这是为了避免多CPU之间的互斥操作,
	//所以实际分配时entries是按照CPU个数分配的。比如有两个CPU,那么就分配2个char指针
	//的空间,分别用CPU ID进行索引
    char *entries[1];
};
//下面这个辅助宏用于计算struct xt_table_info对象的内存大小,
//注意已经根据CPU个数调整entries的大小
#define XT_TABLE_INFO_SZ (offsetof(struct xt_table_info, entries) \
			  + nr_cpu_ids * sizeof(char *))

表基本结构
如上图,rule1~ruleN为table中第一个HOOK点上所有的规则,那么hook_entries[0]就指向rule1(实际上是偏移量而不是指针),underflow[0]指向的就是ruleN,类似的,hook_entries[1]和underflow[1]分别指向ruleN+1和ruleM。更详细的信息见下一篇笔记中对table的分配函数的分析。

下面先来看match和target,再来看规则rule,因为规则是由match和target拼成的。

2. match

match即匹配,看match的数据结构要分两个角度来看:一是match本身,二是构成规则时,match又是如何表示的,下面先看match本身,再看规则中的match。

PS:要注意的是,下面介绍的match都是扩展match,标准match的结构见下面的rule介绍。

2.1 struct xt_match

在内核中,match都是以模块的形式存在的,内核用struct xt_match来表示一种支持的match。

struct xt_match
{
	struct list_head list;
	//每个match都有一个唯一的名字
	const char name[XT_FUNCTION_MAXNAMELEN-1];
	/* Return true or false: return FALSE and set *hotdrop = 1 to
           force immediate packet drop. */
	//判断skb是否匹配该match,匹配返回true,不匹配返回false
	bool (*match)(const struct sk_buff *skb, const struct net_device *in,
		      const struct net_device *out, const struct xt_match *match,
		      const void *matchinfo, int offset, unsigned int protoff, bool *hotdrop);
	/* Called when user tries to insert an entry of this type. */
	/* Should return true or false. */
	//在添加规则时,如果规则中有该match,那么调用该回调检查该match的参数是否正确
	bool (*checkentry)(const char *tablename, const void *ip, const struct xt_match *match,
			   void *matchinfo, unsigned int hook_mask);
	/* Called when entry of this type deleted. */
	void (*destroy)(const struct xt_match *match, void *matchinfo);
	/* Called when userspace align differs from kernel space one */
	void (*compat_from_user)(void *dst, void *src);
	int (*compat_to_user)(void __user *dst, void *src);
	/* Set this to THIS_MODULE if you are a module, otherwise NULL */
	struct module *me;
	/* Free to use by each match */
	unsigned long data;
	const char *table;
	unsigned int matchsize;
	unsigned int compatsize;
	unsigned int hooks;
	unsigned short proto;
	//match所属协议族
	unsigned short family;
	u_int8_t revision;
};

2.2 struct xt_entry_match

一旦match组成规则时,还涉及struct xt_entry_match,该结构才是真正在规则中保存的match。

struct xt_entry_match
{
	union {
		struct {
			u_int16_t match_size;
			/* Used by userspace */
			char name[XT_FUNCTION_MAXNAMELEN-1];
			u_int8_t revision;
		} user;
		struct {
			u_int16_t match_size;
			/* Used inside the kernel */
			struct xt_match *match;
		} kernel;
		/* Total length */
		u_int16_t match_size;
	} u;
	unsigned char data[0];
};

该结构是由用户空间和内核空间共享的,二者的公共结构是match_size和data字段,match_size表示整个match占用的内存空间。在配置规则时,用户空间指定了name,内核根据name查找系统中已注册的match,然后将match指针指向系统中已注册的struct match对象,从而建立起了规则中的match和match本身两个结构之间的联系。

3 target

和match类似,target本身的定义和在规则中的定义不同。

3.1 struct xt_target

这是target本身,内核中的target模块需要向内核注册一个struct xt_target对象。

struct xt_target
{
	struct list_head list;
	const char name[XT_FUNCTION_MAXNAMELEN-1];
	/* Returns verdict. Argument order changed since 2.6.9, as this
	   must now handle non-linear skbs, using skb_copy_bits and
	   skb_ip_make_writable. */
	unsigned int (*target)(struct sk_buff *skb, const struct net_device *in,
			       const struct net_device *out, unsigned int hooknum,
			       const struct xt_target *target, const void *targinfo);
	/* Called when user tries to insert an entry of this type:
           hook_mask is a bitmask of hooks from which it can be called. */
	/* Should return true or false. */
	bool (*checkentry)(const char *tablename, const void *entry,
			   const struct xt_target *target, void *targinfo, unsigned int hook_mask);
	/* Called when entry of this type deleted. */
	void (*destroy)(const struct xt_target *target, void *targinfo);
	/* Called when userspace align differs from kernel space one */
	void (*compat_from_user)(void *dst, void *src);
	int (*compat_to_user)(void __user *dst, void *src);
	/* Set this to THIS_MODULE if you are a module, otherwise NULL */
	struct module *me;
	const char *table;
	unsigned int targetsize;
	unsigned int compatsize;
	unsigned int hooks;
	unsigned short proto;
	unsigned short family;
	u_int8_t revision;
};

所有成员的含义和match基本一致,不在赘述。

3.2 struct xt_entry_target

struct xt_entry_target
{
	union {
		struct {
			u_int16_t target_size;
			/* Used by userspace */
			char name[XT_FUNCTION_MAXNAMELEN-1];
			u_int8_t revision;
		} user;
		struct {
			u_int16_t target_size;
			/* Used inside the kernel */
			struct xt_target *target;
		} kernel;
		/* Total length */
		u_int16_t target_size;
	} u;
	unsigned char data[0];
};

设计思想和struct xt_entry_match基本一致,不同点在于标准target也会有一个struct xt_entry_target结构对应,只不过其target指针为空。对于扩展target,该结构的target指针指向对应的struct xt_target对象。

4. rule

下面来看看规则的表示,首先要牢记:规则是由0个或多个match+1个target组成,当没有match时,认为是匹配所有,直接执行target。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值