1 /* 2 * 25-Jul-1998 Major changes to allow for ip chain table 3 * 4 * 3-Jan-2000 Named tables to allow packet selection for different uses. 5 */ 6 7 /* 8 * Format of an IP firewall descriptor 9 * 注意这里的说明:IP地址和掩码是按照网络字节存储(大端存储)标志字节和端口号是按 照主机字节序存储(依主机硬件结构而定) 10 * src, dst, src_mask, dst_mask are always stored in network byte order. 11 * flags are stored in host byte order (of course). 12 * Port numbers are stored in HOST byte order. 13 */ 14 15 #ifndef _IPTABLES_H 16 #define _IPTABLES_H 17 18 #ifdef __KERNEL__ 19 #include linux/if.h 20 #include linux/types.h 21 #include linux/in.h 22 #include linux/ip.h 23 #include linux/skbuff.h 24 #endif 25 #include linux/netfilter_ipv4.h 26 27 #define IPT_FUNCTION_MAXNAMELEN 30 28 #define IPT_TABLE_MAXNAMELEN 32 29 这个结构存储与IP头部有关的防火墙规则信息。这里的注释说“这个结构无须填充零字节 ”,就是说这个结构的大小正好是4的倍数。这里由于IFNAMSIZ等于16,所以整个结构大小 确实是4的倍数。 30 /* Yes, Virginia, you have to zero the padding. */ 31 struct ipt_ip { 32 /* Source and destination IP addr */ 33 struct in_addr src, dst; 34 /* Mask for src and dest IP addr */ 35 struct in_addr smsk, dmsk; 36 char iniface[IFNAMSIZ], outiface[IFNAMSIZ]; 37 unsigned char iniface_mask[IFNAMSIZ], outiface_mask[IFNAMSIZ]; 38 39 /* Protocol, 0 = ANY */ 40 u_int16_t proto; 41 42 /* Flags word */ 43 u_int8_t flags; 44 /* Inverse flags */ 45 u_int8_t invflags; 46 }; 47这个结构存储match的信息,这里的匹配主要是指与IP无关的防火墙规则信息。由系统缺 省设置的匹配主要有三个“tcp”、“udp”,“icmp”,我在分析ip_tables.c时将详细描 述。 48 struct ipt_entry_match 49 { 50 union { 51 struct { 52 u_int16_t match_size; 53 54 /* Used by userspace */ 55 char name[IPT_FUNCTION_MAXNAMELEN]; 56 } user; 57 struct { 58 u_int16_t match_size; 59 60 /* Used inside the kernel */ 61 struct ipt_match *match; 62 } kernel; 63 64 /* Total length */ 65 u_int16_t match_size; 66 } u; 67 68 unsigned char data[0]; 69 }; 70 target结构信息,是决定一个分组命运的信息。也可以理解为action信息,其意义是指 当一个分组与rule和match信息匹配后,如何处置该分组。处置方法一般有三种:一,命令 常数,比如DROP ACCEPT等等;二 系统预定义的模块处理函数,比如”SNAT DNAT"等等; 第三种是用户自己写模块函数。 71 struct ipt_entry_target 72 { 73 union { 74 struct { 75 u_int16_t target_size; 76 77 /* Used by userspace */ 78 char name[IPT_FUNCTION_MAXNAMELEN]; 79 } user; 80 struct { 81 u_int16_t target_size; 82 83 /* Used inside the kernel */ 84 struct ipt_target *target; 85 } kernel; 86 87 /* Total length */ 88 u_int16_t target_size; 89 } u; 90 91 unsigned char data[0]; 92 }; 93这个结构已经很明显给出了target的形式:命令常数、或者模块函数。 94 struct ipt_standard_target 95 { 96 struct ipt_entry_target target; 97 int verdict; 98 }; 99 计数器结构,每一个rule都有一个计数器结构用来统计匹配该条规则的分组数目和字节数 目。为基于统计的安全工具提供分析基础。 100 struct ipt_counters 101 { 102 u_int64_t pcnt, bcnt; /* Packet and byte counters */ 103 }; 104 标志字段,各个常数后面的注释已经给出了明确的解释,这里不再赘述。 105 /* Values for "flag" field in struct ipt_ip (general ip structure). */ 106 #define IPT_F_FRAG 0x01 /* Set if rule is a fragment rule */ 107 #define IPT_F_MASK 0x01 /* All possible flag bits mask. */ 108 109 /* Values for "inv" field in struct ipt_ip. */ 110 #define IPT_INV_VIA_IN 0x01 /* Invert the sense of IN IFACE. */ 111 #define IPT_INV_VIA_OUT 0x02 /* Invert the sense of OUT IFACE */ 112 #define IPT_INV_TOS 0x04 /* Invert the sense of TOS. */ 113 #define IPT_INV_SRCIP 0x08 /* Invert the sense of SRC IP. */ 114 #define IPT_INV_DSTIP 0x10 /* Invert the sense of DST OP. */ 115 #define IPT_INV_FRAG 0x20 /* Invert the sense of FRAG. */ 116 #define IPT_INV_PROTO 0x40 /* Invert the sense of PROTO. */ 掩码标志。用法是当出现超出掩码范围的标志时,确认是非法标志。 117 #define IPT_INV_MASK 0x7F /* All possible flag bits mask. */ 118 其实这个结构的构成这里的注释已经说的很清楚,但是从论坛上有人问"关于netfilter的 问题“时,可以看出很多人还是不理解。与前面ipchains版本防火墙不同的是iptables的 防火墙规则构成发生了变化。ipchains的构成是rule+target,而iptables的构成是ip匹 配信息+match+target。同时iptables构成的每一个部分都是可变大小的,由于经常出现 ”char XXX[0]“就可以看出。但是我个人认为规则的组织有点不好理解,它经常是先分配 一段空间,然后将规则一条一条放入。如同文件系统存放变长记录的文件时,总要在记录 中放入记录长度,以便以后取出记录,这里iptables正是使用这种方法,在每个规则中都 放入长度字段,这样方便提取各个组成部分和计算下一条规则的位置。 119 /* This structure defines each of the firewall rules. Consists of 3 120 parts which are 1) general IP header stuff 2) match specific 121 stuff 3) the target to perform if the rule matches */ 122 struct ipt_entry 123 { 124 struct ipt_ip ip; 125 126 /* Mark with fields that we care about. */ 127 unsigned int nfcache; 128下面两个字段用来计算target的位置和下一条规则的位置。 129 /* Size of ipt_entry + matches */ 130 u_int16_t target_offset; 131 /* Size of ipt_entry + matches + target */ 132 u_int16_t next_offset; 133 这个字段的存在,为发现规则中存在”环路“提供手段。 134 /* Back pointer */ 135 unsigned int comefrom; 136 137 /* Packet and byte counters. */ 138 struct ipt_counters counters; 139 140 /* The matches (if any), then the target. */ 141 unsigned char elems[0]; 142 }; 143 144 /* 145 * New IP firewall options for [gs]etsockopt at the RAW IP level. 146 * Unlike BSD Linux inherits IP options so you don't have to use a raw 147 * socket for this. Instead we check rights in the calls. */ 定义提供给set/getsockopt系统调用的命令常数的基常数。 148 #define IPT_BASE_CTL 64 /* base for firewall socket options */ 149 150 #define IPT_SO_SET_REPLACE (IPT_BASE_CTL) 151 #define IPT_SO_SET_ADD_COUNTERS (IPT_BASE_CTL + 1) 152 #define IPT_SO_SET_MAX IPT_SO_SET_ADD_COUNTERS 153 154 #define IPT_SO_GET_INFO (IPT_BASE_CTL) 155 #define IPT_SO_GET_ENTRIES (IPT_BASE_CTL + 1) 156 #define IPT_SO_GET_MAX IPT_SO_GET_ENTRIES 157 158 /* CONTINUE verdict for targets */ 159 #define IPT_CONTINUE 0xFFFFFFFF 160 161 /* For standard target */ 162 #define IPT_RETURN (-NF_MAX_VERDICT - 1) 163 Tcp匹配规则信息。 164 /* TCP matching stuff */ 165 struct ipt_tcp 166 { 167 u_int16_t spts[2]; /* Source port range. */ 168 u_int16_t dpts[2]; /* Destination port range. */ 169 u_int8_t option; /* TCP Option iff non-zero*/ 170 u_int8_t flg_mask; /* TCP flags mask byte */ 171 u_int8_t flg_cmp; /* TCP flags compare byte */ 172 u_int8_t invflags; /* Inverse flags */ 173 }; 174 tcp的取反标志值。 175 /* Values for "inv" field in struct ipt_tcp. */ 176 #define IPT_TCP_INV_SRCPT 0x01 /* Invert the sense of source ports. */ 177 #define IPT_TCP_INV_DSTPT 0x02 /* Invert the sense of dest ports. */ 178 #define IPT_TCP_INV_FLAGS 0x04 /* Invert the sense of TCP flags. */ 179 #define IPT_TCP_INV_OPTION 0x08 /* Invert the sense of option test. */ 180 #define IPT_TCP_INV_MASK 0x0F /* All possible flags. */ 181 udp匹配规则信息 182 /* UDP matching stuff */ 183 struct ipt_udp 184 { 185 u_int16_t spts[2]; /* Source port range. */ 186 u_int16_t dpts[2]; /* Destination port range. */ 187 u_int8_t invflags; /* Inverse flags */ 188 }; 189 190 /* Values for "invflags" field in struct ipt_udp. */ 191 #define IPT_UDP_INV_SRCPT 0x01 /* Invert the sense of source ports. */ 192 #define IPT_UDP_INV_DSTPT 0x02 /* Invert the sense of dest ports. */ 193 #define IPT_UDP_INV_MASK 0x03 /* All possible flags. */ 194 195 /* ICMP matching stuff */ ICMP匹配规则信息 196 struct ipt_icmp 197 { 198 u_int8_t type; /* type to match */ 199 u_int8_t code[2]; /* range of code */ 200 u_int8_t invflags; /* Inverse flags */ 201 }; 202 203 /* Values for "inv" field for struct ipt_icmp. */ 204 #define IPT_ICMP_INV 0x01 /* Invert the sense of type/code test */ 205 这个结构实质上用户通过getsockopt系统调用获取table信息时所传递参数的类型。 206 /* The argument to IPT_SO_GET_INFO */ 207 struct ipt_getinfo 208 { 209 /* Which table: caller fills this in. */ 210 char name[IPT_TABLE_MAXNAMELEN]; 211 212 /* Kernel fills these in. */ 213 /* Which hook entry points are valid: bitmask */ 214 unsigned int valid_hooks; 215 216 /* Hook entry points: one per netfilter hook. */ 217 unsigned int hook_entry[NF_IP_NUMHOOKS]; 218 219 /* Underflow points. */ 220 unsigned int underflow[NF_IP_NUMHOOKS]; 221 222 /* Number of entries */ 223 unsigned int num_entries; 224 225 /* Size of entries. */ 226 unsigned int size; 227 }; 228 这个结构是用户通过系统调用更换table是所传递的参数类型。 229 /* The argument to IPT_SO_SET_REPLACE. */ 230 struct ipt_replace 231 { 232 /* Which table. */ 233 char name[IPT_TABLE_MAXNAMELEN]; 234 235 /* Which hook entry points are valid: bitmask. You can't 236 change this. */ 237 unsigned int valid_hooks; 238 239 /* Number of entries */ 240 unsigned int num_entries; 241 242 /* Total size of new entries */ 243 unsigned int size; 244 245 /* Hook entry points. */ 246 unsigned int hook_entry[NF_IP_NUMHOOKS]; 247 248 /* Underflow points. */ 249 unsigned int underflow[NF_IP_NUMHOOKS]; 250 251 /* Information about old entries: */ 252 /* Number of counters (must be equal to current number of entries). */ 253 unsigned int num_counters; 254 /* The old entries' counters. */ 255 struct ipt_counters *counters; 256 257 /* The entries (hang off end: not really an array). */ 258 struct ipt_entry entries[0]; 259 }; 260 这个更改计数器时传递的参数类型。 261 /* The argument to IPT_SO_ADD_COUNTERS. */ 262 struct ipt_counters_info 263 { 264 /* Which table. */ 265 char name[IPT_TABLE_MAXNAMELEN]; 266 267 unsigned int num_counters; 268 269 /* The counters (actually `number' of these). */ 270 struct ipt_counters counters[0]; 271 }; 272 这个是想获取防火墙规则时,传递给系统调用的参数类型。 273 /* The argument to IPT_SO_GET_ENTRIES. */ 274 struct ipt_get_entries 275 { 276 /* Which table: user fills this in. */ 277 char name[IPT_TABLE_MAXNAMELEN]; 278 279 /* User fills this in: total entry size. */ 280 unsigned int size; 281 282 /* The entries. */ 283 struct ipt_entry entrytable[0]; 284 }; 285 286 /* Standard return verdict, or do jump. */ 287 #define IPT_STANDARD_TARGET "" 288 /* Error verdict. */ 289 #define IPT_ERROR_TARGET "ERROR" 290 现面定义了一些使用例程 291 /* Helper functions */ 获取一条防火墙规则的target位置 292 extern __inline__ struct ipt_entry_target * 293 ipt_get_target(struct ipt_entry *e) 294 { 295 return (void *)e + e->target_offset; 296 } 297 下面的宏遍历处理一条防火墙规则的所有匹配。我已经说过每一条防火墙规则在iptables 中分为三部分,而且每一部分的大小都是可变的。比如match部分,它本身可以有多个mat ch项。 298 /* fn returns 0 to continue iteration */ 299 #define IPT_MATCH_ITERATE(e, fn, args...) / 300 ({ / 301 unsigned int __i; / 302 int __ret = 0; / 303 struct ipt_entry_match *__m; / 这个for语句我来解释一下:首先__i取值为ipt_entry结构的大小,实质上就是match匹配 的开始处的偏移地址,将其与e相加就得到了match匹配的地址,然后调用fn处理这个匹配 。如果函数返回值为零,当前匹配的偏移地址加上当前匹配的大小,如果不超过target的 偏移地址,则继续处理下一条匹配。 304 / 305 for (__i = sizeof(struct ipt_entry); / 306 __i < (e)->target_offset; / 307 __i += __m->u.match_size) { / 308 __m = (void *)(e) + __i; / 309 / 310 __ret = fn(__m , ## args); / 311 if (__ret != 0) / 312 break; / 313 } / 314 __ret; / 315 }) 316 这个宏处理一个table中的所有防火墙规则。对比对上一个宏的理解,这里我就不解释了。 317 /* fn returns 0 to continue iteration */ 318 #define IPT_ENTRY_ITERATE(entries, size, fn, args...) / 319 ({ / 320 unsigned int __i; / 321 int __ret = 0; / 322 struct ipt_entry *__e; / 323 / 324 for (__i = 0; __i < (size); __i += __e->next_offset) { / 325 __e = (void *)(entries) + __i; / 326 / 327 __ret = fn(__e , ## args); / 328 if (__ret != 0) / 329 break; / 330 } / 331 __ret; / 332 }) 333 334 /* 335 * Main firewall chains definitions and global var's definitions. 336 */ 337 #ifdef __KERNEL__ 338 339 #include 340 extern void ipt_init(void) __init; 341 所有的匹配处理都注册到一个match处理链表中,链表结点的类型就是这里的结构类型。当 处理匹配时都是调用这里注册的处理函数。每个结点实质上由三个函数构成,一个匹配处 理函数,一个合法性检查函数,一个析构函数。最后一个是反身指针,指针的作用如注释 所示。 342 struct ipt_match 343 { 344 struct list_head list; 345 346 const char name[IPT_FUNCTION_MAXNAMELEN]; 347 348 /* Return true or false: return FALSE and set *hotdrop = 1 to 349 force immediate packet drop. */ 350 int (*match)(const struct sk_buff *skb, 351 const struct net_device *in, 352 const struct net_device *out, 353 const void *matchinfo, 354 int offset, 355 const void *hdr, 356 u_int16_t datalen, 357 int *hotdrop); 358 359 /* Called when user tries to insert an entry of this type. */ 360 /* Should return true or false. */ 361 int (*checkentry)(const char *tablename, 362 const struct ipt_ip *ip, 363 void *matchinfo, 364 unsigned int matchinfosize, 365 unsigned int hook_mask); 366 367 /* Called when entry of this type deleted. */ 368 void (*destroy)(void *matchinfo, unsigned int matchinfosize); 369 370 /* Set this to THIS_MODULE if you are a module, otherwise NULL */ 371 struct module *me; 372 }; 373 和match一样,所有的target都注册到这个结构类型的全局链表中,每个target的处理函数 都是这里注册的函数。和上面的解释一样,这里也主要包含三个函数指针。 374 /* Registration hooks for targets. */ 375 struct ipt_target 376 { 377 struct list_head list; 378 379 const char name[IPT_FUNCTION_MAXNAMELEN]; 380 381 /* Returns verdict. */ 382 unsigned int (*target)(struct sk_buff **pskb, 383 unsigned int hooknum, 384 const struct net_device *in, 385 const struct net_device *out, 386 const void *targinfo, 387 void *userdata); 388 389 /* Called when user tries to insert an entry of this type: 390 hook_mask is a bitmask of hooks from which it can be 391 called. */ 392 /* Should return true or false. */ 393 int (*checkentry)(const char *tablename, 394 const struct ipt_entry *e, 395 void *targinfo, 396 unsigned int targinfosize, 397 unsigned int hook_mask); 398 399 /* Called when entry of this type deleted. */ 400 void (*destroy)(void *targinfo, unsigned int targinfosize); 401 402 /* Set this to THIS_MODULE if you are a module, otherwise NULL */ 403 struct module *me; 404 }; 405 注册函数 406 extern int ipt_register_target(struct ipt_target *target); 407 extern void ipt_unregister_target(struct ipt_target *target); 408 409 extern int ipt_register_match(struct ipt_match *match); 410 extern void ipt_unregister_match(struct ipt_match *match); 411 table结构 412 /* Furniture shopping... */ 413 struct ipt_table 414 { 415 struct list_head list; 416 417 /* A unique name... */ 418 char name[IPT_TABLE_MAXNAMELEN]; 419 420 /* Seed table: copied in register_table */ 421 struct ipt_replace *table; 422 423 /* What hooks you will enter on */ 424 unsigned int valid_hooks; 425 426 /* Lock for the curtain */ 427 rwlock_t lock; 428 429 /* Man behind the curtain... */ 430 struct ipt_table_info *private; 431 }; 432 小结iptables的防火墙组织结构: 现在我们可以给出iptables防火墙规则的组织结构了。第一级是table级,每一个防火墙可 以有多个table;第二级是hook级,每一个table都有一个hook集合,每个hook都有一个防 火墙规则链;第三级基本规则级,基本规则级的规则包括三部分,IP规则信息、匹配规则 信息和target。而这三个组成部分的每一个都可以包括同类型的多个部分规则。 433 extern int ipt_register_table(struct ipt_table *table); 434 extern void ipt_unregister_table(struct ipt_table *table); 435 extern unsigned int ipt_do_table(struct sk_buff **pskb, 436 unsigned int hook, 437 const struct net_device *in, 438 const struct net_device *out, 439 struct ipt_table *table, 440 void *userdata); 441 有关table结构对齐的宏。 442 #define IPT_ALIGN(s) (((s) + (__alignof__(struct ipt_entry)-1)) & ~(__alig nof__(struct ipt_entry)-1)) 443 #endif /*__KERNEL__*/ 444 #endif /* _IPTABLES_H */ 445
|