在Internet中,通过架设各种服务器为用户提供各种网络服务,怎样保护这些服务器,过滤恶意的访问、入侵呢?这里主要介绍Linux系统中的防火墙——netfilter和iptables,包括防火墙的结构和匹配流程,以及如何编写防火墙规则
Linux防火墙基础
Linux的防火墙体系主要工作在网络层,针对TCP/IP数据包进行过滤和限制,属于典型的包过滤防火墙。它基于内核编码实现,具有非常稳定的性能和高效率,也因此得到了广泛的应用。netfilter和iptables都可以用来指Linux防火墙,它们的区别如下:
netfilter:在Linux内核中实现防火墙的内部结构,不以文件或程序的形成存在,属于“内核态”的防火墙功能体系
iptables:用来管理Linux防火墙的命令程序,通常位于/sbin/iptables目录下,属于“用户态”的防火墙管理体系
1. iptables中的表、链结构(四表五链)
为了更加方便地组织和管理防火墙规则,iptables采用了“表”和“链”的分层结构,如下图所示:
(1)规则表(四表)
iptables管理中四个不同的规则表,其功能分别由独立的内核模块实现。表的名称、包含的链及用途如下:
filter表:用来对数据包进行过滤,确定是否放行,对应的内核模块为iptables_filter,表中包含三个链,即INPUT、OUTPUT、FORWARD
nat表:网络地址转换,修改数据包中的源、目标IP地址或端口,内核模块为iptables_nat,表中包含三个链,即PREROUTING、POSTROUTING、OUTPUT
mangle表:为数据包设置标记,以实现流量整形、策略路由等高级功能,内核模块为iptables_mangle,表中包含五个链,即PREROUTING、POSTROUTING、INPUT、OUTPUT、FORWARD
raw表:确定是否对该数据包进行状态跟踪,内核模块为iptables_raw,表中包含两个链,即OUTPUT、PREROUTING
(2)规则链(五链)
在处理数据包时,根据防火墙规则的不同介入时机,默认划分为五个不同的规则链,具体如下:
INPUT:处理入站数据包
OUTPUT:处理出站数据包
FORWARD:处理转发数据包
POSTROUTING链:在进行路由选择后处理数据包
PREROUTING链:在进行路由选择前处理数据包
2. 数据包过滤的匹配顺序
iptables管理着四表五链,各种规则依次存放在链中,那么当一个数据包到达防火墙时,优先使用哪个表,哪个链中的规则?
(1)规则表之间的顺序
当数据包抵达防火墙时,应用的顺序为raw——mangle——nat——filter(如果规则同时存在)
(2)规则链之间的顺序
规则链之间的应用顺序取决于数据包的流向,具体如下:
1)入站数据流向:(PREROUTING——INPUT)当外界的数据包到达防火墙时,首先被PREROUTING链处理,然后进行路由选择,如果数据包的目标地址是本机,那么就将其传递给INPUT链进行处理,通过以后交给上层的应用程序进行响应
2)转发数据流向:(PREROUTING——FORWARD——POSTROUTING)当外界的数据包到达防火墙时,首先被PREROUTING链处理,然后进行路由选择,如果数据包的目标地址是其他外部地址,则将其传递给FORWARD链进行处理,最后交给POSTROUTING链进行处理
3)出站数据流向:(OUTPUT——POSTROUTING)防火墙本机向外部发送数据包时,首先被OUTPUT链处理,然后进行路由选择,再交给POSTROUTING链进行处理
(3)规则链内部的各条防火墙规则匹配顺序
当数据包经过每条规则链时,按顺序依次检查,匹配即停止(LOG策略例外),若找不到相匹配的规则,则按该链的默认策略处理
编写防火墙规则
1. iptables命令基本语法
基本的命令格式如下:
iptables [-t 表名] 管理选项 [链名] [匹配条件] [-j 控制类型]
其中
表名、链名:指定iptables命令所操作的表和链,未指定时默认使用filter表
管理选项:表示iptables规则的操作方式,如增加、删除、插入、查看等
匹配条件:指定要处理的数据包特征,不符合指定条件的数据包将不会处理
控制类型:指定数据包的处理方式,如允许、拒绝、丢弃等,常用的几种控制类型如下
(1)ACCEPT:允许数据包通过
(2)DROP:直接丢弃数据包,不给任何回应信息
(3)REJECT:拒绝数据包通过,必要时给数据包发送端一个响应信息
(4)LOG:在/var/log/messages文件中记录日志信息,然后将数据包传递给下一条规则,不必遵循“匹配即停止”的规则
2. iptables命令的基本操作
(1)添加新的规则
-A:在链的末尾追加一条规则
-I:在链的开头(或指定序号)插入一条规则
1
2
3
|
[root@localhost ~]
# iptables -A INPUT -p tcp -j ACCEPT //在filter表INPUT链的末尾添加一条规则,允许TCP协议的数据包通过
[root@localhost ~]
# iptables -I INPUT -p udp -j ACCEPT //在filter表INPUT链的首行添加一条规则,允许UDP协议的数据包通过
[root@localhost ~]
# iptables -I INPUT 2 -p icmp -j ACCEPT //在filter表INPUT链的第二行添加一条规则,允许icmp协议的数据包通过
|
(2)查看规则列表
-L:列出所有的规则条目,如未指定链名,则列出表中所有链
-n:以数字形式显示地址、端口等信息
-v:以更详细的方式显示规则信息
--line-numbers:查看规则时,显示规则的序号
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
[root@localhost ~]
# iptables -L INPUT --line-numbers //查看filter表INPUT链的所有规则,并显示规则序号
Chain INPUT (policy ACCEPT)
num target prot opt
source
destination
1 ACCEPT udp -- anywhere anywhere
2 ACCEPT icmp -- anywhere anywhere
3 REJECT icmp -- anywhere anywhere reject-with icmp-port-unreachable
4 ACCEPT tcp -- anywhere anywhere
[root@localhost ~]
# iptables -nL INPUT //以数字形式查看filter表INPUT链的所有规则
Chain INPUT (policy ACCEPT)
target prot opt
source
destination
ACCEPT udp -- 0.0.0.0
/0
0.0.0.0
/0
ACCEPT icmp -- 0.0.0.0
/0
0.0.0.0
/0
REJECT icmp -- 0.0.0.0
/0
0.0.0.0
/0
reject-with icmp-port-unreachable
ACCEPT tcp -- 0.0.0.0
/0
0.0.0.0
/0
|
(3)删除、清空规则
-D:删除链内指定序号(或内容)的一条规则
-F:清空所有的规则
1
2
3
4
5
6
|
[root@localhost ~]
# iptables -D INPUT 3 //删除filter表INPUT链的第三条规则
[root@localhost ~]
# iptables -F INPUT //清空filter表INPUT链所有的规则
[root@localhost ~]
# iptables -F //清空filter表
[root@localhost ~]
# iptables -t nat -F //清空nat表
[root@localhost ~]
# iptables -t mangle -F //清空mangle表
[root@localhost ~]
# iptables -t raw -F //清空raw表
|
(4)设置默认策略
-P:为指定的链设置默认规则
当找不到任何一条策略匹配数据包的规则时,将执行默认策略,默认策略的控制类型为ACCEPT、DROP
1
2
|
[root@localhost ~]
# iptables -P FORWARD DROP //将filter表FORWARD链的默认策略设为丢弃
[root@localhost ~]
# iptables -P OUTPUT ACCEPT //将filter表OUTPUT链的默认策略设为允许
|
当使用-F清空链时,默认策略不受影响;若要修改默认策略,必须通过-P重新设置
3. 规则的匹配条件
根据数据包的各种特性,结合iptables模块,匹配条件的设置包括三大类:通用匹配、隐含匹配、显式匹配
(1)通用匹配
也称为常规匹配,可以独立使用,不依赖于其他条件和扩展模块,包括协议匹配、地址匹配、网络接口匹配
1)协议匹配:“-p 协议名”,用来检查数据包所使用的网络协议,如tcp、udp、icmp、all(所有IP数据包)等
1
2
|
[root@localhost ~]
# iptables -I INPUT -p icmp -j DROP //丢弃通过icmp协议访问本机的数据包
[root@localhost ~]
# iptables -A FORWARD ! -p icmp -j ACCEPT //允许转发除了icmp协议之外的数据包
|
2)地址匹配:“-s 源地址”“-d 目标地址”,用来检查数据包的源地址和目标地址,不建议使用主机名、域名(解析过程影响效率)
1
2
|
[root@localhost ~]
# iptables -A FORWARD -s 192.168.1.11 -j REJECT //拒绝转发源地址为192.168.1.11的数据
[root@localhost ~]
# iptables -I INPUT -s 10.20.30.0/24 -j DROP //丢弃源网段为10.20.30.0/24访问本机的数据
|
3)网络接口匹配:“-i 入站网卡”“-o 出站网卡”,用来检查数据包从防火墙的哪一个接口进入或发出
1
2
3
|
[root@localhost ~]
# iptables -A INPUT -i eth1 -s 192.168.0.0/16 -j DROP //丢弃从外网访问本机且防火墙为私有地址的数据包
[root@localhost ~]
# iptables -A INPUT -i eth1 -s 10.0.0.0/8 -j DROP
[root@localhost ~]
# iptables -A INPUT -i eth1 -s 172.16.0.0/12 -j DROP
|
(2)隐含匹配
要求以指定的协议为前提条件,相当于子条件,因此无法独立使用,常见的隐含匹配包括端口匹配、TCP标记匹配、ICMP类型匹配
1)端口匹配:“--sport 源端口”“--dport 目的端口”,用来检查数据包的源端口、目标端口,可以使用单个端口和以冒号分隔的端口范围,不能使用多个不连续的端口
1
2
3
|
[root@localhost ~]
# iptables -A FORWARD -s 192.168.4.0/24 -p udp --dport 53 -j ACCEPT //允许为网段192.168.4.0/24网段转发DNS查询数据包
[root@localhost ~]
# iptables -A FORWARD -d 192.168.4.0/24 -p udp --sport 53 -j ACCEPT
[root@localhost ~]
# iptables -A INPUT -p tcp --dport 20:21 -j ACCEPT //允许通过访问本机FTP服务的数据包
|
2)TCP标记匹配:“--tcp-flags 检查范围 被设置的标记”,用来检查TCP数据包的特定标志,如SYN、ACK、FIN、RST等
1
2
3
|
[root@localhost ~]
# iptables -A INPUT -p tcp --tcp-flags ALL FIN,URG,PSH -j DROP //防止Xmas扫描
[root@localhost ~]
# iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP //防止TCP Null扫描
[root@localhost ~]
# iptables -A INPUT -p tcp --tcp-flags SYN,ACK SYN,ACK -m state --state NEW -j DROP //拒绝TCP标记为SYN/ACK,但连接状态为NEW的数据包,防止ACK欺骗
|
3)ICMP类型匹配:“--icmp-type ICMP类型”,用来检查ICMP数据包的类型,如Echo-Request(代码8)、Echo-Reply(代码0)、Destination-Unreachable(代码3)分别对应ICMP协议的请求、回显、主机不可达
1
2
3
4
5
|
[root@localhost ~]
# iptables -A INPUT -p icmp --icmp-type 8 -j DROP //禁止从其他主机ping本机,但允许本机ping其他主机
[root@localhost ~]
# iptables -A INPUT -p icmp --icmp-type 0 -j ACCEPT
[root@localhost ~]
# iptables -A INPUT -p icmp --icmp-type 3 -j ACCEPT
[root@localhost ~]
# iptables -A INPUT -p icmp -j DROP
[root@localhost ~]
# iptables -p icmp -h //查看可用的ICMP协议类型
|
(3)显式匹配
要求有额外的内核模块提供支持,必须手动以“-m 模块名称”的形式调用相应的模块,然后设置匹配条件。常见的显式匹配包括多端口匹配、IP范围匹配、MAC地址匹配、状态匹配
1
|
[root@localhost ~]
# lsmod | grep xt_ //查看相关的内核扩展模块
|
1)多端口匹配:“-m multiport --sport 源端口列表”“-m multiport --dport 目的端口列表”,多端口以逗号分隔
1
|
[root@localhost ~]
# iptables -A INPUT -p tcp -m multiport --dport 25,80,110,143 -j ACCEPT //允许本机开放25、80、110、143端口,以便提供电子邮件服务
|
2)IP范围匹配:“-m iprange --src-range IP范围”“-m iprange --drc-range IP范围”,检查数据包的源、目的IP地址范围
1
|
[root@localhost ~]
# iptables -A FORWARD -p tcp -m iprange --src-range 192.168.4.21-192.168.4.28 -j ACCEPT //允许转发192.168.4.21与192.168.4.28之间的TCP数据包
|
3)MAC地址匹配:“-m mac --mac-source MAC地址”,用于检查数据包的源MAC地址,只适用于网络内部
1
|
[root@localhost ~]
# iptables -A INPUT -m mac --mac-source 00:0c:29:c0:55:3f -j DROP //禁止其MAC地址访问本机的任何应用
|
4)状态匹配:“-m state --state 连接状态”,基于iptables的状态跟踪机制用来检查数据包的连接状态,如NEW(与任何连接无关的)、ESTABLISHED(响应请求或以建立连接的)、RELATED(与已有连接有相关性的)
1
2
3
4
5
|
[root@localhost ~]
# iptables -I INPUT -p tcp -m state --state NEW -p tcp ! --syn -j DROP //禁止转发与正常TCP连接无关的--syn请求数据包,如伪造的网络攻击数据包
[root@localhost ~]
# iptables -P INPUT DROP //只开放本机的web服务,但对发给本机的TCP应答数据包予以放行,其他入站数据包都丢弃
[root@localhost ~]
# iptables -I INPUT -p tcp -m multiport --dport 80 -j ACCEPT
[root@localhost ~]
# iptables -I INPUT -p tcp -m state --state ESTABLISHED -j ACCEPT
|