现在要开始增加 ipfirewall 的规则以使内部网络获得安全。在实作时有点复杂,因为有些 ipfirewall 的功能在桥接的封包上无法使用。而且,在被桥接的封包和被本地机器接收的封包之间有些差异。一般而言,接收到被桥接的封包时只被过滤一次,而非一般情况的二次,因此使用规则 'out' 或 'xmit' 永远不会符合。我通常使用比较旧但阅读时有意义的语法 'in via'。另一个限制是只能使用 'pass' 或 'drop' 来过滤桥接封包,一些复杂的用法,如 'divert' 、 'forward' 或 'reject' 无法使用。这些语法只有在由机器本身出去或进来的网络传输才可以使用。
在 FreeBSD 4.0 中的新概念是 stateful filtering。对传统要求外流、其后跟随着相同 IP 地址及端口号的集合(但当然也有来源及目)的 UDP 网络传输而言,这是一个很大的吹嘘。对于没有状态维持的防火墙而言,要处理这一连串的网络传输缺乏建立代理权。但防火权可以"记得" 一个向外流的 UDP 封包,而在接下来的几分钟内允许响应,处理 UDP 服务十分繁琐,接下来的范例说明了如何实做。偏执狂也可以像这样建立 TCP 的规则。这样可以避免像拒绝服务攻击或其它令人不愉的恶作剧,但它也将使 state table 的大小急速成长。
我们来看一个设定的范例。请注意在/etc/rc.firewall 的文件顶端中,应该已经处理了 lookback 接口,且关于 ARP 的处理也已经设定好了,这样等一下才不用再顾虑这些。
us_ip=192.168.1.1 oif=fxp0 iif=fxp1 # Things that we've kept state on before get to go through in a hurry. ${ipfw} add check-state # Throw away RFC 1918 networks ${ipfw} add deny log ip from 10.0.0.0/8 to any in via ${oif} ${ipfw} add deny log ip from 172.16.0.0/12 to any in via ${oif} ${ipfw} add deny log ip from 192.168.0.0/16 to any in via ${oif} # 允许桥接器本身所有想做的联机 (keep state if UDP) ${ipfw} add pass udp from ${us_ip} to any keep-state ${ipfw} add pass ip from ${us_ip} to any # 允许内部网络任何想做的联机 (keep state if UDP) ${ipfw} add pass udp from any to any in via ${iif} keep-state ${ipfw} add pass ip from any to any in via ${iif} # 允许任何型式的 ICMP 联机 ${ipfw} add pass icmp from any to any # TCP section # 任何地方都可以建立 TCP 联机 ${ipfw} add pass tcp from any to any established # Pass the "quarantine" range. ${ipfw} add pass tcp from any to any 49152-65535 in via ${oif} # Pass ident probes. It's better than waiting for them to timeout ${ipfw} add pass tcp from any to any 113 in via ${oif} # Pass SSH. ${ipfw} add pass tcp from any to any 22 in via ${oif} # Pass DNS. 当内部网络有名称服务器时才需要 #${ipfw} add pass tcp from any to any 53 in via ${oif} # 只传递 SMTP 给邮件服务器 ${ipfw} add pass tcp from any to mailhost 25 in via ${oif} # UDP section # Pass the "quarantine" range. ${ipfw} add pass udp from any to any 49152-65535 in via ${oif} # Pass DNS. 当内部网络有名称服务器时才需要 #${ipfw} add pass udp from any to any 53 in via ${oif} # 其它的都拒绝 ${ipfw} add deny log ip from any to any
以前有设定过防火墙的人也许注意到有些东西遗漏了,即 anti-spoofing。这里并没有加入:
${ipfw} add deny ip from ${us_ip}/24 to any in via ${oif}
那是指丢弃任何自称来自于内部网络、却从外面来的封包。通常加入这条规则是为了确保别人无法试着以产生恶毒的封包,使它看起来像从内部发出而骗过封包过滤器。但问题是至少有一个在外面的机器你不想要被忽略--你的路由器。以我的情况而言,我有些机器在外面、有些在里面,但我不希望外部机器对内部有例行性的存取。但同时我也不希望把它们的网络传输丢弃,在我的情况里,我的 ISP 在他们的路由器中有 anti-spoofs,因此我不需要操心。而且一般而言,规则越少越好,因为每条规则都需要消耗时间及 CPU 的处理。
请注意最后一条规则几乎和内定的规则65536一模一样,然而以桥接器而言,这二条规则有二个最主要的差异。当然这里的规则在丢弃封包时会留下记录,但这里的规则只适用于 IP 传输,除了 UDP 0.0.0.0 外,无法处理非 IP 的网络传输,所以内定的规则 65536 会丢弃所有网络传输,而非只有非 IP 的传输。所以得到的影响是,不符合的 IP 传输会被记录下来,但非 IP 传输不会。如果你想要的话,可以在核心设定中增加这一项设定 IPFIREWALL_DEFAULT_TO_ACCEPT ,这样一来非 IP 的网络传输就会通过而不会被丢弃。但在具封包过滤的桥接器的情形下,你应该不会希望这样做(除非你是一个超级偏执狂)。
如果你有邮件服务器的话,其中有一条规则是用来传递 SMTP 协议的。以上所有规则很明显的只是个范例,你应该依自己的需求加以修改。特别注意为了使 'mailhost' 正常运作,名称服务器的查询应该在桥接器开始运作之前,这只是一个例子,确保你选择了正确的接口。
另一个要注意的是只要在提供DNS服务时才需要设定 DNS 的规则,也就是说如果没有设定 DNS 服务器,就不需要这条规则。
提供认证封包(TCP port 113)使用的规则中,也可以使用 'reset' 或 'forward' 的规则,不幸的是,这并非桥接器程序代码中提供的选项,因此最少妨碍它的路径就是干脆传递它,使它到达目的地。只要目的地的机器有在跑认证服务(ident daemon),就相对的没什么大碍。另一个选择是丢弃113埠的联机,如此将使诸如 IRC 等永远停不了(the ident probe must timeout)。
也许你已经注意到另一个奇怪的地方,就是允许机器本身所有联机及另一个允许内部网络所有联机的规则。记住这是因为二个网络传输集合是经由核心及封包过滤器这二个不同的路径交谈,内部网络是经由桥接器程序代码,而机器本身使用一般的 IP 堆栈,也就是说这二条规则分别处理不同的情形。而在 via ${oif} 的规则中,同时处理二个路径。一般而言,如果在过滤器中使用 via 规则,你必须为本机产生的封包加入一个例外处理,因为它们并不会经由(via)任何地方。
This, and other documents, can be downloaded from ftp://ftp.FreeBSD.org/pub/FreeBSD/doc/.
For questions about FreeBSD, read the
documentation
before contacting <questions@FreeBSD.org>.
For questions about this documentation, e-mail <doc@FreeBSD.org>.