|
|
This document is available in: English Castellano ChineseGB Deutsch Francais Nederlands Russian Turkce |
by Vincent Renardias <vincent(at)renardias.com> 关于作者: Vincent Renardias于1993使用GNU/Linux,1996年开始涉及于它的发展: Debian开发者,GIMP和GNOME 桌面的法语译者, Linux组织Marseille(PLUG) 的创始人...现在是EFB2公司的R&D经理,他始终为GNU/Linux做着贡献。 目录: |
Packet filtering with Linux摘要:
这篇文章首次发表是在Linux期刊法国特刊中的安全焦点上。编辑,作者和翻译者 总是和善的允许LinuxFocus发表这个特刊里的每一篇文章。因此,LinuxFocus将立 刻将他们翻译成英文带给你。感谢所有为此工作的人们。这个摘要将会被复制在每篇文 章的开头。
|
过滤机构可以被考虑成一张能够过滤有害的数据包的网。最重要要的是找到合适大
小的网孔和安装他的正确位置。
为了能够完全的过滤数据包,这个过滤机构必须无缝的插入他所要保护的网络和“其
余的世界”之间。在实践上,这个可以用一台带有两块网络接口(通常是以太网卡)的
设备来完成 ,一个连接内部的网络,另一块连接外部作为路由转发。这种方式,通信
将不得不通过防火墙,这样防火墙可以阻止他们或不依照他们的内容进行发送。
设备运行过滤机构可以被配置成3种不同的方式:
- "simple" Gateway:
这是最普通的配置。设备被用作两个网络或子网之间的网关。在本地网络内的电脑将使
用防火墙代替他们的默认路由。
- "Proxy-ARP" Gateway: 前面那个配置暗示着把一个网络划分成两个子网,这个
会造成一半可利用的 ip 地址失效了。这是有点恼人的。举个例子,一个16个地址的子
网(28位子网掩码),除去网络地址和广播地址只有14个是有效的,子网添加一位,有
效地址将从14减少到6(8个ip减去网络地址和广播地址)。当你不能够接受失去一半有
效ip地址的情况,你可以使用这种技术,我们将会在稍后的文章里解释他。此外,这种
技术不需要对网络中存在的路由器和被保护的电脑做的任何改变。
- Ethernet bridge: 作为一个以太网网关安装 (不是ip网关),使过滤机构对于
其他设备来说是透明的。因此不分配ip地址给以太网接口是妥当的。于是,设备将不会
被ping,traceroute等工具发现。让我们注意一个数据包过滤执行,在2.4.x内核还
还没完成前提下,基于这个端口的特性需要2.2.x的内核。
既然我们知道什么地方安装过滤器,那么我们必须定义什么应该阻止什么应该接受。
这里有两种方式去配置一个过滤器:
- 好的方法:没有数据被允许通过,除了规则允许的。
- 坏的方法:(不幸的是经常被使用)明确地阻止被禁止数据包,所有的数据包被接受。
这有一个简单的解释:在第一种情况,遗忘规则导致服务不完全工作或根本不工作。通
常,这会被很快的注意到,然后添加适当的规则使服务再运行起来。
在第二中情况,遗忘一个规则会造成一个潜在的弱点,如果我们去找,很难去发现...
在linux 2.4内核上使用的最多的包过滤软件是Netfilter:它很好的取代了使 用在2.2内核的‘ipchains’。Netfilter由两部分组成:内核支持这需要编译你的 内核和在你系统中可用到的‘iptables’命令
一个实例的注释比一段长时间的演讲要好的多,下面我们将描述怎样去安装和配置 一个过滤器设备。首先,设备要先配置成一个网关,使用Proxy-ARP来限定ip地址的 数量,我们将配置过滤系统。
著者偏好选择了Debian发布版来构建一个这样的系统,任何linux发行版都可以。
首先,检查你的内核已经支持Netfilter。如果是的,引导信息将包含:
ip_conntrack (4095 buckets, 32760 max)
ip_tables: (c)2000 Netfilter core team
另外,当Netfilter支持被激活后你不得不反编译内核。相应的选项将会在 "Networking Options"菜单里的"Network Packet Filtering" 子菜单里找到。从"Netfilter Configuration"选项,选择你需要的。 如果不能确定,你可以全部选择。此外,最好把Netfilter包含至内核,而不是作为加 载模块。如果因为一些原因或者Netfilter一个模块出错或不能加载,过滤器将不能工 作,我们不更多的谈论关于这么做所冒的风险了。
你也应该安装‘iproute2’包(这在最后是不必要做的,但是我们的实例将使
用从它允许我们建立配置脚本文件开始。)对于Debian,‘apt-get install iproute’
命令足够了。
其他的发行版,获得相应的软件包。用通常的方法,或从源程序安装。你可以在下面的
地址下载到相应的软件包:
ftp://ftp.inr.ac.ru/ip-routing/
现在对两块以太网卡配置。我们必须注意Liunx的内核,自动检测硬件程序到检测
网络卡的这一步时就会发现它。可是,仅仅第一块被探测到。
一个简单的解决方案是在lilo.conf文件里添加一句话:
append="ether=0,0,eth1"
现在,我们配置以太网接口。我们选择对两块网卡使用同一个ip地址的方法,因而
可以节约一个地址。
我们假定有一个10.1.2.96/28的子网。它的地址从10.1.2.96到10.1.2.111
路由器的地址是10.1.2.97,我们的过滤器设备的地址的10.1.2.98。eth0
接口之间如果没有通过hub或switch相连,那么将通过RJ45双绞线直接连接路由器;
eth1接口将连接hub或switch, 通过他它到达本地网络设备。
因此,两个接口将会被配置成下列参数:
address : 10.1.2.98 netmask : 255.255.255.240 network : 10.1.2.96 broadcast: 10.1.2.111 gateway : 10.1.2.97
接下来,我们使用下面的脚本,它必须在网卡初始化配置以后运行。
net.vars: configuration variables PREFIX=10.1.2 DMZ_ADDR=$PREFIX.96/28 # Interface definitions BAD_IFACE=eth0 DMZ_IFACE=eth1 ROUTER=$PREFIX.97 net-config.sh: network configuration script #!/bin/sh # Comment out the next line to display the commands at execution time # set -x # We read the variables defined in the previous file source /etc/init.d/net.vars # We remove the present routes from the local network ip route del $PREFIX.96/28 dev $BAD_IFACE ip route del $PREFIX.96/28 dev $DMZ_IFACE # We define that the local network can be reached through eth1 # and the router through eth0. ip route add $ROUTER dev $BAD_IFACE ip route add $PREFIX.96/28 dev $DMZ_IFACE # We activate Proxy-ARP for both interfaces echo 1 > /proc/sys/net/ipv4/conf/eth0/proxy_arp echo 1 > /proc/sys/net/ipv4/conf/eth1/proxy_arp # We activate the IP forwarding to allow the packets coming to one card # to be routed to the other one. echo 1 > /proc/sys/net/ipv4/ip_forward
让我们返回Proxy-ARP机制对我们的配置所必需的。
当一个设备在同一个网段里同另一台设备会话时,他需要知道以太网地址(或者MAC地
址或者硬件地址)相应的ip地址。当源设备广播请求”ip地址位1.2.3.4的MAC地址是
什么?”目标设备必须回答。
这里有一个“会话”的实例,是通过tcpdump检测到的:
- the request: the machine 172.16.6.72 asks the MAC address
corresponding to the IP address IP 172.16.6.10.
19:46:15.702516 arp who-has 172.16.6.10 tell
172.16.6.72
- the answer: the machine 172.16.6.10 provides its card
number.
19:46:15.702747 arp reply 172.16.6.10 is-at
0:a0:4b:7:43:71
通过这个简略的解释将引导我们到达目的地:ARP请求通过广播传播,因此它被限 定在同一个物理网段里。因此,受保护的设备想要去查找路由器MAC地址的请求将会被 过滤器设备阻止。激活着的Proxy-ARP的特色就是解决这个问题,它将传 输ARP请求。
这下一阶段里,你将有一个运行着的网络,它是由一台设备管理整个本地网络和外 网的通信。
现在,我们必须使用Netfilter建立过滤。
Netfilter允许直接对经过的数据包有所行动。在基本配置里,数据包被3条规则链管理:
- INPUT:数据包通过一个接口进来。
- FORWARD:把所有的数据包从一个接口转发到另一个接口。
- OUTPUT:数据包通过一个接口出去。
‘iptables’命令允许对这些链添加,改变或者移除规则从而修改过滤器的动作。
此外,每一个链有一个默认的策略,换句话说,它知道当一个数据包没有规则匹配时该
怎么处理。
当前有四个选项:
- ACCEPT:允许通过数据包。
- REJECT:拒绝数据包通过,关联的错误信息被传送(ICMP端口不能到达,TCP重置
关于这些的),
- LOG:把数据包记录写在syslog。
- DROP:忽略数据包,不发送回答。
这里有一些操作整个链常用到的iptables选项。我们将在稍后解释他们:
-N:创建一条新链。
-X:移除一条空链。
-P:改变一条链的默认策略。
-L:列出一条链的规则。
-F:清空一条链里所的规则。
-Z:清除已经通过这条链的字节和数据包包的计算器。
修改一条链,下面的命令将会有用的:
-A:添加一条规则在链的最后。
-I:插入一条新规则在链的给定位置。
-R:取代一条给定规则。
-D:删除链里的规则,可以使用规则的编号或它的具体描述。
让我们看一个简单的实例:我们将阻止对给定设备PING回应(这是一个'echo-reply'
类型的ICMP数据包)。
首先,让我们检测能"ping"通所给定的设备:
# ping -c 1 172.16.6.74 PING 172.16.6.74 (172.16.6.74): 56 data bytes 64 bytes from 172.16.6.74: icmp_seq=0 ttl=255 time=0.6 ms --- 172.16.6.74 ping statistics --- 1 packets transmitted, 1 packets received, 0% packet loss round-trip min/avg/max = 0.6/0.6/0.6 ms现在,我们对INPUT链添加一条规则,这将截取来自172.16.6.74('-s 172.16.6.74') 的ICMP-Reply数据包('-p icmp --icmp-type echo-reply')这些数据包将会被 忽略('-j DROP')。
# iptables -A INPUT -s 172.16.6.74 -p icmp --icmp-type echo-reply -j DROP
让我们再PING那个设备:
# ping -c 3 172.16.6.74 PING 172.16.6.74 (172.16.6.74): 56 data bytes --- 172.16.6.74 ping statistics --- 3 packets transmitted, 0 packets received, 100% packet loss
这和我们所期望的一样,回应没有通过。我们检查已经被阻止的3个回 应。(3个数据包共252字节)
# iptables -L INPUT -v Chain INPUT (policy ACCEPT 604K packets, 482M bytes) pkts bytes target prot opt in out source destination 3 252 DROP icmp -- any any 172.16.6.74 anywhere
如果想返回到初始状态,我们要做的仅仅是移除INPUT链里的第一条规则:
# iptables -D INPUT 1
我们再PING一次:
# ping -c 1 172.16.6.74 PING 172.16.6.74 (172.16.6.74): 56 data bytes 64 bytes from 172.16.6.74: icmp_seq=0 ttl=255 time=0.6 ms --- 172.16.6.74 ping statistics --- 1 packets transmitted, 1 packets received, 0% packet loss round-trip min/avg/max = 0.6/0.6/0.6 ms #
运行了!
你可以对3条存在链添加其他的链(这3条链你无论如何不能移除),使通信通过他 们。这是有用,举个例子,可以避免在不同的链里重复规则。
让我们设置一个最小化的防火墙所必需的规则。他将允许ssh,域(DNS),http,
smtp服务和其他一些无关紧要的。
为了简单化,将设置命令写在shell脚本比配置更容易一点。当这个脚本设立一个新的
规则前应当清空当前配置。这里有一个小诀窍去运行脚本,就是在配置没有副本规则下
被激活。
rc.firewall #!/bin/sh # Flushing out the rules iptables -F iptables -F INPUT iptables -F OUTPUT iptables -F FORWARD # The chain is built according to the direction. # bad = eth0 (outside) # dmz = eth1 (inside) iptables -X bad-dmz iptables -N bad-dmz iptables -X dmz-bad iptables -N dmz-bad iptables -X icmp-acc iptables -N icmp-acc iptables -X log-and-drop iptables -N log-and-drop # Specific chain used for logging packets before blocking them iptables -A log-and-drop -j LOG --log-prefix "drop " iptables -A log-and-drop -j DROP # The packets having the TCP flags activated are dropped # and so for the ones with no flag at all (often used with Nmap scans) iptables -A FORWARD -p tcp --tcp-flags ALL ALL -j log-and-drop iptables -A FORWARD -p tcp --tcp-flags ALL NONE -j log-and-drop # The packets coming from reserved addresses classes are dropped # and so for multicast iptables -A FORWARD -i eth+ -s 224.0.0.0/4 -j log-and-drop iptables -A FORWARD -i eth+ -s 192.168.0.0/16 -j log-and-drop iptables -A FORWARD -i eth+ -s 172.16.0.0/12 -j log-and-drop iptables -A FORWARD -i eth+ -s 10.0.0.0/8 -j log-and-drop # The packets belonging to an already established connexion are accepted iptables -A FORWARD -m state --state INVALID -j log-and-drop iptables -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT # The corresponding chain is sent according to the packet origin iptables -A FORWARD -s $DMZ_ADDR -i $DMZ_IFACE -o $BAD_IFACE -j dmz-bad iptables -A FORWARD -o $DMZ_IFACE -j bad-dmz # All the rest is ignored iptables -A FORWARD -j log-and-drop # Accepted ICMPs iptables -A icmp-acc -p icmp --icmp-type destination-unreachable -j ACCEPT iptables -A icmp-acc -p icmp --icmp-type source-quench -j ACCEPT iptables -A icmp-acc -p icmp --icmp-type time-exceeded -j ACCEPT iptables -A icmp-acc -p icmp --icmp-type echo-request -j ACCEPT iptables -A icmp-acc -p icmp --icmp-type echo-reply -j ACCEPT iptables -A icmp-acc -j log-and-drop # Outside -> Inside chain # mail, DNS, http(s) and SSH are accepted iptables -A bad-dmz -p tcp --dport smtp -j ACCEPT iptables -A bad-dmz -p udp --dport domain -j ACCEPT iptables -A bad-dmz -p tcp --dport domain -j ACCEPT iptables -A bad-dmz -p tcp --dport www -j ACCEPT iptables -A bad-dmz -p tcp --dport https -j ACCEPT iptables -A bad-dmz -p tcp --dport ssh -j ACCEPT iptables -A bad-dmz -p icmp -j icmp-acc iptables -A bad-dmz -j log-and-drop # Inside -> Outside chain # mail, DNS, http(s) and telnet are accepted iptables -A dmz-bad -p tcp --dport smtp -j ACCEPT iptables -A dmz-bad -p tcp --sport smtp -j ACCEPT iptables -A dmz-bad -p udp --dport domain -j ACCEPT iptables -A dmz-bad -p tcp --dport domain -j ACCEPT iptables -A dmz-bad -p tcp --dport www -j ACCEPT iptables -A dmz-bad -p tcp --dport https -j ACCEPT iptables -A dmz-bad -p tcp --dport telnet -j ACCEPT iptables -A dmz-bad -p icmp -j icmp-acc iptables -A dmz-bad -j log-and-drop # Chains for the machine itself iptables -N bad-if iptables -N dmz-if iptables -A INPUT -i $BAD_IFACE -j bad-if iptables -A INPUT -i $DMZ_IFACE -j dmz-if # External interface # SSH only accepted on this machine iptables -A bad-if -p icmp -j icmp-acc iptables -A bad-if -p tcp --dport ssh -j ACCEPT iptables -A bad-if -p tcp --sport ssh -j ACCEPT ipchains -A bad-if -j log-and-drop # Internal interface iptables -A dmz-if -p icmp -j icmp-acc iptables -A dmz-if -j ACCEPT
关于服务质量的几点说明。Linux能够修改ToS("Type of Service")字段,对 一个数据包赋予不同的优先权。举例:下面的命令改善流出的SSH数据包的连接响应。
iptables -A OUTPUT -t mangle -p tcp --dport ssh -j TOS --set-tos Minimize-Delay
用同样的方法,对于FTP连接你可以使用'--set-tos Maximize-Throughput' 选项来改善传输速度。
这就是Netfilter。现在你知道设置一个有效的数据包过滤系统的基础知识。但是,
紧记当涉及安全时防火墙并不是万能药。他仅仅是一种预防。你还需使用强壮的密码,
最新的安全补丁,入侵检测系统等等。
|
主页由LinuxFocus编辑组维护
© Vincent Renardias, FDL LinuxFocus.org |
翻译信息:
|
2004-03-15, generated by lfparser version 2.46