防火墙规则保存
iptables提供了两个很有用的工具用来处理大规则集: iptables-save和iptables-restore,它们把规则存入一个与标准脚本代码只有细微查别的特殊格式的文件中,或从中恢复规则。
使用iptables-save和iptables-restore的一个最重要的原因是,它们能在相当程度上提高装载、保存规则的速度。使用脚本更改规则的问题是,改动每个规则都要调运命令iptables,而每一次调用iptables,它首先要把Netfilter内核空间中的整个规则集都提取出来,然后再插入或附加,或做其他的改动,最后,再把新的规则集从它的内存空间插入到内核空间中。对于一个很大的规则集,如果用脚本来设置,这会花费时间多一些。
使用方法如下:
1 2 3 4 5 6 7 8 |
# 默认保存在/etc/sysconfig/iptables文件. $ service iptables save # 导出规则到特定文件. $ iptables-save > /etc/sysconfig/iptables.20140727 # 导入规则文件. $ iptables-restore < /etc/sysconfig/iptables.20140727 |
PS:iptables防火墙每一次关闭时都会清空规则,开启时都会应用/etc/sysconfig/iptables文件中设置的规则条目。另外对于iptables模块更详细的用户可以参考官网。
Iptables语法
1 |
iptables [-t table] [option [chain] [number]] [match] [-j target/jump] |
对于iptables语法使用很容易理解,主要分为以下四步:
一是“[-t TABLE]”指定要操作的表
二是“[option [chain] [number]]”一些选项用来操作链或查看规则
三是“[match]”针对某表中某链写一些匹配规则
四是“[-j target/jump]”针对某表中某链匹配到的规则做出处理
理解了Iptables语法的组成之后,然后就可以针对每一步可用的操作有哪些,然后将这些操作组合起来就完成了一条完整的iptables规则,下面针对以上四步详细介绍。
[-t TABLE]
1 2 3 4 |
raw mangle net filter |
PS:需要使用-t指定规则要应用的表,但是默认使用filter表,所以说如果就是要使用filter表的话就不需要[-t filter]指定表了。
[option <chain> [number]]
管理规则
1 2 3 4 5 6 7 |
-A <chain> #指定链的末尾添加一条新的规则. -I <chain> [number] #在指定链中插入一条规则,未指定序号时默认在链首插入. -R <chain> [number] #修改、替换指定链中的某一条规则,需指定链序号. -D <chain> [number] #删除指定链中的某一条规则,需指定链序号. -F #清空指定表的所有规则链,但是不会改变表默认规则. -F <chain> #清空指定表的指定规则链. -P <chain> <target> #指定链的默认处理动作,不用指定-j. |
管理链
1 2 3 4 |
-N chain_name #自定义一个新的空链. -X chain_name #删除一个自定义的空链. -E old_chain_name new_ chain_name #重命名自定义链. -Z #置零指定链中所偶规则的计数器(数据包匹配的次数和匹配的总流量). |
查看规则
1 2 3 4 5 6 |
-L #列出指定链中的所有规则、不指定链名则列出表中的所有链. -L -n #使用数字形式显示主机地址和端口号. -v | -vvv #查看规则列表时显示详细的信息. -x #显示计数器的精确值(数据包匹配的次数和匹配的总流量). -h #查看命令帮助信息. --line-numbers #查看规则序列号. |
<CHAIN>
1 2 3 4 5 |
INPUT OUTPUT FORWARD PREROUTING POSTROUTING |
[match]
通用匹配:就是无论我们使用的是何种协议,也不管我们又装入了匹配的何种扩展,通用匹配都使可用的。也就是说,它们可以直接使用,而不需要什么前提条件,在后面你会看到,有很多匹配操作是需要其他的匹配作为前提的。
1 2 3 4 5 |
-s [host | net] #指定源地址. -d [host | net] #指定目标地址. -p {tcp | udp | icmp} #指定协议. -i eth# #指定数据报文流入的接口(可用于定义标准的链:PREROUTING,INPUT,FORWARD). -o eth# #指定数据报文流出的接口(可用于定义标准的链:OUTPUT,POSTROUTING,FORWARD). |
隐含匹配:就是不用特别指明由哪个模块进行的扩展,这种匹配操作是自动地或隐含地装载入内核的。例如我们使用-p tcp 时,不需再装入任何东西就可以匹配只有IP包才有的一些特点。现在有三种隐含的匹配针对三种不同的协 议,即TCP matches,UDP matches和 ICMP matches。它们分别包括一套只适用于相应协议的判别标准。
① tcp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
# 匹配TCP协议源端口80,端口可任意修改. -p tcp --sport 80 # 匹配TCP协议目标端口80,端口可任意修改. -p tcp --dport 80 # 表示匹配SYN标记被设置,而FIN和ACK标记没有设置的包. -p tcp --tcp-flags SYN,FIN,ACK # 表示匹配那些FIN和ACK标记被设置,而SYN标记没有设置的包. -p tcp --tcp-flags ! SYN,FIN,ACK SYN # 表示匹配所有标记都未置1的包. -p tcp --tcp-flags ALL NONE |
② udp
1 2 3 4 5 |
# 匹配UDP协议源端口22,端口可任意修改. -p udp --sport 22 # 匹配UDP协议目标端口22,端口可任意修改. -p udp --dport 22 |
③ icmp
1 2 3 4 5 |
# 8表示Echo request——回显请求(Ping请求). -p icmp --icmp-type 8 # 0表示Echo Reply——回显应答(Ping应答). -p icmp --icmp-type 0 |
显示匹配:就是必须指明由哪个模块进行的扩展,在iptables中必须用-m或–match装载,比如要使用状态匹配就必须使用-m state。有些匹配还需要指定协议,有些就不需要,比如连接状态就不要。常用模块如下:
1)State模块
状态匹配扩展要有内核里的连接跟踪代码的协助,因为它是从连接跟踪机制中得到包的状态的。这样我们就可以了解连接所处的状态。它几乎适用于所有的协议,包括那些无状态的协议,如ICMP和UDP。具体原理看连接跟踪部分介绍。
1 2 3 4 5 |
# 匹配NEW状态数据包和已建立连接的数据包,注意两个状态都要给才能正常通信,因为第一次连接是NEW,第二次连接就是ESTABLISHED. -m state --state NEW,ESTABLISHED # 匹配复杂协议使用的,如FTP服务,具体原理看前面的状态机制. -m state --state RELATED,ESTABLISHED |
实例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
$ iptables -P INPUT REJECT $ iptables -P OUTPUT REJECT $ iptables -A INPUT -d 192.168.10.1 -p tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT # 在INPUT链上对于80端口允许SYN数据包和已建立连接的数据包通过,在OUTPUT链上本地只要是已建立连接的都允许出去. $ iptables -A OUTPUT -s 192.168.10.1 -m state --state ESTABLISHED -j ACCEPT # 对于复杂协议FTP允许通过本地防火墙,需要装载ip_nat_ftp和ip_conntrack_ftp两个模块,如下: $ iptables -A INPUT -d 192.168.10.1 -m state --state RELATED,ESTABLISHED -j ACCEPT $ iptables -A OUTPUT -s 192.168.10.1 -m state --state RELATED,ESTABLISHED -j ACCEPT # 对于ftp模块,在Centos6上还是依然可以兼容Centos5上的风格. $ vim /etc/sysconfig/iptables-config IPTABLES_MODULES=”nf_nat_ftp nf_conntrack_ftp” 或 IPTABLES_MODULES=”ip_nat_ftp ip_conntrack_ftp” |
2)Multiport模块:多端口匹配
1 2 3 4 5 6 7 8 |
# 离散目标多端口匹配,最多可以指定15个端口,使用时必须有-p tcp或-p udp为前提条件. -m multiport --destination-ports 21,22,80 # 离散源多端口匹配. -m multiport --source-ports 21,22,80 # 离散源和目标多端口匹配,意思就是它匹配的是那种源端口和目的端口是同一个端口的包,比如:端口80到端口80的包. -m multiport --ports 21,22,80 |
3)Iprange模块:IP地址范围匹配
1 2 3 4 5 |
# 源地址匹配. -m iprange --src-range 172.16.16.1-172.16.16.100 # 目标地址匹配. -m iprange --dst-range 172.16.16.1-172.16.16.100 |
实例
1 2 3 4 5 |
# 允许源IP地址范围192.168.1.5-192.168.1.124的包进行转发. $ iptables -A FORWARD -m iprange --src-range 192.168.1.5-192.168.1.124 -j ACCEPT # 允许目标IP地址范围10.0.0.0-10.255.255.255的包进行转发. $ iptables -A FORWARD -m iprange --dst-range 10.0.0.0-10.255.255.255 -j ACCEPT |
4)Mac模块:可以做到根据MAC地址做限制。
1 |
-m mac --mac-source 00:dd:33:dd:33:33 |
#基于包的MAC源地址匹配包,地址格式只能是XX:XX:XX:XX:XX:XX,当然它也可以用英文感叹号取反,如–mac- source ! 00:00:00:00:00:01,意思很简单了,就是除此之外的地址都可接受嘛。注意,因为MAC addresses只用于Ethernet类型的网络,所以这个match只能用于Ethernet接 口。而且,它还只能在PREROUTING,FORWARD 和INPUT链里使用。
实例
1 2 3 4 5 |
# 只允许MAC地址00:0F:EA:25:51:37的主机收发邮件. $ iptables -I FORWARD -m mac --mac-source 00:0F:EA:25:51:37 -j DROP $ iptables -I FORWARD -m mac --mac-source 00:0F:EA:25:51:37 -p udp --dport 53 -j ACCEPT $ iptables -I FORWARD -m mac --mac-source 00:0F:EA:25:51:37 -p tcp --dport 25 -j ACCEPT $ iptables -I FORWARD -m mac --mac-source 00:0F:EA:25:51:37 -p tcp --dport 110 -j ACCEPT |
5)String模块:对报文中的应用层数据做字符串模式匹配检测,字符串匹配可以做内容过滤。
实例
1 2 |
$ iptables -I FORWARD -m string --algok mp --string "色情" -j DROP $ iptables -I FORWARD -p tcp --sport 80 -m string --algok mp --string "广告" -j DROP |
拒绝匹配到的字符串,一般使用在FORWARD上面,支持中文(mp是字符串匹配算法,还有一种算法kmp,两种都差不度)。
6)Time模块
做时间匹配使用的,允许你过滤基于包到达时间/日期(这个到达时间和日期是指这个netfilter运行的机器上的)或者发出时间/日期(本地产生的信息包)。
1 2 3 4 5 |
-m time --timestart 00:00 #起始时间. -m time --timestop 00:00 #结束时间. -m time --days listofdays #格式Mon,Tue,Wed,Thu,Fri,Sat,Sun;默认每天. -m time --datestart #起始日期. -m time --datestop date #结束日期. |
实例
1 2 3 4 5 |
# 表示周一到周五每天早上8点到下午6点生效. iptables -A INPUT -m time --timestart 8:00 --timestop 18:00 --days Mon,Tue,Wed,Thu,Fri # 表示每个周一早上8点到下午6点生效,直到2016年结束. iptables -A INPUT -m time --timestart 8:00 --timestop 18:00 --days Mon --date-stop 2016 |
7)Layer7模块
七层过滤模块,能过滤包括电驴,msn,qq等一些列软件,但这个模块没有内置,我们也知道在Linux上面firewall是基于内核模块实现的,所以我们要想起用layer7模块就必须编译内核。
实例
1 2 |
# 七层过滤拒绝QQ协议使用(这个模块默认不支持,后面会特别介绍). $ iptables -A FORWARD -m layer7 --l7proto qq -j DROP |
[-j target/jump]
target/jump决定符合条件的包到何处去,Target和Jump它们唯一的区别是,jump的目标是一个在同一个表内的链,而target的目标是具体的操作。我们会先接触到两个基本的target,就是ACCEPT和DROP。处理动作就是对于规则匹配到的数据库进行处理.
常用Target有以下几种:
-j ACCEPT
#这个target允许规则匹配到的数据包通过。
-j DROP
#这个target直接丢弃规则匹配到的数据包,不会向发送者返回任何信息。在某些情况下,这个target会引起意外的结果,因为它不会向发送者返回任何信息,也不会向路由器返回信息,这就可能会使连接的另一方的sockets因苦等回音而亡。
-j REJECT
#这个target拒绝规则匹配到的数据包,可以向发送者返回一个错误信息。
-j LOG
#这个target是专门用来记录包地有关信息的。这些信息可能是非法的,那就可以用来除错。LOG会返回包的有关细节,如IP头的大部分和其他有趣的信息。这个功能是通过内核的日志工具完成的,一般是syslogd。返回的信息可用dmesg阅读,或者可以直接查看syslogd的日志文件,也可以用其他的什么程序来看。LOG对调试规则有很大的帮助,你可以看到包去了哪里、经过了什么规则的处理,什么样的规则处理什么样的包,等等。当你在生产服务器上 调试一个不敢保证100%正常的规则集时,用LOG代替DROP是比较好的(有详细的信息可看,错误就容易定位、解决了),因为一个小小的语法错误就可能引起严重的连接问题。如果你想使用真正地扩展日志地话,可能会对ULOG target有些兴趣,因为它可以把日志直接记录到MySQL databases或类似的数据库中。另外LOG还有一些–log–evel可选,如下:
-j LOG –log-level debug
#告诉iptables和 syslog使用哪个记录等级,具体日志级别可以看syslog。
-j LOG –log-prefix “INPUT packets”
#告诉iptables在记录的信息之前加上指定的前缀。这样和grep或其他工具一起使用时就容易追踪特定的问题,而且也方便从不同的规则输出,默认存在/var/log/message中。
-j LOG –log-tcp-sequence
#把包的TCP序列号和其他日志信息一起记录下来。TCP序列号可以唯一标识一个包,在重组时也是用它来确定每个分组在包里的位置。
–log-ip-options
#记录IP包头中的字段大小不变的选项。这对一些除错是很有价值的,还可以用来跟踪特定地址的包。
-j SNAT
#这个target是用来做源网络地址转换的,就是重写包的源IP地址。当我们有几个机子共享一个Internet 连接时,就能用到它了。先在内核里打开ip转发功能,然后再写一个SNAT规则,就可以把所有从本地网络出去的包的源地址改为Internet连接的地址了。
-j DNAT
#这个target是用来做目的网络地址转换的,就是重写包的目的IP地址。如果一个包被匹配了,那么和它属于同一个流的所有的包都会被自动转换,然后就可以被路由到正确的主机或网络。DNAT target是非常有用的。比如,你的Web服务器在LAN内部,而且没有可在Internet上使用的真实IP地址,那就可以使用这个target让防火墙把所有到它自己HTTP端口的包转发给LAN内部真正的Web服务器。目的地址也可以是一个范围,这样的话,DNAT会为每一个流随机分配一个地址。因此,我们可以用这个target做某种类型地负载平衡。注意,DANT target只能用在nat表的PREROUTING和OUTPUT链中。
-j REDIRECT
#在防火墙所在的机子内部转发包或流到另一个端口。比如,我们可以把所有去往端口HTTP的包REDIRECT到HTTP proxy(例如squid),当然这都发生在我们自己的主机内部。本地生成的包都会被映射到127.0.0.1。换句 话说,这个target把要转发的包的目的地址改写为我们自己机子的IP。我们在做透明代理(LAN内的机子根 本不需要知道代理的存在就可以正常上网)时,这个target可是起了很大作用的。注意,它只能用在nat表的PREROUTING、OUTPUT链和被它们调用的自定义链里。 REDIRECT只有一个选项“–to-ports”
-j MASQUERADE
#这个target和SNAT target的作用是一样的,区别就是它不需要指定–to-source 。MASQUERADE是被专门设计用于那些动态获取IP地址的连接的,比如,拨号上网、DHCP连接等。如果你有固定的IP地址,还是用SNAT target吧。伪装一个连接意味着,我们自动获取网络接口的IP地址,而不使用–to-source。当接口停用时,MASQUERADE不会记住任何连接。
-j MARK
#这个target用来设置mark值,这个值只能在本地的mangle表里使用,不能用在其他任何地方,就更不用说路由器或另一台机子了。因为mark比较特殊,它不是包本身的一部分,而是在包穿越计算机的过程中由内核分配的和它相关联的一个字段。它可以和本地的高级路由功能联用,以使不同的包能使用不同的队列要求,等等。如果你想在传输过程中也有这种功能,还是用TOS target吧。