Linux 版 (精华区)

发信人: lofe (『故乡Θ梧桐树』), 信区: Linux
标  题: Linux 2.4有状态防火墙设计(三)
发信站: 哈工大紫丁香 (2001年07月30日11:12:13 星期一), 站内信件

Linux 2.4有状态防火墙设计(三) 
2001-07-28 10:17 

发布者:netbull 阅读次数:164  


第五章 有状态改进 

明确关闭 ECN 


我以前提到过应当关闭 ECN(明确拥塞通知),以便因特网通信可以正确工作。虽
然您可能会按我的建议禁用了 ECN,但在将来您也许会忘了这样做。或者,您可能
将防火墙脚本传送给某个人,而那个人启用了 ECN。由于这些原因,最好使用 
/proc 接口来明确禁用 ECN,如下所示: 


if [ -e /proc/sys/net/ipv4/tcp_ecn ] 
then 
echo 0 > /proc/sys/net/ipv4/tcp_ecn 
fi 


转发 

如果使用 Linux 机器作为路由器,那么应该启用 IP 转发,它给予内核许可权,
以允许包在 eth0 和 eth1 之间传递,反之亦然。在我们的配置示例中,eth0 连
接到 LAN,eth1 连接到因特网,在允许 LAN 经由 Linux 机器连接因特网时,启
用 IP 转发是必要步骤。要启用 IP 转发,请使用以下这行命令: 


echo 1 > /proc/sys/net/ipv4/ip_forward 


处理拒绝,第 1 部分 


目前,我们已经删除了所有来自因特网的未经请求的通信流。虽然这是一种阻止讨
厌的网络活动的有效方法,但是它有一些缺点。这种方法最大的问题是闯入者很容
易就可以检测到我们正在使用防火墙,因为我们的机器没有应答标准 TCP 复位和
 ICMP 端口不可到达响应 -- 一般机器发送会的响应,用于表示对不存在服务的连
接失败。 


处理拒绝,第 2 部分 


与其让潜在的闯入者知道我们在运行防火墙(对于在提示他们,我们正在运行一些
他们不能得到的有价值服务),还不如假装我们根本没有运行服务。通过将以下两
个规则添加到 INPUT 链的末端,可以成功地完成此项任务: 


iptables -A INPUT -p tcp -i eth1 -j REJECT --reject-with tcp-reset 
iptables -A INPUT -p udp -i eth1 -j REJECT --reject-with 
icmp-port-unreachable 

第一个规则负责正确传递 TCP 连接,而第二个规则处理 UDP。只要这两个规则就
位,闯入者就很难检测到我们运行了防火墙;但愿,这会使闯入者离开我们的机器
,转而搜索其它更潜在的目标以供他滥用。 


处理拒绝,第 3 部分 


除了使防火墙变得更“隐蔽”,这些规则还消除了由于连接到某些 ftp 和 irc 服
务器带来的延迟。这个延迟是由于服务器对您的机器执行身份查找(连接到端口 
113)而引起的,并最终(大约 15 秒之后)导致超时。现在,防火墙将返回 
TCP 复位,身份查找将立即失败,而不是重试 15 秒(而您正在耐心地等待服务器
的响应)。 


防止欺骗 


在许多发行版中,当建成网络接口时,还会将旧的 ipchains 规则添加到系统。这
些特殊规则是由发行版的创建程序添加的,用于处理电子欺骗问题,即包的源地址
已经过调整,这样它们就包含了无效值(某些脚本骗子做的事)。虽然我们可以创
建类似的 iptables 规则来阻拦受到欺骗的包,但还有一种更简单的方法。目前,
内核的内置功能可以删除受到欺骗的包;我们要做的只是通过简单的 /proc 接口
来启用它。方法如下。 

for x in lo eth0 eth1 
do 
echo 1 > /proc/sys/net/ipv4/conf/${x}/rp_filter 
done 

此 shell 脚本将告诉内核删除接口 lo、eth0 和 eth1 上所有受到欺骗的包。可
以将这些行添加到防火墙脚本中,也可以将它们添加到创建 lo、eth0 和 eth1 接
口的脚本中。 


伪装 


NAT(网络地址转换)和 IP 伪装虽然与防火墙没有直接关系,但通常与防火墙一
起使用。我们将讨论您可能需要使用的两种常用 NAT/伪装配置。第一个规则负责
处理那种用拨号链接到使用动态 IP 的因特网 (ppp0) 的情况: 


iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE 

如果您属于这种情况,那么还应该转换防火墙脚本,将对 "eth1"(我们的示例 
DSL 路由器)更改成 "ppp0"。如果 ppp0 还不存在,最好添加引用 "ppp0" 的防
火墙规则。只要创建了 ppp0,一切立即就会正常工作。请确保还启用了 IP 转发
。 


SNAT 


如果使用 DSL 来连接因特网,那么您或许有两种可能配置中的一种。一种可能性
是 DSL 路由器或调制解调器有其自己的 IP 号码,并为您执行网络地址转换。如
果是这种情况,那么就不需要 Linux 来执行 NAT,因为 DSL 路由器已经这样处理
了。 

但是,如果想要更多地控制 NAT 功能,也许应该与 ISP 讨论关于 DSL 连接的配
置,以便使您的 DSL 连接处于“桥接方式”。在桥接方式中,防火墙将成为 
ISP 的网络中的正式部分,DSL 路由器将会在 ISP 和您的 Linux 机器之间透明的
来回转发 IP 通信流,而不会让任何人知道它的存在。它不再拥有 IP 号码;事实
上,eth1(在我们的示例中)隐藏了 IP。如果有人从因特网上 ping 您的 IP,他
们将从您的 Linux 机器上得到应答,而不是路由器。 


使用了这种设置,就应该使用 NAT(源 NAT),而不是伪装。以下就是您应该添加
到防火墙的一行代码: 


iptables -t nat -A POSTROUTING -o eth1 -j SNAT --to 1.2.3.4 

在这个示例中,应该将 eth1 更改成直接连接到 DSL 路由器的以太网接口,1.2.
3.4 应该更改成静态 IP(以太网接口的 IP)。再次声明,请记住要启用 IP 转发
。 


NAT 问题 


幸好,NAT 和伪装与防火墙能够和睦相处。在编写防火墙过滤规则时,应忽略正在
使用 NAT 的事实。您的规则应该根据包的“真正”源地址和目的地址接受、删除
或拒绝它们。防火墙过滤代码能够看到包的原始源地址,以及最终目的地址。这对
我们很有用处,因为它可以让防火墙继续正常工作,即使我们暂时禁用了 NAT 或
伪装。 


了解表 


在以上的 NAT/伪装示例中,我们将规则附加到链,但还做了一些略有不同的事。
请注意 "-t" 选项。"-t" 选项可以让我们指定链所属的表。当省略这个选项时,
缺省表将缺省为 "filter"。因此,以前所有与非 NAT 相关的命令修改 
"filter" 表中的 INPUT 链。"filter" 表包含了所有与接收或拒绝包相关的规则
,而 "nat" 表(如您假设的)包含了与网络地址转换相关的规则。还有其它内置
 iptables 链,在 iptables 帮助页面以及 Rusty 的 HOWTO(请参阅本教程结尾
处的“参考资料”部分,以获取链接)中详细描述了这些链。 


增强的脚本 


现在已经讨论过一些可能的增强,让我们看一下第二种更灵活的防火墙启动/停止
脚本: 


#!/bin/bash 

# An enhanced stateful firewall for a workstation, laptop or router that
 isn 
# running any network services like a web server, SMTP server, ftp 
server, etc. 

#change this to the name of the interface that provides your "uplink" 
#(connection to the Internet) 

UPLINK="eth1" 

#if you e a router (and thus should forward IP packets between 
interfaces), 
#you want ROUTER="yes"; otherwise, ROUTER="no" 

ROUTER="yes" 

#change this next line to the static IP of your uplink interface for 
static SNAT, or 
#"dynamic" if you have a dynamic IP. If you don need any NAT, set NAT to
 "" to 
