iptables的maual的BUG一节:
BUGS
Bugs? What's this? ;-) Well, you might want to have a look at http://bugzilla.netfilter.org/
OK,我去netfilter的bug站点...唉,这帮人啊!
我相信很多人都遇到过iptables规则无法删除的问题,比如我使用了xtables-addons中的condition这个match模块,当我成功设置了一个规则后:
iptables -t mangle -A PREROUTING -m condition --condition xtt -j ACCEPT
然后尝试用上述规则的D命令删除之:
iptables -t mangle -D PREROUTING -m condition --condition xtt -j ACCEPT
我得到了一个报错:
iptables: Bad rule (does a matching rule exist in that chain?).
然而如果我用rulenum的方式则可以成功删除!即先查找上述规则的rulenum,然后删除该num标示的规则就可以成功,但是这样就多了一个步骤,我将不能仅仅通过简单的A或者D控制一条规则的增加和删除,于是,我必须找出来到底是哪里出了问题。
enum { CONDITION_NAME_LEN = 31, }; struct xt_condition_mtinfo { char name[CONDITION_NAME_LEN]; __u8 invert; /* Used internally by the kernel */ void *condvar __attribute__((aligned(8))); };注意那个注释!condvar字段只用在内核。如果你用过condition模块,你会知道,它除了一个名称参数之外,不会携带任何参数,也就是说仅仅iptables的命令不会对condvar进行任何设置,默认可能是NULL,然而整个结构体,当然也包括condvar,在添加规则的时候,全都会被注入内核并被内核保存起来,condvar的赋值是在内核中进行的,它表示一个内核结构体的地址。
static int condition_parse(int c, char **argv, int invert, unsigned int *flags, const void *entry, struct xt_entry_match **match) { struct xt_condition_mtinfo *info = (void *)(*match)->data; if (c == 'X') { if (*flags) xtables_error(PARAMETER_PROBLEM, "Can't specify multiple conditions"); if (strlen(optarg) < sizeof(info->name)) strcpy(info->name, optarg); else xtables_error(PARAMETER_PROBLEM, "File name too long"); info->invert = invert; #ifdef _DEBUG memset((char *)info+32, 0xC0, 1); memset((char *)info+33, 0x0B, 1); memset((char *)info+34, 0x2D, 1); memset((char *)info+35, 0x0A, 1); memset((char *)info+36, 0x00, 1); memset((char *)info+37, 0x88, 1); memset((char *)info+38, 0xFF, 1); memset((char *)info+39, 0xFF, 1); #endif *flags = 1; return true; } return false; }这样在make install之后,就可以成功删除了!
.userspacesize = XT_ALIGN(sizeof(struct xt_condition_mtinfo)),显然这是不对的,而实际上它应该是:
.userspacesize = XT_ALIGN(sizeof(struct xt_condition_mtinfo))-sizeof(...)-对齐...有一种更好的办法,即:
.userspacesize = offsetof(struct xt_condition_mtinfo, condvar ),这样iptables就会忽略掉condvar字段的比对。