服务器之家

专注于服务器技术!
当前位置:首页 > 服务器系统 > Linux

CentOS系统配置iptables

发布时间:2013-08-22 来源:服务器之家

1. 引言  
CentOS 內置了一个非常強劲的防火牆,统称为 iptables,但更正确的名称是 iptables/netfilter。iptables 是一个用戶空间的模块。作为用戶,你在命令行就是通过它将防火牆规则放进缺省的表裡。netfilter 是一个核心模块,它內置於內核中,进行实际的过滤。iptables 有很多前缀图像界面可以让用戶新增或定义规则,但它们很多时不及使用命令行般有灵活性,而且限制用戶了解实际发生的事情。我们将会学习 iptables 的命令行界面。
在我们正式应付 iptables 前,我们必须对它的运作有一个基本的理解。iptables 利用到 IP 地址、协议(tcp、udp、icmp)及端口这些概念。我们不需要成为这些方面的专家(因为我们可以找到所需的信息),但对它们有一般的理解会有帮助。
iptables 将规则放进缺省的规则链(INPUT、OUTPUT 及 FORWARD),而所有流量(IP 压缩)都会被相关的规则链检查,根据当中的规则判断如何处理每个压缩,例如:接纳或丟棄它。这些动作称为目标,而最常见的两个缺省目标就是 DROP 来丟棄压缩;或 ACCEPT 来接纳压缩。

规则链
我们可以在过滤表的 3 条缺省规则链內加入规则,来处理通过这些规则链的压缩。它们分別是:
INPUT - 所有以主机为目的地的压缩。
OUTPUT - 所有源自主机的压缩。
FORWARD - 这些压缩的目的地或来源地都不是主机,但路经主机(由它选路)。假若你的主机是一个路由器,这条规则链将会被应用。
我们将会花费最多时间处理 INPUT 规则链,借以过滤进入我们的机器的压缩 —— 亦即是将坏蛋拒诸门外。
规 则是以列表的方式被加进每条规则链。每个压缩会被头一条规则开始检查,才至最后一条。假若压缩与其中一条规则吻合,相应的动作便会被执行,例如接纳 (ACCEPT)或丟棄(DROP)压缩。一但有吻合的规则,这个压缩便会按照规则来处理,而不再被规则链內的其它规则所检查。假如压缩通过所有检查而不 符合任何规则链內的任何一条规则,那应这条规则链的缺省动作将会被执行。这就是所谓的缺省政策,可以设置为接纳(ACCEPT)或丟棄(DROP)压缩。
规则链拥有缺省政策这个概念带来两个基本的可能性,而我们必须考虑它们才能決定如何组织我们的防火牆。
1. 我们可以缺省一个政策来丟棄(DROP)所有压缩,然后刻意加入规则来接纳(ACCEPT)源自被信任的 IP 地址的压缩,或者打开那些提供服务的端口,如:bittorrent、FTP 服务器、网页服务器、Samba 文件服务器等。
又或者,
2. 我们可以缺省一个政策来接纳(ACCEPT)所有压缩,然后刻意加入规则来拦截(DROP)来自有问题的 IP 地址或系列的压缩,也或者阻止压缩进出只作私人用途或未提供服务的端口。
普遍来說,第一个方法多数用在 INPUT 规则链,因为我们会希望控制哪些东西可以访问我们的机器;而第二个方法多数用在 OUTPUT 规则链,因为我们多数信赖那些离开(源自)我们机器的压缩。
 
2. 準备开始 在命令行上使用 iptables 需要 root 的权限,因此你必须化身为 root 用戶来做下面的事情。

注意: 我们将会停用 iptables 及复位你的防火牆规则,因此假若你依赖你的 Linux 防火牆作为第一道防線,请特別留意这点。
iptables 应该缺省被安装在所有 CentOS 3.x、4.x 及 5.x 上。你可以这樣来检查 iptables 是否已安装在你的系统上:
 
$ rpm -q iptables
iptables-1.3.5-1.2.1
要知道 iptables 是否正在运作中,我们可以检查 iptables 这个模块是否已被装入,並利用 -L 这个选项来查看活动的规则:
 
# lsmod | grep ip_tables
ip_tables              29288  1 iptable_filter
x_tables               29192  6 ip6t_REJECT,ip6_tables,ipt_REJECT,xt_state,xt_tcpudp,ip_tables
 
# iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
RH-Firewall-1-INPUT  all  --  anywhere             anywhere
Chain FORWARD (policy ACCEPT)
target     prot opt source               destination
RH-Firewall-1-INPUT  all  --  anywhere             anywhere
Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
Chain RH-Firewall-1-INPUT (2 references)
target     prot opt source               destination
ACCEPT     all  --  anywhere             anywhere
ACCEPT     icmp --  anywhere             anywhere            icmp any
ACCEPT     esp  --  anywhere             anywhere
ACCEPT     ah   --  anywhere             anywhere
ACCEPT     udp  --  anywhere             224.0.0.251         udp dpt:mdns
ACCEPT     udp  --  anywhere             anywhere            udp dpt:ipp
ACCEPT     tcp  --  anywhere             anywhere            tcp dpt:ipp
ACCEPT     all  --  anywhere             anywhere            state RELATED,ESTABLISHED
ACCEPT     tcp  --  anywhere             anywhere            state NEW tcp dpt:ssh
REJECT     all  --  anywhere             anywhere            reject-with icmp-host-prohibited
从上面我们可看见缺省的规则,与及访问 SSH 服务用的规则。
如果 iptables 並未被执行,你可以这樣啟用它:
 
# system-config-securitylevel
 
3. 创建一组简单的规则

注意: 此刻我们将会清除缺省的规则集。如果你是通过 SSH 远程连接到一台服务器来进行学习,你有可能会将自己拒诸这台机器之外。你必须将缺省的输入(input)政策改为接纳(accept),然后才清除现有规则,接著你要预先加入一条容许你自己访问机器的规则,避免你将自己封锁在外。
我们会採用一个以样例为本的方法来查看 iptables 的不同指令。在首个样例中,我们会创建一组简单的规则来设置一个「状态压缩检验」(SPI)防火牆,容许对外的连接但拦截一切无用的对內连接:
 
# iptables -P INPUT ACCEPT
# iptables -F
# iptables -A INPUT -i lo -j ACCEPT
# iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# iptables -A INPUT -p tcp --dport 22 -j ACCEPT
# iptables -P INPUT DROP
# iptables -P FORWARD DROP
# iptables -P OUTPUT ACCEPT
# iptables -L -v
你应该得到这樣的输出:
 
Chain INPUT (policy DROP 0 packets, 0 bytes)
pkts bytes target     prot opt in     out     source               destination
0     0 ACCEPT     all  --  lo     any     anywhere             anywhere
0     0 ACCEPT     all  --  any    any     anywhere             anywhere            state RELATED,ESTABLISHED
0     0 ACCEPT     tcp  --  any    any     anywhere             anywhere            tcp dpt:ssh
Chain FORWARD (policy DROP 0 packets, 0 bytes)
pkts bytes target     prot opt in     out     source               destination
Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target     prot opt in     out     source               destination
现在让我们逐一看看以上的 8 个指令,並理解我们实际做了甚麼:
iptables -P INPUT ACCEPT 假如利用远程连接,我们必须临时将 INPUT 链的缺省政策改为 ACCEPT,否则当我们清除现有的规则集时,便会将自己封锁在服务器之外。
iptables -F 我们利用 -F 选项来清除一切现存的规则,好让我们能夠在崭新的状态下加入的规则。
iptables -A INPUT -i lo -j ACCEPT 现在是时候加入一些规则了。我们利用 -A 选项来附加(新增)规则到某条链,而这裡所指的是 INPUT 链。接著我们利用 -i 选项(interface「界面」之意)来指定那些符合或来自 lo(localhost、127.0.0.1)界面的压缩。最后我们 -j(jump「跳至」)符合这条规则的目标动作:在这裡是 ACCEPT。所以这条规则会导致所有转至 localhost 界面的对內压缩获得接纳。一般来說这是必须的,因为很多软件预期能夠与 localhost 适配器沟通。
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT 这是担负起大部份工作的规则,而我们再一次将它加进(-A)INPUT 链內。这裡我们利用 -m 选项来装入一个模块(state)。state 模块能夠查看一个压缩並判断它的状态是 NEW、ESTABLISHED 抑或 RELATED。NEW 指內进的压缩属於不是由主机啟主导的新增连接。ESTABLISHED 及 RELATED 指內进的压缩隸属於一条现存的连接,或者与现存的连接有关系。
iptables -A INPUT -p tcp --dport 22 -j ACCEPT 现在我们加入一条规则来容许 SSH 通过 tcp 端口 22 来连接。这樣做是要防止我们连接到远程系统的 SSH 连接意外地被封销。我们稍后会更详细解释这条规则。
iptables -P INPUT DROP 这个 -P 选项设置某条规则链上的缺省政策。我们现在可以将 INPUT 链的缺省政策改为 DROP。意思就是,不符合任何一条规则的对內压缩将会被丟棄。要是我们通过 SSH 远程连接而沒有加入上一条规则,此刻我们便会被封锁於系统之外。
iptables -P FORWARD DROP 同樣地,在这裡我们将 FORWARD 链的缺省政策设为 DROP,因为我们並不是用计算机作为路由器,所以理应沒有任何压缩路经它。
iptables -P OUTPUT ACCEPT 而最后,我们将 OUTPUT 链的缺省政策设为 ACCEPT,因为我们想容许所有对外的流量(由於我们信任我们的用戶)。
iptables -L -v 最后,我们可以列出(-L)刚加入的规则,並检查它们是否被正确地装入。
我们需要做的最后一件事情,就是存储我们的规则,好让它们在下次开机时会自动被重新装入:
 