#disable it. 

NAT="1.2.3.4" 

#change this next line so it lists all your network interfaces, 
including lo 

INTERFACES="lo eth0 eth1" 

if [ "$1" = "start" ] 
then 
echo "Starting firewall..." 
iptables -P INPUT DROP 
iptables -A INPUT -i ! ${UPLINK} -j ACCEPT 
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT 
iptables -A INPUT -p tcp -i ${UPLINK} -j REJECT --reject-with 
tcp-reset 
iptables -A INPUT -p udp -i ${UPLINK} -j REJECT --reject-with 
icmp-port-unreachable 

#explicitly disable ECN 
if [ -e /proc/sys/net/ipv4/tcp_ecn ] 
then 
echo 0 > /proc/sys/net/ipv4/tcp_ecn 
fi 

#disable spoofing on all interfaces 
for x in ${INTERFACES} 
do 
echo 1 > /proc/sys/net/ipv4/conf/${x}/rp_filter 
done 

if [ "$ROUTER" = "yes" ] 
then 
#we e a router of some kind, enable IP forwarding 
echo 1 > /proc/sys/net/ipv4/ip_forward 
if [ "$NAT" = "dynamic" ] 
then 
#dynamic IP address, use masquerading 
echo "Enabling masquerading (dynamic ip)..." 
iptables -t nat -A POSTROUTING -o ${UPLINK} -j MASQUERADE 
elif [ "$NAT" != "" ] 
then 
#static IP, use SNAT 
echo "Enabling SNAT (static ip)..." 
iptables -t nat -A POSTROUTING -o ${UPLINK} -j SNAT --to ${UPIP} 
fi 
fi 

elif [ "$1" = "stop" ] 
then 
echo "Stopping firewall..." 
iptables -F INPUT 
iptables -P INPUT ACCEPT 
#turn off NAT/masquerading, if any 
iptables -t nat -F POSTROUTING 
fi 


第六章 有状态服务 

查看规则 


在开始定制防火墙以便可以在服务器上使用它之前,我需要演示如何列出当前活动
的防火墙规则。要查看过滤器表的 INPUT 链中的规则,输入: 


# iptables -v -L INPUT 

-v 选项给出一个冗长的输出,这样我们可以查看每个规则传送的总包数和总的字
节数。还可以使用以下命令查看 nat POSTROUTING 表: 


# iptables -t nat -v -L POSTROUTING 
Chain POSTROUTING (policy ACCEPT 399 packets, 48418 bytes) 
pkts bytes target prot opt in out source destination 
2728 170K SNAT all -- any eth1 anywhere anywhere to:215.218.215.2 


准备提供服务 


现在,防火墙不允许陌生人连接我们机器上的服务,因为它只接受进入 
ESTABLISHED 或 RELATED 包。由于它删除了所有进入 NEW 包,因此所有连接尝试
都将被无条件拒绝。但是,只要有选择地允许一些进入通信流通过防火墙,我们就
可以让陌生人连接到我们指定的服务。 

有状态 HTTP 


虽然我们要接受一些进入连接,但我们可能并不想接受所有进入连接。最好从“缺
省拒绝”策略开始(就象我们现在使用的策略),逐渐开放对那些希望人们可以连
接的服务的访问。例如,如果正在运行 Web 服务器,我们允许 NEW 包进入我们的
机器,只要它们去往端口 80 (HTTP)。那就是我们需要做的。一旦允许 NEW 包进
入,那我们就允许建立连接。一旦建立了连接,就匹配了允许进入 ESTABLISHED 
和 RELATED 包的现有规则,从而 HTTP 连接将变得畅通无阻。 


有状态 HTTP 示例 


让我们看一下防火墙的“核心”,以及允许进入 HTTP 连接的新规则: 


iptables -P INPUT DROP 
iptables -A INPUT -i ! ${UPLINK} -j ACCEPT 
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT 
#our new rule follows 
iptables -A INPUT -p tcp --dport http -m state --state NEW -j ACCEPT 
iptables -A INPUT -p tcp -i ${UPLINK} -j REJECT --reject-with 
tcp-reset 
iptables -A INPUT -p udp -i ${UPLINK} -j REJECT --reject-with 
icmp-port-unreachable 

