免费注册 查看新帖 |

Chinaunix

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

Linux netfilter-hacking-HOWTO(3) [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2008-01-22 10:32 |只看该作者 |倒序浏览

5.
2.0与2.2的包过滤模块的转义

查看ip_fw_compat.c文件,寻找一种使得端口控制非常简单的层定义。
6.
提供给Tunnel驱动程序编写者的网络过滤钩子(Netfilter Hooks)

Tunnel(或者叫做encapsulation(封装))驱动程序的编写者应该遵守2.4内核的两个简单的规则(如同内核内部的驱动所作的一样,比如net/ipv4/ipip.c):
1. 如果你想让数据包隐藏起来(即解封/封装),请释放skb->nfct。如果你把数据包解开到一个新的skb时,就不需要这样做了。但是如果你想正确地封装或者解封,就必须按照前面说得那样做。
否则:NAT编码就会使用旧的链接路径信息处理数据包,从而破坏原数据包的顺序性。
2. 请确认封装后的数据包通过LOCAL_OUT钩子,解封的数据包通过PRE_ROUTING钩子(很多tunnel都使用ip_rcv()函数来完成这些功能)
否则:用户不能想他们期望的那样,使用tunnel来完成过滤功能。
完成第一条规则标准方法是,在封装或者解封数据包之前使用下面的方法将代码嵌入其中:
/*告诉netfilter这个数据包与前面那个不相同*/
#ifdef CONFIG_NETFILTER
nf_conntrack_put(skb->nfct);
skb->nfct=NULL;
#ifdef CONFIG_NETFILTER_DEBUG
skb->nf_debug=0;
#endif
#endif
一般,对于第二条规则,你所做的只是找到“ip_send()”函数处理最新封装的数据包的地方,并且用类似下面的代码代替它:
/*从当地主机发送“新”的数据包/*
NF_HOOK(PF_INET, NF_IP_LOCAL_OUT, skb, NULL, rt->u.dst.dev, ip_send);
遵守这些规则意味着对于那些在tunnel box里使用数据包过滤规则的用户,他们将会看到经过tunnel的数据包会包括以下过程:
1. FORWARD钩子:普通数据包(来自eth0->tunl0)
2. LOCAL_OUT钩子:封装后的数据包(发往eth1)
对于应答数据包来说:
1. LOCAL_IN钩子:封装后的应答数据包(来自eth1)
2. FORWARD钩子:应答数据包(来自eth1->eth0)
7.
测试程序组
在CVS工具库中有一个工具叫做测试程序组:
测试程序组所测试的范围越广,
你就越能够确定对代码所进行的更改不会在未知的情况下破坏程序。
这些对于细微之处的测试起码应该象那些需要费脑筋的复杂的测试一样重要。
正是这写细微之处的测试使本来复杂的测试变得简单
(因为在那些复杂的测试进行之前,你起码知道那些基本的功能都是好用的)。
这种测试非常简单:它们只是存在于testsuite/目录里下的假设是能够正常运行的系统脚本程序。
这些脚本按照字母的运行,比如‘01test’就会在‘02test'前运行。一般来说,共有5个测试子目录:
00netfilter/                                                       常规 netfilter 架构测试
01iptables/                                                        iptables 测试
02conntrack/                                                       联结追踪测试
03NAT/                                                          NAT 测试
04ipchains-compat/                                         ipchains/ipfwadm 兼容性测试
  在testsuide/这个目录下有个叫做‘test.sh’的脚本。它配置了两个模拟的接口(tap0和tap1),可以转发并且清除所有的netfilter模块。然后通过它的上层目录来运行它们自己的test.sh脚本直到其中的一个测试失败。这个脚本有两个可选参数:“-v”,打印出它运行的每个测试;还有一个是可选的测试名称:如果提供了这个名称,那么它将跳过其他的测试而直接运行这个。
7.1
写一个测试
  在适当的目录中建立一个新的文件:记下你测试的次数以便它能够在正确的时间运行。比如,为了测试ICMP答复跟踪(02conntrack/02reply.sh),我们首先需要检察是否能够正确跟踪送出的ICMP(02conntrack/01simple.sh)。
  通常来说,建立很多小文件的效果更好一些,每一个文件测试一小部分,因为它能够帮助进行测试的人快速地确定问题所在的具体位置。
  如果在测试的过程中出现了问题,只需在出错的地方输入‘exit 1’;如果是出现了在你所预料到的错误,你就应当输出一条唯一的标识信息。如果一切正常的话,你的测试应当以‘exit 0’结尾。你最好使用这两种方法来确定每一条命令都正确地运行,一是在脚本的开始部分添加‘set -e’,或者在每一条命令后面添加‘|| exit 1’
 ‘load_module’和‘remove_module’这两个有用的函数可以来调用或删除模块:在测试程序组中千万不要相信自动加载,除非你能够确定这就是你要测试的东西。
7.2
变量和环境
  你有两个播放接口:tap0和tap1。它们的接口地址分别存在于变量$TAP0和$TAP1。它们都有255.255.255.0的掩码。它们的网络分别存于$TAP0NET和$TAP1NET。
  在$TMPFILE中是一个空的临时文件。在你的测试结束时,它将被删除。
  不论脚本在什么地方,它们都将在testsuite/这个目录下运行。因此你应当使用以“../userspace”开始的路径来存取工具(比如iptables)。
7.3
一些有用的工具
  在“tools”目录下,有一些有用处的测试组工具:如果有问题,这些程序就会以一个非零标志退出。
gen_ip
  使用“gen_ip”可以产生IP包,它将把一个IP包输出到标准输出。你可以在tap0和tap1中供给包,把一个标准输出送到/dev/tap0和/dev/tap1(如果不存在的话,那么第一次运行时它们将被建立)。
gen_ip是一个十分简单的程序,但目前它对参数顺序要求却是十分的严格。首先是常规的可选参数:
FRAG=offset,length
生成包,然后根据后面的offset和length将它转换成一个分段
MF
设置包的More Fragments位
MAC=xx:xx:xx:xx:xx:xx
设置包来源的MAC地址
TOS=tos
设置包的TOS域(0到255)
下面是一些必要的参数
source ip
包来源的IP地址
dest ip
包的目标IP地址
length
包括头信息在内,包的长度
protocol
包的协议号, 比如说 17 = UDP
  下面的参数根据协议的改变而不同:对于UDP(17),是源端口和目标端口。
  对于ICMP(1),是ICMP信息的类型和编码:如果type是0或者8(ping-reply 或 ping),那么还需要两个额外的参数(ID和顺序字段)。对于TCP协议,则需要源端口和目标端口,以及标志位("SYN", "SYN/ACK", "ACK", "RST" 或者 "FIN")。有三个可选参数,"OPT="后面是一个以逗号分割的选项列表,"SYN=" 后面是一个顺序号,最后"ACK="后面也是一个顺序号。最后一个可选参数是"DATA",它指明了TCP包的负载是由标准输入的内容填写的。
rcv_ip
你可以使用“rcv_ip”来查看IP包,它将为供给gen_ip使用的原始值尽可能接近地打印出命令行(分段除外)。这对于分析包是非常有用处的。它使用了两个必须的参数:
wait time
从标准输入所等待一个包的最大时间(秒)
iterations
接受包的数目
有一个可选参数。“DATA”,在包的头过后,它会在标准输出打印出一个包的有效负荷。
# 设置工作控制,以便我们能在脚本中使用&
set -m
# 当一个包从tap0中发来的时候,等待2秒
../tools/rcv_ip 2 1  $TMPFILE &
# 确定rcv_ip已经开始运行
sleep 1
发送一个ping包
../tools/gen_ip $TAP1NET.2 $TAP0NET.2 100 1 8 0 55 57 > /dev/tap1 || exit 1
# 等待rcv_ip
if wait %../tools/rcv_ip; then :
else
echo rcv_ip failed:
cat $TMPFILE
exit 1
fi
gen_err
这个程序在标准输入处捕捉一个包(比如由gen_ip产生),然后把它转换成一个ICMP的错误。
它又三个参数:源IP地址,类型和编码。目标IP地址可以设置成由标准输入产生的源IP包地址。
local_ip
这个参数从标准输入产生一个包,然后把它输入到一个写后读的socket。这就使一个本地产生的包能够出现。
(例如从一个ethertap设备上产生的包中抽出一个,就好象是远端生成的一样)
7.4
随机消息

所有的工具都假设自己能够在一次读写过程中能够完成所有的事情:对于其他的tap设备,这一点是正确的,但如果你要通过管道做一些狡猾的事情,那就不一定了。
dd可以用来切割包:dd有一个obs(output block size--输出块大小)选项,
首先进行对成功的测试:例如,测试包是否被成功的锁定。首先测试包是否能正常地通过,然后测试包是否被锁定。否则,一个不相关的错误就能够使包停止……
尝试正确地写测试,而不是进行“产生随机的材料然后看发生了什么”的这种测试。如果一个正确的测试出错了,这就是一个有用的事情。
如果一旦一个随机的测试出错了,那它不会有什么帮助的。
如果一个测试失败了但没有产生一个信息,你则可以在脚本的第一行添加一个“-x”(就是#! /bin/sh -x)来观察现在是在运行哪些命令。
如果一个测试随机地失败了,那么检察随机网络运输干扰(尝试一下把所有的外部接口关掉)。象Andrew Tridgell一样设置成一样的网络,例如,我倾向于是Windows广播引起的干扰。
8.
动机
As I was developing ipchains, I realized (in one of those blinding-flash-while-waiting-for-entree moments in a Chinese restaurant in Sydney) that packet filtering was being done in the wrong place. I can't find it now, but I remember sending mail to Alan Cox, who kind of said `why don't you finish what you're doing, first, even though you're probably right'. In the short term, pragmatism was to win over The Right Thing.
After I finished ipchains, which was initially going to be a minor modification of the kernel part of ipfwadm, and turned into a larger rewrite, and wrote the HOWTO, I became aware of just how much confusion there is in the wider Linux community about issues like packet filtering, masquerading, port forwarding and the like.
This is the joy of doing your own support: you get a closer feel for what the users are trying to do, and what they are struggling with. Free software is most rewarding when it's in the hands of the most users (that's the point, right?), and that means making it easy. The architecture, not the documentation, was the key flaw.
So I had the experience, with the ipchains code, and a good idea of what people out there were doing. There were only two problems.
Firstly, I didn't want to get back into security. Being a security consultant is a constant moral tug-of-war between your conscience and your wallet. At a fundamental level, you are selling the feeling of security, which is at odds with actual security. Maybe working in a military setting, where they understand security, it'd be different.
The second problem is that newbie users aren't the only concern; an increasing number of large companies and ISPs are using this stuff. I needed reliable input from that class of users if it was to scale to tomorrow's home users.
These problems were resolved, when I ran into David Bonn, of WatchGuard fame, at Usenix in July 1998. They were looking for a Linux kernel coder; in the end we agreed that I'd head across to their Seattle offices for a month and we'd see if we could hammer out an agreement whereby they'd sponsor my new code, and my current support efforts. The rate we agreed on was more than I asked, so I didn't take a pay cut. This means I don't have to even think about external conslutting for a while.
Exposure to WatchGuard gave me exposure to the large clients I need, and being independent from them allowed me to support all users (eg. WatchGuard competitors) equally.
So I could have simply written netfilter, ported ipchains over the top, and been done with it. Unfortunately, that would leave all the masquerading code in the kernel: making masquerading independent from filtering is the one of the major wins point of moving the packet filtering points, but to do that masquerading also needed to be moved over to the netfilter framework as well.
Also, my experience with ipfwadm's `interface-address' feature (the one I removed in ipchains) had taught me that there was no hope of simply ripping out the masquerading code and expecting someone who needed it to do the work of porting it onto netfilter for me.
So I needed to have at least as many features as the current code; preferably a few more, to encourage niche users to become early adopters. This means replacing transparent proxying (gladly!), masquerading and port forwarding. In other words, a complete NAT layer.
Even if I had decided to port the existing masquerading layer, instead of writing a generic NAT system, the masquerading code was showing its age, and lack of maintenance. See, there was no masquerading maintainer, and it shows. It seems that serious users generally don't use masquerading, and there aren't many home users up to the task of doing maintenance. Brave people like Juan Ciarlante were doing fixes, but it had reached to the stage (being extended over and over) that a rewrite was needed.
Please note that I wasn't the person to do a NAT rewrite: I didn't use masquerading any more, and I'd not studied the existing code at the time. That's probably why it took me longer than it should have. But the result is fairly good, in my opinion, and I sure as hell learned a lot. No doubt the second version will be even better, once we see how people use it.
9.
鸣谢
Thanks to those who helped, expecially Harald Welte for writing the Protocol Helpers section.


本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u1/55913/showart_469207.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP