Iptables是unix/linux自带的一款优秀且开放源代码的安全自由的基于包过滤的防火墙工具,它的功能十分强大,使用非常灵活,可以对流入和流出服务器的数据包进行很精细的控制。其主要工作在OSI七层的二、三、四层,如果重新编译内核,iptables也可以支持7层控制(squid代理+iptables)以下是个人实践的使用方法和心得分享给大家,其中包括一些使用技巧和日常工作中使遇到的坑的处理方法。
1.作用与用途
使用iptables命令可以设置、维护和检查在Linux内核中的IPv4数据包过滤规则表。几个不同的表可以被定义。每个表含有一些内置的链,也可以含有用户自定义链。每条链是规则可匹配一组的包的列表。每个规则指定如何处理数据包匹配。这就是所谓的“目标”,其可以在同一表中跳转到一个用户定义的链。
常用命令语法:
iptables [-t表] {-A|-D} [链] [规则详述]
iptables [-t表] -I [链] [规则号] [规则详述]
iptables [-t表] -R [链] [规则号] [规则详述]
iptables [-t表] -D [链] [规则号]
iptables [-t表] -S [链[规则号]]
iptables [-t表] {-F|-L|-Z} [链[规则号]] [选项]
iptables [-t表] -N [链]
iptables [-t表] -X [链]
iptables [-t表] -P [链] [目标]
iptables [-t表] -E [旧链名] [新链名]
其中:
-A 添加防火墙规则
-D 删除防火墙规则
-I 插入防火墙规则
-F 清空防火墙规则
-L 列出添加防火墙规则
-R 替换防火墙规则
-Z 清空防火墙数据表统计信息
-P 设置链默认规则
iptables 命令常用匹配参数及各自的功能如下:
-p 匹配协议,! 表示取反
-s 匹配源地址
-d 匹配目标地址
-i 匹配入站网卡接口
o 匹配出站网卡接口
--sport 匹配源端口
--dport 匹配目标端口
--src-range 匹配源地址范围
--dst-range 匹配目标地址范围
--limit 四配数据表速率
--mac-source 匹配源MAC地址
--sports 匹配源端口
--dports 匹配目标端口
--stste 匹配状态(INVALID、ESTABLISHED、NEW、RELATED)
--string 匹配应用层字串
iptables 命令触发动作及各自的功能如下。
ACCEPT:接收数据包。
DROP:丢弃数据包。
REDIRECT:将数据包重新转向到本机或另一台主机的某一个端口,通常能实现透明代理或对外开放内网的某些服务。
REJECT:拦截该数据封包,并发回封包通知对方。
SNAT:源地址转换,即改变数据包的源地址。例如:将局域网的IP(10.0.0.1/24)转换为广域网的IP(203.93.236.141/24),在NAT表的POSTROUTING链上进行该动作。
DNAT:目标地址转换,即改变数据包的目的地址。例如:将广域网的IP(203.93.236.141/24)转换为局域网的IP(10.0.0.1/24),在NAT表的PREROUTING链上进行该动作。
MASQUERADE:IP伪装,即常说的NAT技术,MASQUERADE只能用于ADSL等拨号上网的IP伪装,也就是主机的IP是由ISP分配动态的,如果主机的IP地址是静态固定的,就要使用SNAT。LOG:日志功能,将符合规则的数据包相关信息记录在日志中,以便管理员的分析和排错。
2.iptables使用
防火墙的工作策略一般包含两种方式,第一种是仅接受允许的数据,这种策略一般是设置防火墙的默认策略为拒绝所有数据包(也就是拒绝网卡上出入的数据包),然后有针对性地放开特定的访问;第二种是只防止不允许的数据访问请求,这种策略一般是设置防火墙的默认策略为允许所有数据包,只拒绝已知的非法访问数据。从安全效果而言,前一种防火墙策略表现更为优秀,所以这里使用第一种策略来开发防火墙脚本
以下根据日常使用中需要用到的iptables基本命令和使用方法进行介绍
2.1显示当前配置
首先在使用iptables -vnL查看当前规则。
[root@localhost ~]# iptables -vnL
Chain INPUT (policy ACCEPT 83 packets, 5911 bytes)
pkts bytes target prot opt in out source destination
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 54 packets, 4688 bytes)
pkts bytes target prot opt in out source destination
上面的结果表明还没有配置规则,没有数据包被阻止。在输入中添加--line-numbers选项,可以在列出规则的时候显示行号,这在添加单独的规则时很有用
2.2恢复设置默认配置。
在进行测试练习时,如果因为误操作等练习的测试,需要恢复默认配置规则时,保证使服务器服务器快速恢复到可使用状态。以下命令直接复制粘贴即可
iptables -F #清空filter表
iptables -X #清空用户自定义的链
iptables -t nat -F #清空nat表
iptables -t nat -X #清空自定义的链
iptables -t mangle -F #清空mangle表
iptables -t mangle -X #清空自定义的链
iptables -t raw -F #清空raw表
iptables -t raw -X #清空自定义的链
iptables -t security -F #清空security表
iptables -t security -X #清空自定义的链
iptables -P INPUT ACCEPT #设置filter表的INPUT链默认都允许
iptables -P FORWARD ACCEPT #设置filter表的FORWARD链默认都允许
iptables -P OUTPUT ACCEPT #设置出去的数据包默认都允许
2.3建立一个基本的防火墙规则
这种类型的防火墙需要一些基本策略来保证一些基本功能可用,所以下面的一些规则也是需要的
Iptables -A INPUT-p icmp--icmp-type any-j ACCEPT
#允许icmp包进入。如果确认不需要icmp通信,此条可以不写
Iptables -A OUTPUT-p icmp--icmp any-j ACCEPT
#允许icmp包出去
Iptables -A INPUT-s localhost-d localhost-j ACCEPT
#允许本地数据包出
Iptables -A OUTPUT-s localhost-d localhost-j ACCEPT
#允许本地数据包入
Iptables -A INPUT-m state--state ESTABLISHED,RELATED-j ACCEPT
#允许已经建立和相关的数据包进入
Iptables -A OUTPUT-m state--state ESTABLISHED,RELATED-j ACCEPT
#允许已经建立和相关的数据包出去
完成上面的基本策略后,现在需要考虑一些特定策略了,如果是一台Web服务器的话,典型的需要是能访问80端口,、所以需要允许80端口的访问。命令如下
Iptables -A INPUT-p tcp--dport 80-j ACCEPT
此时你会发现依然打开不了Web服务器的主页(假设你设置好了Apache服务,并应用了以上的防火墙规则),为什么呢?
假设你的计算机是A,服务器是B,从A发送了一个目的地址为B、目的端口是80的数据包。服务器B收到这个数据包时发现该数据包匹配INPUT链规则,所以这个包可以正常的进入服务器B;然后服务器B在给A回包时,回包会进入本地的OUTPUT链—但是OUTPUT链默认是DROP所有包的,而且没有定义相关允许策略,回包无法出去,于是造成了整个访问的过程不完整。所以就需要下面的命令。
Iptables -A OUTPUT-m state--state ESTABLISHED,RELATED-j ACCEPT
现在再试试访问Web服务器,一定是成功的。这条命令中使用了状态跟踪模块,意思是对能建立完整的连接以及为了维持该连接需要打开的其他连接所产生的数据包都是可以通过防火墙的OUTPUT链。如果需要允许该服务器访问其他的Web服务器,只要打开让数据出去的80端口就可以了,具体命令如下
Iptables -A OUTPUT-p tcp-m state--state NEW--dport 80 -j ACCEPT
Iptables -A INPUT-m state--state ESTABLISHED,RELATED-j ACCEPT
如果此时尝试使用服务器访问某个域名,比如www.baidu.com,则是不能访问到页面的。需要考虑一下使用域名访问网站需要经历什么过程-域名解析。因为服务器访问该域名之前需要先解析出它的IP地址,所以防火墙必须允许域名解析的数据包出去,使用如下的命令就可以了。
Iptables -A OUTPUT-p udp--dport 53-j ACCEPT
以下是一些常见的需要打开的端口,可以参考设置。
#由于管理需要ssh到这台服务器,则需要打开22号端口
Iptables -A IPUT-p tcp-dport 22-j ACCEPT
#如果只允许一个固定的IP能ssh到该服务器的话,上面的语句需要改为
Iptables -A INPUT-p tcp--dport 22-s 192.168.1.10-j ACCEPT
#可能还需要从该服务器ssh到别的服务器
Iptables -A OUTPUT-p tcp--dport 22-j ACCEPT
2.4创建脚本
至此,一个简单的iptables防火墙就可以使用了,最后将以上过程脚本化,如下所示
#!/bin/bash
#DEFINE VARIABLES
HTTP_PORT=80
SECURE_HTTP_PORT=443
SSH_PORT=22
DNS_PORT=53
ALLOWED_IP=192.168.1.10
IPTABLES=/sbin/iptables
#FLUSH IPTABLES
$IPTABLES-F
$IPTABLES-X
#DEFINE DEFAULT ACTION
$IPTABLES-P INPUT DROP
$IPTABLES-P OUTPUT DROP
#DEFINE INPUT CHAINS
$IPTABLES-A INPUT-p icmp--icmp-type any-j ACCEPT
$IPTABLES-A INPUT-s localhost-d localhost-j ACCEPT
$IPTABLES-A INPUT-m state--state ESTABLISHED,RELATED-j ACCEPT
$IPTABLES-A INPUT-p tcp--dport $SSH_PORT-j ACCEPT
#DEFINE OUTPUT CHAINS
$IPTABLES-A OUTPUT-p icmp--icmp any-j ACCEPT
$IPTABLES-A OUTPUT-s localhost-d localhost-j ACCEPT
$IPTABLES-A OUTPUT-m state--state ESTABLISHED,RELATED-j ACCEPT
$IPTABLES-A OUTPUT-p tcp-m state--state NEW--dport $HTTP_PORT -j ACCEPT
$IPTABLES-A OUTPUT-p tcp--dport $SECURE_HTTP_PORT-j ACCEPT
$IPTABLES-A OUTPUT-p udp--dport $DNS_PORT-j ACCEPT
$IPTABLES-A OUTPUT-p tcp--dport $SSH_PORT-j ACCEPT
3常用命令实操
3.1列出所有链的规则(默认为filter表):
[root@rhel ~]# iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT all -- anywhere anywhere state RELATED, ESTABLISHED
ACCEPT icmp-- anywhere anywhere
ACCEPT all -- anywhere anywhere
ACCEPT tcp -- anywhere anywhere state NEW tcp dpt:ssh
REJECT all -- anywhere anywhere reject-with icmp-host-prohibited
Chain FORWARD (policy ACCEPT)
target prot opt source destination
REJECT all -- anywhere anywhere reject-with icmp-host-prohibited
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
3.2将IP地址和端口号以数字格式显示列出所有链的规则:
[root@rhel ~]# iptables -nL
Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 state RELATED, ESTABLISHED
ACCEPT icmp-- 0.0.0.0/0 0.0.0.0/0
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 state NEW tcp dpt:22
REJECT all -- 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited
Chain FORWARD (policy ACCEPT)
target prot opt source destination
REJECT all -- 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
3.3详细列出所有链的规则:
[root@rhel ~]# iptables -vL
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
978700 ACCEPT all -- any any anywhere anywhere state RELATED, ESTABLISHED
0 0 ACCEPT icmp-- any any anywhere anywhere
4240 ACCEPT all -- lo any anywhere anywhere
1 52 ACCEPT tcp -- any any anywhere anywhere state NEW tcp dpt:ssh
1038185 REJECT all -- any any anywhere anywhere reject-with icmp-host-prohibited
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 REJECT all -- any any anywhere anywhere reject-with icmp-host-prohibited
Chain OUTPUT (policy ACCEPT 123 packets, 11761 bytes)
pkts bytes target prot opt in out source destination
3.4列出INPUT链的规则
[root@rhel ~]# iptables -L INPUT
Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT all -- anywhere anywhere state RELATED, ESTABLISHED
ACCEPT icmp-- anywhere anywhere
ACCEPT all -- anywhere anywhere
ACCEPT tcp -- anywhere anywhere state NEW tcp dpt:ssh
REJECT all -- anywhere anywhere reject-with icmp-host-prohibited
3.5显示所有链的规则
[root@rhel ~]# iptables -S
-P INPUT ACCEPT
-P FORWARD ACCEPT
-P OUTPUT ACCEPT
-A INPUT -m state --state RELATED, ESTABLISHED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 22-j ACCEPT
-A INPUT -j REJECT --reject-with icmp-host-prohibited
-A FORWARD -j REJECT --reject-with icmp-host-prohibited
3.6清除INPUT链的所有规则。
[root@rhel ~]# iptables -F INPUT
[root@rhel ~]# iptables -nvL #查看时已经没有任何规则
Chain INPUT (policy ACCEPT 6 packets, 384 bytes)
pkts bytes target prot opt in out source destination
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 4 packets, 368 bytes)
pkts bytes target prot opt in out source destination
#当清理之后,可以看到 INPUT 、FORWARD、OUTPUT默认策略都是ACCEPT,也就是说默认当前所有发往本机的报文,都将放行。
3.7将所有链中的规则的包字节计数器清零。
[root@rhel ~]# iptables -Z
3.8将INPUT链中的规则的包字节计数器清零。
[root@rhel ~]# iptables -Z INPUT
3.9将INPUT链中的1号规则的包字节计数器清零。
[root@rhel ~]# iptables -Z INPUT 1
3.10在INPUT链上插入规则,协议为tcp,目标端口号是23,规则号是1
[root@rhel ~]# iptables -I INPUT 1-p tcp --dport 23
[root@rhel ~]# iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
tcp -- anywhere anywhere tcp dpt:telnet
tcp -- anywhere anywhere tcp dpt:ftp
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
3.11在INPUT链上删除规则号是1的iptables规则
[root@rhel ~]# iptables -D INPUT 1
3.12删除所有的用户自定义链。
[root@rhel ~]# iptables -X
3.13指定协议配置iptables。
[root@rhel ~]# iptables -A INPUT -p tcp -j ACCEPT
[root@rhel ~]# iptables -A INPUT -p udp -j ACCEPT
3.14指定ICMP类型配置iptables。
[root@rhel ~]# iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
[root@rhel ~]# iptables -A OUTPUT -p icmp --icmp-type echo-reply -j ACCEPT
[root@rhel ~]# iptables -A INPUT -p icmp --icmp-type 8-j ACCEPT
3.15指定IP地址配置iptables。
[root@rhel ~]# iptables -A INPUT -s 192.168.0.5-j ACCEPT
[root@rhel ~]# iptables -A INPUT -s 192.168.0.0/24-j ACCEPT
3.16指定接口配置iptables。
[root@rhel ~]# iptables -A INPUT -i eth0-j ACCEPT
[root@rhel ~]# iptables -A FORWARD -o eth0-j ACCEPT
[root@rhel ~]# iptables -A FORWARD -o ppp+ -j ACCEPT
3.17指定端口号配置iptables。
[root@rhel ~]# iptables -A INPUT -p tcp --sport www -j ACCEPT
[root@rhel ~]# iptables -A INPUT -p tcp --sport 80-j ACCEPT
[root@rhel ~]# iptables -A INPUT -p tcp --dport 53-j ACCEPT
[root@rhel ~]# iptables -A INPUT -p tcp --sport 22:80-j ACCEPT
3.18指定IP碎片配置iptables。
[root@rhel ~]# iptables -A FORWARD -p tcp -s 192.168.0.0/24-d 192.168.1.200--dport 80-j ACCEPT
[root@rhel ~]# iptables -A FORWARD -f -s 192.168.0.0/24-d 192.168.1.200-j ACCEPT
3.19指定TCP标记配置iptables。
[root@rhel ~]# iptables -A FORWARD -p tcp --tcp-flags ALL NONE -j ACCEPT
[root@rhel ~]# iptables -A FORWARD -p tcp --tcp-flags ALL SYN, ACK -j ACCEPT
[root@rhel ~]# iptables -A FORWARD -p tcp --tcp-flags SYN, ACK, FIN, RST SYN -j ACCEPT
3.20保存和恢复规则通过命令行添加规则
配置文件不会自动改变,所以必须手动保存,执行以下命令:
iptables-save > /etc/iptables/iptables.rules
修改配置文件后,需要重新加载:
iptables-restore < /etc/iptables/iptables.rules
4.实用实例
需求是先只开放Web服务,然后添加内网为白名单,这适用于大部分用户,规则如下:
iptables -F #清空filter表
iptables -X #清空用户自定义的链
iptables -t nat –F #清空nat表
iptables -t nat -X #清空自定义的链
iptables -t mangle -F #清空mangle表
iptables -t mangle -X #清空自定义的链
iptables -t raw -F #清空raw表
iptables -t raw -X #清空自定义的链
iptables -t security -F #清空security表
iptables -t security -X #清空自定义的链
iptables -P INPUT DROP #设置filter表的INPUT链默认丢弃任何数据包
iptables -P FORWARD DROP #设置filter表的FORWARD链丢弃任何数据包
iptables -P OUTPUT ACCEPT #设置出去的数据包默认都允许
#设置连接状态为ESTABLISHED,RELATED的数据允许
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -m state --state INVALI -j DROP
#连接状态为INVALI的数据包丢弃
iptables -A INPUT -i lo -j ACCEPT #允许回环地址通信
iptables -A INPUT -p icmp -j ACCEPT #允许icmp协议进来
iptables -A INPUT -p tcp -m multiport --dports 80,443 -j ACCEPT
#开放tcp协议80,443端口
iptables -A INPUT -s 192.168.18.0/24 -j ACCEPT #添加内网地址为白名单
依次执行上述命令,最后保存iptables-save>/etc/iptables/iptables.rules规则。
5. iptables防火墙初始化的注意事项(避免把自己锁在外面)
在跟一些系统管理员进行交流时,我发现大家经常遇到的一个问题就是:误操作iptables而将自己也拦截在机器之外了,没办法只有去机房重启iptables。对于这个问题也是有办法解决的,特推荐给大家,建议大家学习参考。我们可以配置一计划任务Crontab,每5分钟运行一次,即**/5***/etc/init.d/iptables stop;,这样即使你的脚本存在错误设置(或丢失的)规则时,也不至于将你锁在计算机外而无法返回与计算机的连接,可让你放心大胆地调试你的脚本。鉴于许多同事在学习及调试iptables脚本时也是用自己内部的机房,所以推荐用此方法,免得受进出机房之苦。