首先,通过iptables命令将使用扩展模块的相关策略添加。例如:iptables -t mangle -A OUTPUT -p icmp -m pktsiz --size 100:200 -j DROP
其次,当接收到网络数据,内核对相关协议(IPV4)相关表(mangle)相关链(OUTPUT)..扩展模块(pktsize)进行匹配,对符合规则的进行相关的动作。
详见:https://blog.csdn.net/sidemap/article/details/103035483
1、用户空间数据结构定义
在扩展match模块时,需要对扩展的模块进行数据结构定义。由于该数据结构是被用来封装用户的数据数据,并且在内核中被解析,因此,最好将对该数据结构定义的文件,按照内核中uapi的文件路径结构定义,以便于往内核中引用。
6 struct
7 ipt_pktsize_info {
8 u_int32_t min_pktsize, max_pktsize;
9 };
2、用户空间的数据是传入到内核中
在用空空间iptables架构中,定义了结构体struct xtables_match(include/xtables.h)的x6_parse(parse为旧版版本)回调函数,将xt_option_call中的data(per-extension kernel data block)指向的内核内存进行数据填充(ipt_packetsize_info)
struct xtables_match
225 struct xtables_match {
226 /*
227 * ABI/API version this module requires. Must be first member,
228 * as the rest of this struct may be subject to ABI changes.
229 */
230 const char *version;
231
232 struct xtables_match *next;
233
234 const char *name;
235 const char *real_name;
236
237 /* Revision of match (0 by default). */
238 uint8_t revision;
239
240 /* Extension flags */
241 uint8_t ext_flags;
242
243 uint16_t family;
244
245 /* Size of match data. */
246 size_t size;
247
248 /* Size of match data relevant for userspace comparison purposes */
249 size_t userspacesize;
250
251 /* Function which prints out usage message. */
252 void (*help)(void);
253
254 /* Initialize the match. */
255 void (*init)(struct xt_entry_match *m);
256
257 /* Function which parses command options; returns true if it
258 ate an option */
259 /* entry is struct ipt_entry for example */
260 int (*parse)(int c, char **argv, int invert, unsigned int *flags,
261 const void *entry,
262 struct xt_entry_match **match);
263
264 /* Final check; exit if not ok. */
265 void (*final_check)(unsigned int flags);
266
267 /* Prints out the match iff non-NULL: put space at end */
268 /* ip is struct ipt_ip * for example */
269 void (*print)(const void *ip,
270 const struct xt_entry_match *match, int numeric);
271
272 /* Saves the match info in parsable form to stdout. */
273 /* ip is struct ipt_ip * for example */
274 void (*save)(const void *ip, const struct xt_entry_match *match);
275
276 /* Print match name or alias */
277 const char *(*alias)(const struct xt_entry_match *match);
278
279 /* Pointer to list of extra command-line options */
280 const struct option *extra_opts;
281
282 /* New parser */
283 void (*x6_parse)(struct xt_option_call *);
284 void (*x6_fcheck)(struct xt_fcheck_call *);
285 const struct xt_option_entry *x6_options;
286
287 /* Translate iptables to nft */
288 int (*xlate)(struct xt_xlate *xl,
289 const struct xt_xlate_mt_params *params);
290
291 /* Size of per-extension instance extra "global" scratch space */
292 size_t udata_size;
293
294 /* Ignore these men behind the curtain: */
295 void *udata;
296 unsigned int option_offset;
297 struct xt_entry_match *m;
298 unsigned int mflags;
299 unsigned int loaded; /* simulate loading so options are merged properly */
300 };
struct xt_option_call
135 /**
136 * @arg: input from command line
137 * @ext_name: name of extension currently being processed
138 * @entry: current option being processed
139 * @data: per-extension kernel data block
140 * @xflags: options of the extension that have been used
141 * @invert: whether option was used with !
142 * @nvals: number of results in uXX_multi
143 * @val: parsed result
144 * @udata: per-extension private scratch area
145 * (cf. xtables_{match,target}->udata_size)
146 */
147 struct xt_option_call {
148 const char *arg, *ext_name;
149 const struct xt_option_entry *entry;
150 void *data;
151 unsigned int xflags;
152 bool invert;
153 uint8_t nvals;
154 union {
155 uint8_t u8, u8_range[2], syslog_level, protocol;
156 uint16_t u16, u16_range[2], port, port_range[2];
157 uint32_t u32, u32_range[2];
158 uint64_t u64, u64_range[2];
159 double dbl;
160 struct {
161 union nf_inet_addr haddr, hmask;
162 uint8_t hlen;
163 };
164 struct {
165 uint8_t tos_value, tos_mask;
166 };
167 struct {
168 uint32_t mark, mask;
169 };
170 uint8_t ethermac[6];
171 } val;
172 /* Wished for a world where the ones below were gone: */
173 union {
174 struct xt_entry_match **match;
175 struct xt_entry_target **target;
176 };
177 void *xt_entry;
178 void *udata;
179 };
3、在内核中接收到iptables发送的数据
在内核中net/ipv4/netfilter/构建module处理扩展模块,构建module使用的数据结构xt_match,构建该对象之后,通过xt_register_match向系统进行注册。
30 static struct xt_match pktsize_match = {
31 .name = "pktsize",
32 .family = NFPROTO_IPV4,
33 .match = match,
34 .matchsize = sizeof(struct ipt_pktsize_info),
35 .destroy = NULL,
36 .me = THIS_MODULE,
37 };
xt_match实现(include/linux/netfilter/x_tables.h):
109 struct xt_match {
110 struct list_head list;
111
112 const char name[XT_EXTENSION_MAXNAMELEN];
113 u_int8_t revision;
114
115 /* Return true or false: return FALSE and set *hotdrop = 1 to
116 force immediate packet drop. */
117 /* Arguments changed since 2.6.9, as this must now handle
118 non-linear skb, using skb_header_pointer and
119 skb_ip_make_writable. */
120 bool (*match)(const struct sk_buff *skb,
121 struct xt_action_param *);
122
123 /* Called when user tries to insert an entry of this type. */
124 int (*checkentry)(const struct xt_mtchk_param *);
125
126 /* Called when entry of this type deleted. */
127 void (*destroy)(const struct xt_mtdtor_param *);
128 #ifdef CONFIG_COMPAT
129 /* Called when userspace align differs from kernel space one */
130 void (*compat_from_user)(void *dst, const void *src);
131 int (*compat_to_user)(void __user *dst, const void *src);
132 #endif
133 /* Set this to THIS_MODULE if you are a module, otherwise NULL */
134 struct module *me;
135
136 const char *table;
137 unsigned int matchsize;
138 #ifdef CONFIG_COMPAT
139 unsigned int compatsize;
140 #endif
141 unsigned int hooks;
142 unsigned short proto;
143
144 unsigned short family;
145 };
在其中的match函数xt_action_param会得到到通过用户空间iptables设置的数据(ipt_packetsize_info 100:200),其中 xt_action_param定义(也在include/linux/netfilt/x_table.h):
9 /**
10 * struct xt_action_param - parameters for matches/targets
11 *
12 * @match: the match extension
13 * @target: the target extension
14 * @matchinfo: per-match data
15 * @targetinfo: per-target data
16 * @net network namespace through which the action was invoked
17 * @in: input netdevice
18 * @out: output netdevice
19 * @fragoff: packet is a fragment, this is the data offset
20 * @thoff: position of transport header relative to skb->data
21 * @hook: hook number given packet came from
22 * @family: Actual NFPROTO_* through which the function is invoked
23 * (helpful when match->family == NFPROTO_UNSPEC)
24 *
25 * Fields written to by extensions:
26 *
27 * @hotdrop: drop packet if we had inspection problems
28 */
29 struct xt_action_param {
30 union {
31 const struct xt_match *match;
32 const struct xt_target *target;
33 };
34 union {
35 const void *matchinfo, *targinfo;
36 };
37 struct net *net;
38 const struct net_device *in, *out;
39 int fragoff;
40 unsigned int thoff;
41 unsigned int hooknum;
42 u_int8_t family;
43 bool hotdrop;
44 };
对于扩展match,设置的信息(ipt_pktsize_info)位于matchinfo中。