这个新规则允许去往我们机器的端口 80 (http) 的 NEW TCP 包进入。请注意这个
规则的位置。它出现在 REJECT 规则有重要意义。由于 iptables 将应用第一个匹
配的规则,因此将它放到 REJECT 行的后面会使这个规则无法生效。 


最后的防火墙脚本 


现在来看一下最后的防火墙脚本,它可以用于膝上型计算机、工作站、路由器或服
务器(或者其中的某些组合!)。 


#!/bin/bash 

#Our complete stateful firewall script. This firewall can be 
customized for 
#a laptop, workstation, router or even a server. :) 

#change this to the name of the interface that provides your "uplink" 
#(connection to the Internet) 

UPLINK="eth1" 

#if you e a router (and thus should forward IP packets between 
interfaces), 
#you want ROUTER="yes"; otherwise, ROUTER="no" 

ROUTER="yes" 

#change this next line to the static IP of your uplink interface for 
static SNAT, or 
#"dynamic" if you have a dynamic IP. If you don need any NAT, set NAT to
 "" to 
#disable it. 

NAT="1.2.3.4" 

#change this next line so it lists all your network interfaces, 
including lo 

INTERFACES="lo eth0 eth1" 

#change this line so that it lists the assigned numbers or symbolic 
names (from 
#/etc/services) of all the services that youd like to provide to the 
general 
#public. If you don want any services enabled, set it to "" 

SERVICES="http ftp smtp ssh rsync" 

if [ "$1" = "start" ] 
then 
echo "Starting firewall..." 
iptables -P INPUT DROP 
iptables -A INPUT -i ! ${UPLINK} -j ACCEPT 
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT 

#enable public access to certain services 
for x in ${SERVICES} 
do 
iptables -A INPUT -p tcp --dport ${x} -m state --state NEW -j ACCEPT 
done 

iptables -A INPUT -p tcp -i ${UPLINK} -j REJECT --reject-with 
tcp-reset 
iptables -A INPUT -p udp -i ${UPLINK} -j REJECT --reject-with 
icmp-port-unreachable 

#explicitly disable ECN 
if [ -e /proc/sys/net/ipv4/tcp_ecn ] 
then 
echo 0 > /proc/sys/net/ipv4/tcp_ecn 
fi 

#disable spoofing on all interfaces 
for x in ${INTERFACES} 
do 
echo 1 > /proc/sys/net/ipv4/conf/${x}/rp_filter 
done 

if [ "$ROUTER" = "yes" ] 
then 
#we e a router of some kind, enable IP forwarding 
echo 1 > /proc/sys/net/ipv4/ip_forward 
if [ "$NAT" = "dynamic" ] 
then 
#dynamic IP address, use masquerading 
echo "Enabling masquerading (dynamic ip)..." 
iptables -t nat -A POSTROUTING -o ${UPLINK} -j MASQUERADE 
elif [ "$NAT" != "" ] 
then 
#static IP, use SNAT 
echo "Enabling SNAT (static ip)..." 
iptables -t nat -A POSTROUTING -o ${UPLINK} -j SNAT --to ${UPIP} 
fi 
fi 

elif [ "$1" = "stop" ] 
then 
echo "Stopping firewall..." 
iptables -F INPUT 
iptables -P INPUT ACCEPT 
#turn off NAT/masquerading, if any 
iptables -t nat -F POSTROUTING 
fi 


 

来源:IBM developerWorks 中国  


--
直到有一天,
你看淡了一切,
觉得这些是人生来来往往中的一部分,
都是美丽的,
你就悟了。

※ 来源:·哈工大紫丁香 bbs.hit.edu.cn·[FROM: 172.16.7.88]
[百宝箱] [返回首页] [上级目录] [根目录] [返回顶部] [刷新] [返回]
Powered by KBS BBS 2.0 (http://dev.kcn.cn)
页面执行时间:4.871毫秒