# /sbin/service iptables save
这 樣做会执行 iptables 的 init 腳本,它会执行 /sbin/iptables-ave 並将现有的 iptables 设置写进 /etc/sysconfig/iptables。开机时,iptables 的 init 腳本会通过 /sbin/iptables-restore 这个指令重新施用存储在 /etc/sysconfig/iptables 內的规则。
很明显的,在指令殼內输入这堆指令会颇乏味,因此运用 iptables 的最简易方法就是创建一个代你做以上一切的腳本。你可以将上面的指令输入到你喜欢的文字编辑器內並存储为 myfirewall,例如:
 
#!/bin/bash
#
# iptables 样例设置腳本
#
# 清除 iptables 內一切现存的规则
#
iptables -F
#
# 容让 SSH 连接到 tcp 端口 22
# 当通过 SSH 远程连接到服务器,你必须这樣做才能群免被封锁於系统外
#
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
#
# 设置 INPUT、FORWARD、及 OUTPUT 链的缺省政策
#
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
#
# 设置 localhost 的访问权
#
iptables -A INPUT -i lo -j ACCEPT
#
# 接纳属於现存及相关连接的压缩
#
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
#
# 存储设置
#
/sbin/service iptables save
#
# 列出规则
#
iptables -L -v
註: 我们可以在腳本內加入註释来提醒自己正在做甚麼。
现在令腳本可以被执行:
 
# chmod +x myfirewall
我们现在可以编辑这个腳本,並在指令殼內用以下指令来执行它:
 
# ./myfirewall
 
4. 界面
在上一个范本中,我们看见如何能接纳所有来自某个界面的压缩,也就是 localhost 界面:
iptables -A INPUT -i lo -j ACCEPT
假设我们现在有两个独立的界面,分別是将我们连接到內联网的 eth0 及连接到外部互联网的 ppp0 拨号调制解调器(或者 eth1 适配器)。我们或许会想接纳所有来自內联网的对內压缩,但依然过滤那些来自互联网的压缩。我们可以这樣做:
 
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -i eth0 -j ACCEPT
让特別留意 —— 假如你接纳来自互联网界面(例如 ppp0 拨号调制解调器)的所有压缩:
 
iptables -A INPUT -i ppp0 -j ACCEPT
你便等同於停用了我们的防火牆!
 
5. IP 地址
将整个界面开放给对內的压缩也许不夠严谨,而你想拥有更多控制权来決定接纳甚麼及拒絕甚麼。现在假设我们拥有一群採用 192.168.0.x 私人网络的计算机。我们可以打开防火牆给来自某个被信任 IP 地址(例如 192.168.0.4)的对內压缩:
 
# 接纳来自被信任 IP 地址的压缩
iptables -A INPUT -s 192.168.0.4 -j ACCEPT # change the IP address as appropriate
将这个指令分解,我们首先附加(-A)一条规则到 INPUT 链,指明来源(-s)IP 地址是 192.168.0.4 的压缩都应该被接纳(ACCEPT)(请亦留意我们如何利用 # 符号来解释我们的腳本,因为 # 之后的所有文字都会被视为註释)。
当 然,如果我们想接纳来自一系列 IP 地址的压缩,我们可以为每个被位任的 IP 地址加入一条规则,而这樣做的确是可行的。但是假如它们的数量很多,一次过加入一系列 IP 地址会比较简单。要这樣做,我们可以利用一个子网掩码或标準的斜線记法来指定 IP 地址的范围。举个例說,如果我们想将防火牆开放给来自整个 192.168.0.x(当中 x=1 到 254)范围的压缩,我们可以用下面其中一个方法来达致目的:
 
# 接纳来自被信任 IP 地址的压缩
iptables -A INPUT -s 192.168.0.0/24 -j ACCEPT  # using standard slash notation
iptables -A INPUT -s 192.168.0.0/255.255.255.0 -j ACCEPT # using a subnet mask
最 后,除了过滤单一的 IP 地址外,我们亦可以配对该设备的 MAC 地址。要这应做,我们需要装入一个容许过滤 MAC