iptables 是 Linux 中重要的访问控制手段,是俗称的 Linux 防火墙系统的重要组成部分。这里记录了iptables 防火墙规则的一些常用的操作指令。
下面的操作以 CentOS 为基础介绍,应该对不同的 Linux 发行版都差不多。在 CentOS 5.x 和 6.x 中,iptables 是默认安装的(如果没有安装,先安装 iptables 即可)。如果对 iptables 的工作流程不太了解,可以先读读这篇 iptables 工作流程的通俗理解。
下面的操作指的是直接从 Linux 命令行输入的指令,也可以写成 .sh 文件批处理执行。
rpm -q iptables
这里返回的结果类似于 iptables-1.4.7-9.el6.i686
。
service iptables status
或者
iptables -L --line-numbers
该命令会以列表的形式显示出当前使用的 iptables 规则,每一条规则前面的编号可以用来做为其它操作——例如后面的删除操作——的参数,很有用。显示的结果类似于,
# service iptables status Table: filter Chain INPUT (policy ACCEPT) num target prot opt source destination 1 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED 2 ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0 3 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 4 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 state NEW tcp dpt:22 5 REJECT all -- 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited Chain FORWARD (policy ACCEPT) num target prot opt source destination 1 REJECT all -- 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited Chain OUTPUT (policy ACCEPT) num target prot opt source destination
显示出该 iptables 中有一个表 filter,其中在 INPUT chain 中有 5 条规则,在 FORWARD chain 中有 1 条规则,在 OUTPUT chain 中没有规则。
操作指令也是直接在终端输入,
iptables --help
可以查看 iptables 的帮助信息:
Usage: iptables -[AD] chain rule-specification [options] iptables -I chain [rulenum] rule-specification [options] iptables -R chain rulenum rule-specification [options] iptables -D chain rulenum [options] iptables -[LS] [chain [rulenum]] [options] iptables -[FZ] [chain] [options] iptables -[NX] chain iptables -E old-chain-name new-chain-name iptables -P chain target [options] iptables -h (print this help information) 指令Commands: Either long(单词,以 -- 做前导) or short(字母,区分大小写,以 - 做前导) options are allowed. --append -A chain Append to chain --delete -D chain Delete matching rule from chain --delete -D chain rulenum Delete rule rulenum (1 = first) from chain --insert -I chain [rulenum] Insert in chain as rulenum (default 1=first) --replace -R chain rulenum Replace rule rulenum (1 = first) in chain --list -L [chain [rulenum]] List the rules in a chain or all chains --list-rules -S [chain [rulenum]] Print the rules in a chain or all chains --flush -F [chain] Delete all rules in chain or all chains --zero -Z [chain [rulenum]] Zero counters in chain or all chains --new -N chain Create a new user-defined chain --delete-chain -X [chain] Delete a user-defined chain --policy -P chain target Change policy on chain to target --rename-chain -E old-chain new-chain Change chain name, (moving any references) 参数(选项)Options: [!] --proto -p proto protocol: by number or name, eg. `tcp' [!] --source -s address[/mask][...] source specification [!] --destination -d address[/mask][...] destination specification [!] --in-interface -i input name[+] network interface name ([+] for wildcard) --jump -j target target for rule (may load target extension) --goto -g chain jump to chain with no return --match -m match extended match (may load extension) --numeric -n numeric output of addresses and ports [!] --out-interface -o output name[+] network interface name ([+] for wildcard) --table -t table table to manipulate (default: `filter') --verbose -v verbose mode --line-numbers print line numbers when listing --exact -x expand numbers (display exact values) [!] --fragment -f match second or further fragments only --modprobe= try to insert modules using this command --set-counters PKTS BYTES set the counter during insert/append [!] --version -V print package version.
各种指令如下(前面的帮助信息中列出来的第一大块内容)。既可以使用长指令(单词,以 — 做前导),也可以使用短指令字母,区分大小写,以 – 做前导),例如,
iptables --append chain firewall-rule
等价于,
iptables -A chain firewall-rule
下面介绍各种指令。因为形式都一样,下面针对 –append -A 作详细介绍,其它的只介绍其作用。举例时仅使用短指令。
另外,指令后面所带的参数/选项,如果以 [ ] 包括,则表示该参数/选项可省略(有缺省值)。
指令形式,
iptables -A chain firewall-rule
“-A” 的意思是附加(append),并不是添加(Add)的意思。它是将规则添加到已有的防火墙链(chain)的末尾的操作指令。这是特别重要的,因为规则在 iptables 中的位置非常重要,所以千万要记住, -A 的意思是将规则添加到末尾。因为一般情况下 iptables 中最后一条规则是丢弃所有数据包。如果你已经有了一条这样的规则,使用 -A 参数添加的规则将会在丢弃规则之后,以至于新规则根本无法起作用。如果要插入到中间位置,需要用 -I 指令。
如果不理解 chain(链)的含义,最好先读读 iptables fundamentals。
从 chain 中删除与指定规则匹配,或指定编号的条目。
形式,
iptables -D chain firewall-rule
表示从 chain 中删除对应规则 firewall-rule 的那一条目。这种形式删除规则比较麻烦,通常用下面的形式
iptables -D chain rulenum
删除 chain 中编号为 rulenum 的那条规则。1 表示第一条。
形式,
iptables -I chain [rulenum] firewall-rule
将 firewall-rule 添加为 chain 中的第 rulenum 条规则,原先的第 rulenum 条及以后各条的需要顺次 +1。如上面一样,1 表示该 chain 中第一条。默认为 1,即,如果没有指定 rulenum 则将该 chain 中第一条规则替换掉。
形式,
iptables -R chain [rulenum] firewall-rule
将 chain 中原来的第 rulenum 条规则替换为 firewall-rule。如果没有指定 rulenum,则替换该 chain 中第一条。
形式,
iptables -L [chain [rulenum]]
列出 chain 或者所有 chain(当未指定 chain 名称时)中的 第 rulenum 条规则或者所有规则(当未指定 rulenum 时)。不过要注意,如果未指定 chain 则不能带 rulenum 参数。
如果在 -L 后再加上 –line-numbers,则表示在每条规则前面显示序号。如,
iptables -L --line-numbers
形式,
iptables -S [chain [rulenum]]
打印出 chain 或者所有 chain(当未指定 chain 名称时)中的 第 rulenum 条规则或者所有规则(当未指定 rulenum 时)。不过要注意,如果未指定 chain 则不能带 rulenum 参数。
形式,
iptables -F [chain]
清空 chain 或所有 chain (当未指定 chain 名称时)中的规则。
形式,
iptables -Z [chain [rulenum]]
把 chain 或者所有 chain(当未指定 chain 名称时)的包及字节的计数器清空。
形式,
--new -N chain
创建一个名称为 chain 的新链。
形式,
iptables -X [chain]
删除用户自定义 chain 或者所有用户自定义 chain(当未指定 chain 名称时)。该指令不影响预设规则(如 INPUT、OUTPUT、FORWARD 等)。
形式,
iptables -P chain target
改变 chain 的策略为 target。
形式,
iptables -E old-chain new-chain
将 old-chain 名称更改为 new-chain。这样做可以使所有引用 old-chain 的规则失效。
各种参数如下(前面的帮助信息中列出来的第二大块内容)。
上面某些防火墙参数还有属于它自己的参数选项,可以与其配合使用。下面是一些常用的选项。
要使用这些参数选项,需要指定相应的参数,例如,要使用 “–sport” 选项,应该在规则中指定 “-p tcp” (或者 “-p udp”)等参数。
注意:所有这些选项前面都是 –(2个短横线 – )。
在了解了各种 iptables 参数以及参数选项之后,再来看看下面的实例。
在这个例子中,我们的目标是:仅允许 SSH 连接到服务器,而其它所有连接都被禁止(包括 ping)。
警告:如果设置不当,可能会使系统无法通过网络访问,所以在玩 VPS 的时候要特别注意。不过如果是 Linode VPS 的话,它提供了 LISH 接口,可以让你象访问本地系统一样的操作 VPS,倒也不用太担心,只是有些麻烦而已。如果是别的 VPS,我就不太了解了。总之,万事小心!最好在本地的虚拟机里面测试这些玩意儿,否则把自己挡在了 VPS 外面无法通过 SSH 来连接控制台,那可就不好玩了。
如果已经有了某些规则,需要先备份一下,以后恢复起来也方便,
service iptables save iptables: Saving firewall rules to /etc/sysconfig/iptables:[ OK ]
默认保存为 /etc/sysconfig/iptables
。我们可以将这个文件再备份一下,
cp /etc/sysconfig/iptables /etc/sysconfig/iptables.x0
然后清空所有规则,从头开始,
iptables -F
当我们完成下面的设置后,就只能通过 SSH 连接服务器,而无法 ping 通或者访问服务器上的别的服务(如网站)了。切记不要在生产环境中玩。
下面开始设置使得服务器只接受 SSH 连接(不限制发起连接的位置),假设 SSH 使用了默认的端口 22.
使用下面的规则,让服务器接受所有通过 22 号端口进入的连接。
iptables -A INPUT -i eth0 -p tcp --dport 22 -j ACCEPT
上面的指令中包含了 4 个部分:
用普通话来讲,上面的规则就是说:所有从 eth0 接口传入的 SSH 连接都接受。
指明了系统可以接受的连接之后,一般要设置一条“丢弃”规则,将所有那些没有打算接受的数据包统统抛弃。
这样的规则应该放到 INPUT 链的最末位置。
要丢弃所有数据包(因为在刚才的那条接受 SSH 连接的规则的后面,所以不会影响到刚才那条规则),使用下面的命令添加规则,
iptables -A INPUT -j DROP
要查看刚才添加的规则,使用命令 iptables -L
,下面同时给了该命令的输出结果。
# iptables -L Chain INPUT (policy ACCEPT) target prot opt source destination ACCEPT tcp -- anywhere anywhere tcp dpt:ssh DROP all -- anywhere anywhere
从上面的结果可以看到,规则是按照我们输入的顺序排列的,
如果不想一条条的从命令行输入这些规则命令,最好创建一个脚本文件(shell script)来包含所有规则,然后自动执行。例如,
# vi iptables.sh iptables -A INPUT -i eth0 -p tcp --dport 22 -j ACCEPT iptables -A INPUT -j DROP # sh -x iptables.sh + iptables -A INPUT -i eth0 -p tcp --dport 22 -j ACCEPT + iptables -A INPUT -j DROP # iptables -L INPUT Chain INPUT (policy ACCEPT) target prot opt source destination ACCEPT tcp -- anywhere anywhere tcp dpt:ssh DROP all -- anywhere anywhere
看了上面的 iptables 命令及其参数/选项之后,应该就可以看懂我的 VPS 安全策略中的 iptables 设置了。
上面的介绍针对的是 iptables,也就是针对 IPv4 的防火墙。IPv6 的与之类似,不过 IPv6 的防火墙是 ip6tables。