3.5 Linux防火墙iptables
在CentOS 7之前的版本均使用iptables,因此本书也介绍iptables的使用。要使用iptables防火墙,必须要先了解TCP/IP网络的基本原理,理解Linux防火墙的工作原理。本节主要介绍Linux防火墙方面的知识。
3.5.1 Linux内核防火墙的工作原理
Linux内核提供的防火墙功能通过netfiter框架实现,并提供了iptables工具配置和修改防火墙的规则。
netfilter的通用框架不依赖于具体的协议,而是为每种网络协议定义一套钩子函数。这些钩子函数在数据包经过协议栈的几个关键点时被调用,在这几个点中,协议栈将数据包及钩子函数作为参数,传递给netfilter框架。
对于每种网络协议定义的钩子函数,任何内核模块都可以对每种协议的一个或多个钩子函数进行注册,实现挂接。这样当某个数据包被传递给netfilter框架时,内核能检测到是否有有关模块对该协议和钩子函数进行了注册。若发现注册信息则调用该模块在注册时使用的回调函数,然后对应模块去检查、修改、丢弃该数据包及指示netfilter将该数据包传入用户空间的队列。
从以上描述可以得知钩子提供了一种方便的机制,以便在数据包通过Linux内核的不同位置上截获和操作处理数据包。
1.netfilter的体系结构
网络数据包的通信主要经过以下相关步骤对应netfilter定义的钩子函数,更多信息可以参考源代码。
- NF_IP_PRE_ROUTING:网络数据包进入系统,经过了简单的检测后,数据包转交给该函数进行处理,然后根据系统设置的规则对数据包进行处理,如果数据包不被丢弃就交给路由函数进行处理。在该函数中可以替换IP包的目的地址,即DNAT。
- NF_IP_LOCAL_IN:所有发送给本机的数据包都要通过该函数的处理,该函数根据系统设置的规则对数据包进行处理,如果数据包不被丢弃就交给本地的应用程序。
- NF_IP_FORWARD:所有不是发送给本机的数据包都要通过该函数进行处理,该函数会根据系统设置的规则对数据包进行处理,若数据包不被丢弃则转到NF_IP_POST_ROUTING进行处理。
- NF_IP_LOCAL_OUT:所有从本地应用程序出来的数据包必须通过该函数的处理,该函数根据系统设置的规则对数据包进行处理,如果数据包不被丢弃就交给路由函数进行处理。
- NF_IP_POST_ROUTING:所有数据包在发给其他主机之前需要通过该函数的处理,该函数根据系统设置的规则对数据包进行处理,如果数据包不被丢弃,就将数据包发给数据链路层。在该函数中可以替换IP包的源地址,即SNAT。
图3.3显示了数据包在通过Linux防火墙时的处理过程。
图3.3 数据包在通过Linux防火墙时的处理过程
2.包过滤
每个函数都可以对数据包进行处理,最基本的操作为对数据包进行过滤。系统管理员可以通过iptables工具来向内核模块注册多个过滤规则,并且指明过滤规则的优先权。设置完以后每个钩子按照规则进行匹配,如果与规则匹配,函数就会进行一些过滤操作,这些操作主要是以下几个:
- NF_ACCEPT:继续正常地传递包。
- NF_DROP:丢弃包,停止传送。
- NF_STOLEN:已经接管了包,不要继续传送。
- NF_QUEUE:排列包。
- NF_REPEAT:再次使用该钩子。
3.包选择
在netfilter框架上已经创建了一个包选择系统,这个包选择工具默认已经注册了3个表,分别是过滤(filter)表、网络地址转换(NAT)表和mangle表。
在调用钩子函数时是按照表的顺序来调用的。例如,在执行NF_IP_PRE_ROUTING时,首先检查filter表,然后检查Mangle表,最后检查NAT表。
过滤(filter)表过滤包而不会改变包,仅仅是过滤的作用,实际上由网络过滤框架来提供NF_IP_FORWARD钩子的输出和输入接口使得很多过滤工作变得非常简单。从图3.3中可以看出,NF_IP_LOCAL_IN和NF_IP_LOCAL_OUT也可以做过滤,但是只是针对本机。
网络地址转换(NAT)表分别服务于两套不同的网络过滤挂钩的包,对于非本地包,NF_IP_PRE_ROUTING和NF_IP_POST_ROUTING挂钩可以完美地解决源地址和目的地址的变更。
NAT表与filter表的区别在于只有新建连接的第1个包会在表中传送,结果将被用于以后所有来自这一连接的包。例如,某一个连接的第1个数据包在这个表中被替换了源地址,那么以后这条连接的所有包都将被替换源地址。
mangle表被用于真正的改变包的信息,mangle表和所有的5个网络过滤的钩子函数都有关。
4.切换至iptables
在正式学习iptables之前,还需要将默认使用的firewalld停止,并让系统将iptables作为默认防火墙。其命令如下:
#关闭并禁用firewalld [root@CentOS ~]# systemctl stop firewalld [root@CentOS ~]# systemctl disable firewalld #启动并启用iptables [root@CentOS ~]# systemctl start iptables [root@CentOS ~]# systemctl enable iptables #如果使用了IPv6,还需要开启ip6tables #启动并启用ip6tables [root@CentOS ~]# systemctl start ip6tables [root@CentOS ~]# systemctl enable ip6tables
使用上述命令之后就可以在CentOS 7.5中使用iptables了。
3.5.2 Linux软件防火墙iptables
iptables工具用来设置、维护和检查Linux内核的IP包过滤规则。filter、NAT和mangle表可以包含多个链(chain),每个链可以包含多条规则(rule)。iptables主要对表(table)、链(chain)和规则(rule)进行管理。
iptables预定义了5个链,分别对应netfilter的5个钩子函数。这5个链分别是INPUT链、FORWARD链、OUTPUT链、PREROUTING链、POSTROUTING链。
iptables指令语法如下:
iptables [-t table] command [match] [-j target/jump]
“-t table”参数用来指定规则表,内建的规则表分别为nat、mangle和filter,当未指定规则表时,默认为filter。各个规则表的功能如下:
- nat:此规则表主要针对PREROUTING和POSTROUTING两个规则链,主要功能为进行源地址或目的地址的网址转换工作(SNAT、DNAT)。
- mangle:此规则表主要针对PREROUTING、FORWARD和POSTROUTING 3个规则链,某些特殊应用可以在此规则表里设定,比如为数据包做标记。
- filter:这个规则表是默认规则表,针对INPUT、FORWARD和OUTPUT 3个规则链,这个规则表主要用来进行封包过滤的处理动作,如DROP、LOG、ACCEPT或REJECT。
iptables的简单用法如【示例3-15】所示。
【示例3-15】
提示
其中,“-t filter”表示该规则作用于filter表,“-A”表示新增规则,“-s”表示IP段选项,“-j”表示指定动作。该规则表示在filter表FORWARD链上新增一条规则,发往192.168.19.0/24网段的包采取丢弃操作。要查看某个表下各个链的信息,可以使用“iptables -nL”。
要使Linux系统成为网络防火墙,当然除了内核支持之外,还需要启用Linux的网络转发功能。
echo 1 > /proc/sys/net/ipv4/ip_forward
若需要在系统启动时就具有该功能,则可将上面的命令写入/etc/rc.d/rc.local文件中。
数据包通过表和链时需要遵循一定的顺序,当数据包到达防火墙时,如果MAC地址符合,就会由内核里相应的驱动程序接收,然后经过一系列操作,从而决定是发送给本地的程序还是转发给其他机器。数据包通过防火墙时分以下3种情况。
1.以本地为目标的包
当一个数据包进入防火墙后,如果目的地址是本机,被防火墙进行检查的顺序如表3.8所示。如果在某一个步骤数据包被丢弃,当然就不会执行后面的检查了。
表3.8 以本地为目的的包检查顺序
2.以本地为源的包
本地应用程序发出的数据包,被防火墙进行检查的顺序如表3.9所示。
表3.9 以本地为源的包检查顺序
3.被转发的包
需要通过防火墙转发的数据包,被防火墙进行检查的顺序如表3.10所示。
表3.10 被转发的包检查顺序
在对包进行过滤时,常用的有以下3个动作。
(1)ACCEPT:一旦数据包满足了指定的匹配条件,数据包就会被ACCEPT,并且不会再去匹配当前链中的其他规则或同一个表内的其他规则,但数据仍然需要通过其他表中的链。
(2)DROP:如果包符合条件,数据包就会被丢掉,并且不会向发送者返回任何信息,也不会向路由器返回信息。
(3)REJECT:和DROP基本一样,区别在于除了将包丢弃以外,还会向发送者返回错误信息。
要进一步了解各个链中规则的匹配顺序,就来学习一下filter表中FORWARD链的输出,如【示例3-16】所示。
【示例3-16】
[root@CentOS ~]# iptables -nvL Chain FORWARD (policy DROP) target prot opt source destination ACCEPT all -- 192.168.100.0/24 0.0.0.0/0 ACCEPT all -- 0.0.0.0/0 69.147.0.0/24 ACCEPT all -- 172.16.0.0/16 0.0.0.0/0 mychain tcp -- 10.0.0.0/24 0.0.0.0 tcp dpt:80
“policy DROP”表示该链的默认规则为DROP操作。如现有一数据包,源地址为192.168.1.58,目的地址为137.254.60.6,协议为TCP,目的端口为80,当该数据包通过FORWARD链时,从上往下开始匹配:
(1)与第1条规则:源为192.168.100.0/24,源不匹配。
(2)与第2条规则:目的为69.147.0.0/24,目标不匹配。
(3)与第3条规则:源为172.16.0.0/16,源不匹配。
(4)与第4条规则:源为10.0.0.0/24,源不匹配。
经过匹配,以上所有规则都不符合,数据包将转交给默认规则处理。由于本示例中默认的规则为DROP,因此该数据包被丢弃。
再看另一个数据包,源地址为192.168.1.58,目的地址为69.147.83.199,协议为TCP,目的端口为80,当该数据包通过FORWARD链时,从上往下开始匹配:
(1)与第1条规则:源为192.168.100.0/24,源不匹配。
(2)与第2条规则:源地址为任意(0.0.0.0/0),匹配;目的地址为69.147.0.0/24,69.147.83.199在范围内,匹配;源端口和目的端口为任意,匹配;协议为任意(all),匹配;规则链对该数据包的动作为ACCEPT,因此该数据包通过。
如果数据包的源地址为10.0.0.35,目的地址为69.147.83.199,协议为TCP,目的端口为80,那么该数据包通过FORWARD链时,从上往下开始匹配,第4条规则匹配,动作为mychain,此时数据包会被转到用户自己定义的规则链mychain进行处理。
3.5.3 iptables配置实例
iptables工具支持丰富的参数,可以对IP和端口、网络接口、TCP标志位或MAC地址进行过滤,参数指定方式除传统方法外,可以支持“!”“ALL”或“NONE”等进行参数匹配。iptables常用参数说明如表3.11所示。
表3.11 iptables命令参数含义说明
1.简单应用示例
iptables使用方法首先指定规则表,然后指定要执行的命令,接着指定参数匹配数据包的内容,最后是要采取的动作。下面通过一些示例来说明iptables的使用方法,如【示例3-17】所示。
【示例3-17】
#清除所有规则 [root@CentOS ~]# iptables –F #清除nat表中的所有规则 [root@CentOS ~]# iptables -t nat –F #允许来自192.168.3.0/24连接sshd服务 [root@CentOS ~]# iptables -A INPUT -p tcp -s 192.168.3.0/24 --dport 22 -j ACCEPT #其他任何网段访问不能访问sshd服务 [root@CentOS ~]# iptables -A INPUT -p tcp --dport 22 -j DROP
在上述示例中,“-F”表示清除已存在的所有规则,“-A”表示添加一条规则,“-p”指定协议为TCP,“-s”指定源地址段,如果该参数忽略或为0.0.0.0/0,则源地址表示任何地址,“-dport”指定目的端口。包的判断顺序为首先判断第1条规则,由于允许192.168.3.0/24网段的服务器访问sshd服务,因此包可以通过;如果是其他来源的主机,由于第1条规则不符合接着判断第2条规则,策略为禁止,因此包将被丢弃。
除以上示例外,iptables可以为每个链指定默认规则,如果包不符合现存的所有规则,就按默认规则处理,方法如【示例3-18】所示。
【示例3-18】
#清除所有规则 [root@CentOS ~]# iptables –F #设置默认规则 [root@CentOS ~]# iptables -t filter -P INPUT ACCEPT #允许来自192.168.3.0/24连接sshd服务 [root@CentOS ~]# iptables -A INPUT -p tcp -s 192.168.3.0/24 --dport 22 -j ACCEPT
由于设置了默认规则,该示例的功能同示例3-3。
提示
上面所列举的示例仅仅是为了说明语法和原理,在实际使用中,还需要注意规则添加的顺序,使数据包通过的规则最少。
基于网络接口的过滤如【示例3-19】所示。
【示例3-19】
[root@CentOS ~]#iptables -t filter -F [root@CentOS ~]#iptables -t filter -P FORWARD DROP [root@CentOS ~]#iptables -t filter -A FORWARD -p tcp -i eth2 -o eth1 --dport 80 -j ACCEPT
使用-i参数来指定数据包的来源网络接口,使用-o来指定数据包将从哪个网络接口出去。
提示
在INPUT链中不能使用-o选项,OUTPUT链中不能使用-i选项。
2.NAT设置
通常网络中的数据包从包的源地址发出直到包要发送的目的地址,整个路径经过很多不同的连接,一般情况下这些连接不会更改数据包的内容,只是原样转发。如果发出数据包的主机使用的源地址是私用网络地址,该数据包将不能在互联网上传输。要能够使用私有网络访问互联网,就必须做NAT(Network Address Translation,网络地址转换)。
NAT分为两种不同的类型:源NAT(SNAT)和目标NAT(DNAT)。SNAT通常用于使用了私网地址的局域网络,能够访问互联网。DNAT是指修改包的目标地址,端口转发、负载均衡和透明代理都属于DNAT。
在SNAT中改变源地址,如【示例3-20】所示。
【示例3-20】
# SNAT改变源地址为1.2.3.4 [root@CentOS ~]# iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to 1.2.3.4 #DNAT [root@CentOS ~]# iptables -t nat -A PREROUTING -p tcp -i eth2 -d 1.2.3.4 --dport 80 –j DNAT --to 192.168.3.88:80
提示
如果做SNAT只能在POSTROUTING上进行,而做DNAT只能在PREROUTING内进行。