免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1721 | 回复: 1
打印 上一主题 下一主题

iptables实现中的一些trick [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-06-17 12:02 |只看该作者 |倒序浏览
itpables trick

以下讨论仅针对v1.3.5

1. 在同一个规则里的不同match的option不能重名

例如以下规则有问题
-m match1 --opt 1 -m match2 --opt 2
(无论match1和match2是相同的match还是不同的match)

原因:
0) 所有的-m参数都会触发merge_options操作
其主要工作是构造一个新的供getopt_long使用的选项列表
1) 扫描到-m match1,merge_options,--opt加到列表中
2) 扫描到--opt 1,match1的opt被正确的处理
3) 扫描到-m match2,merget_optpions,--opt再次被加到列表中
4) 扫描到--opt 2,依赖于getopt_long的实现,match1的参数处理函数被调用,与期望不同

2. 在同一个规则里不能有同一个match的两个实例

例如以下规则有问题
-m match --opta -m match --optb
(假设match支持opta和optb两个参数)

原因:还是跟merge_options有关
1) 两个-m对应同一个iptables_match(M),但是对应不同的ipt_entry_match(m1/m2)(类比类和对象)

2) iptables在遇到一个新的-m的时候(意味着前面的match处理完毕)不会去释放前面的match的信息
这样是为了优化iptables-restore,因为同一个match可以出现在多个规则中

3) 小小的跑一下题
从match的角度,每个支持的option都有个编号,例如match1把opt1编号1,opt2编号2,
(用于match->parse,通常有一个关于编号的switch,不同选项不同处理),
但match2同样会把opt3编号1,opt4编号2,那如何区分不同match的相同编号呢?

merge_options通过编号偏移解决了这个问题,
把match1的opt1和opt2的编号重新定义为257和258(偏移256),
把match2的opt3和opt4的编号重新定义为513和514(偏移512),
具体偏移是多少取决于match在规则中出现的顺序,每个match有256大小的编号空间

该偏移值记在M上,调用M->parse的使用会减去偏移,
例如--opt3会被识别为514,调用match2->parse的时候会变为514-512=2,跟match2的期待相同

PS:为什么--opt3不会被match1识别
实际上,--opt3会导致所有的match的parse都会被调用,
调用match1->parse的时候,但由于match1的偏移为256,
传递的编号为514-256=258,并不满足match1的期待(只期待1或者2)

4)跑题结束... 问题的关键在于偏移被记在了M上,而不是m1和m2上
4.1) 扫描-m match, M->offset=256, opta和optb的编号为257和258
4.2) 扫描--opta,编号257, 调用M->parse(257-256=1),没有问题
4.3) 扫描-m match, M->offset=512(原有值被覆盖了),第二份opta和optb编号为513和514
4.4) 扫描--optb,编号258(getopt忽略重复的选项),调用M->parse(258-512=-254),
        -254换成无符号是个很大的数,不是match所期望的选项

【未完待续】

论坛徽章:
0
2 [报告]
发表于 2009-06-17 15:01 |只看该作者

回复 #1 netentsec 的帖子

3. 当一条规则的参数很长的时候,iptables-restore会出现段错误

iptables-resotre保存参数时使用了stack上的空间(char param_buffer[1024]),
如果参数长度超过1024,则会破坏调用者的stack

4. limit/hashlimit的内核实现中的master到底起什么作用?

在limit/hashlimit等扩展模块的内核实现中,经常会看到如下的模式
int xxx_check_entry(..., void *matchinfo, ...)
{
        struct ipt_xxx_info *r = matchinfo;
        ...
        /* Ugly hack: For SMP, we only want to use one set */
        r->master = r;
        ...
}
int xxx_match(..., void *matchinfo, ...)
{
        struct ipt_xxx_info *r = matchinfo;
        r = r->master;
        ...
}
注释里已经说的很清楚了

SMP内核下,当iptables用户态在某个CPU上把规则传递给内核的时候,
该CPU会首先执行check_entry逻辑,检查规则是否合法,
然后它会把规则(对应matchinfo)在每个CPU上(自身除外)复制一份;
这样每个CPU在处理数据包的时候就可以并行的处理(至少规则的计数不需要同步)
从代码的角度,同一个规则的同一个match在不同CPU上看到的matchinfo是不相同的。

xxx_match里的r = r->master的含义就是,
使用执行check_entry时的matchinfo,而不是当前CPU上的被复制过来的matchinfo

这是因为limit/hashlimit是基于计数的逻辑,
不同CPU上处理的数据包,只要命中同一条limit/hashlimit规则,
都应该对同一个计数器进行更新(需要额外的同步逻辑)

例如一条限制某用户最多100个SYN包的规则,
假设用户的100个SYN包有一半经过CPU0,一半经过CPU1,
如果没有r = r->master,则100个SYN包过后,每个CPU的计数器都是50,
也就是说,每个CPU都还可以继续接收SYN包,这与预期不符合

注意:如果用nfhipac替换iptables的话,这种用法会导致crash
因为
1) nfhipac并没有在每个CPU上复制一份matchinfo的步骤,
2) 最终挂在DIM-tree里的matchinfo并不是执行check_entry时的matchinfo
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP