4. 网络地址转换和代理 防火墙一个最大的应用是使几台机器可以通过一个公用的外部接口连到外部网络。对于那些熟悉linux的用户来说,这个概念就是ip伪装,对于其他人来说它有一个更模糊的说法"网络地址转换",简称NAT. 4.1 多个地址转换为一个地址 基本的NAT可以完成Linux ip伪装的功能,可以这样做: 4.2 多地址影射到地址池 NAT另外一个用法是将很多的静态地址映射(地址转换)到较少量的地址空间,利用你所学的知识就能够做到: 4.3 点对点映射 4.4 伪装 假设我们有一台web服务器地址是20.20.20.5,我们怀疑我们网络的安全性有问题,我们不想在端口80上提供服务,因为它需要用root来运行一小段时间。我们如何让web服务器运行于8000端口呢?客户机如何访问呢?我们可以使用NAT的重定向来解决这个问题,指示所有对20.20.20.5:80访问都指向20.20.20.5:8000,用rdr关键字来实现:
IP Filter Based Firewalls HOWTO
3.10 关键字Fastroute
尽管我们已经转发一些数据包并阻止其它一些数据包,这样看起来,我们的机器像一台路由器,防火墙同样也减少数据包TTL的值(一跳减一)而且告诉外面我们已经收到了数据包。但是我们可以在一些应用中(比如unix的traceroute)隐藏我们的存在,不减少TTL的值。如果我们想让进入的traceroute正常工作,但是我们不想让它知道防火墙的存在,我们可以这样做:
block in quick on xl0 fastroute proto udp from any to any port 33434 >< 33465
关键字fastroute将告诉ipfilter不要让这个包进入unix的ip栈,因为进入unix的ip栈会减少TTL的值。这个数据包会被防火墙偷偷的放到正确的出口,而且不会减少TTL的值。当然ipfilter会根据系统路由表指出数据包从哪个接口出去。
在这个例子中,我们使用了block quick是有理由的。如果我们使用了pass,而且我们在内核中打开ip转发,我们将会有两条这个数据包的出口路径,内核就很有可能"不知所措"。
需要注意的是,大部分unix的内核路由的代码比ipfilter的效率更高,因此这个关键字不是用来提高防火墙的性能,而仅仅是用来隐藏我们自己。
其实ipfilter可以称为NPAT,因为ipfilter不仅对地址进行转换还对端口进行转换,而NAT只是改变了地址。
map tun0 192.168.1.0/24 -> 20.20.20.1/32
很简单,只要源地址符合192.168.1.0/24通过tun0出去的数据包,它的源地址都会被改写为20.20.20.1而目的地址不会改变。系统为地址转换维护一个表,这样回复的包都可以根据这个表转换为正确的地址(20.20.20.1转换成内网地址)。
我们刚才写的那条规则有个缺点:在大部分情况下,我们不知道我们外网的ip地址(动态地址),幸好NAT解决了这个问题,它可以用0/32来代替,当它发现地址是0/32时它就知道应该查找接口的真正地址。
map tun0 192.168.1.0/24 -> 0/32
现在我们可以放心的加载NAT规则了,并且不用做任何修改就可以连到外部网了。你所需要做的仅仅是当你的IP地址改变后运行一下ipf -y
你或许会想到当地址转换的时候,端口有什么变化。以我们现在的规则源端口是不会改变的,在有些场合我们希望端口也能够改变,例如,当你的防火墙上面还有一个防火墙,而我们又需要通过这个防火墙,或者是有很多主机用到了相同的源端口,这个时候就会发生冲突,ipnat可以用关键字portmap解决这个问题:
map tun0 192.168.1.0/24 -> 0/32 portmap tcp/udp 20000:30000
它的作法是将所有的链接都塞入20000到30000之间的端口。
map tun0 192.168.0.0/16 -> 20.20.20.0/24 portmap tcp/udp 20000:60000
当然有些远程运用需要多个链接来自同一个ip地址(比如192.168.0.31需要访问218.9.121.110,它的并发链接经过NAT之后很有可能来自不同的IP地址),我们可以告诉NAT静态的映射每个链接,用关键字map-block实现:
map-block tun0 192.168.1.0/24 -> 20.20.20.0/24
rdr tun0 20.20.20.5/32 port 80 -> 20.20.20.5 port 8000
当然这里我们也可以指定协议,如果我们想重定向一个udp服务而不是tcp(tcp是默认的)。例如,如果我们在防火墙上有一个模仿windows后门的"蜜罐",我们可以把整个网络都定向到这个地方:
rdr tun0 20.20.20.0/24 port 31337 -> 127.0.0.1 port 31337 udp
rdr有一个相当重要的地方:你不能简单地把重定向用成“反射镜”。例如:
rdr tun0 20.20.20.5/32 port 80 -> 20.20.20.6 port 80 tcp
将不会正常工作,因为.5和.6在同一个局域网段上。首先,一个到达20.20.20.5接口tun0的数据包将会被重定向到20.20.20.6,也就是它的目的地址被修改了,然后被送到ipf过滤规则进行过滤(注意作用顺序,先地址转换后过滤),如果它通过了ipf,那么它就被送到unix路由代码处,这个时候这个数据包目的地址被改了,但是它的目的接口还是tun0,系统就不知道该怎么办了。因此"反射镜"是不能正常工作的。记住:使用rdr时,目的地址必须是从不同的接口离开防火墙。