深入理解Netfilter和iptables架构
什么是防火墙
在计算机中,防火墙是基于预定安全规则来监视和控制传入和传出网络流量的网络安全系统。所有流入和流出该计算机的网络通信都要经过防火墙扫描和过滤。
防火墙可以过滤掉一些攻击、还可以关闭不使用的端口,而且它还能禁止特定端口的流出通信,封锁特洛伊木马。最后,它还能禁止来自特殊站点的访问,从而防止来自不明入侵的所有通信。
防火墙分为硬件防火墙和软件防火墙,在最基本的层面上,硬件防火墙是物理单元,而软件防火墙则通过应用程序从计算机内部运行。它们有总体相同的使命,但以略有不同的方式实现该使命:
- 硬件防火墙
- 硬件防火墙具有更好的安全性,是大多数企业用户的首选。然而,它比软件防火墙贵一点,并且设置配置可能需要更复杂的系统网络知识以获得更好和更优选的性能。
- 软件防火墙
- 软件防火墙的成本更低,设置配置通常更简单。它是大多数家庭用户的首选
Netfilter和iptables就是以软件方式实现防火墙能力。
Netfilter和iptables关系
对于不经常接触Linux内核的应用层开发者来说,可能对Netfilter
了解的比较少。但大多数Linux用户多少都用过或知道iptables
。iptables是使用很广泛的软件防火墙工具之一,它的功能实现就是在Netfilter
之上完成的。
- Netfilter框架由Linux开发人员Rusty Russell提出的Linux2.4内核防火墙框架,该框架即简洁又灵活,可实现安全策略应用中的许多功能呢。如数据包过滤、数据包处理、地址伪装、透明代理、动态网络地址转换(Network Address Translation)NAT,以及基于MAC地址的过滤和基础状态的过滤、包速率限制等。
- Iptables是一个命令行工具,用来配置Netfilter防火墙的。通常位于/sbin/iptables目录下,属于"用户态"的一个程序。它使得插入、修改、删除数据包过滤表中的规则变得容易。
Netfilter所设置的规则存放在内核空间中,而iptables是一个应用层的程序,它通过Netfilter提供的API接口对存放在内核空间中的XXtables(Netfilter配置表)进行修改。
假定我们需要通过iptables下发安全规则或者策略,需要在用户态应用程序调用iptabes内核模块
,再调用Netfilter hook API
执行规则所对应的动作,来完成对系统的防护。整个流程图如下:
下面让我们具体了解下netfilter和iptables架构原理。
Netfilter架构
从下图中我们可以看到,Netfilter框架采用模块化设计理念,并且贯穿Linux系统的内核态和用户态。在用户态层面,根据不同的协议类型,为上层用户提供了不同的系统调用工具。比如我们常用针对IPv4协议(iptables)、IPv6协议(ip6tables)、APR协议(arptables)、网桥控制(ebtables)、网络连接追踪(conntrack)等。这些用户态工具在内核中都有对应的模块调用Netfilter hook API
。
Netfilter hook API
是指Netfilter围绕网络层(IP 协议)的周围,埋下了五个钩子(Hooks),每当有数据包流到网络层,经过这些钩子时,就会自动触发由内核模块注册在这里的回调函数,程序代码就能够通过回调完成包过滤(Packet filtering)、网络地址转换(Network Address Translation)NAT和网络包协议头修改(Packet mangling)等各种操作。
这5个钩子挂载点分别是:
- PREROUTING:来自设备的数据包进入协议栈后立即触发此钩子。PREROUTING 钩子在进入 IP 路由之前触发,这意味着只要接收到的数据包,无论是否真的发往本机,都会触发此钩子。一般用于目标网络地址转换(Destination NAT,DNAT)。
- INPUT:报文经过 IP 路由后,如果确定是发往本机的,将会触发此钩子,一般用于加工发往本地进程的数据包。
- FORWARD:报文经过 IP 路由后,如果确定不是发往本机的,将会触发此钩子,一般用于处理转发到其他机器的数据包。
- OUTPUT:从本机程序发出的数据包,在经过 IP 路由前,将会触发此钩子,一般用于加工本地进程的输出数据包。
- POSTROUTING:从本机网卡出去的数据包,无论是本机的程序所发出的,还是由本机转发给其他机器的,都会触发此钩子,一般用于源网络地址转换(Source NAT,SNAT)。
下图是数据包在 Netfilter 框架中的流动过程:
从上图可以看出,路由判定是数据流向的关键点:
- 发往本地:第一个路由判定通过查找输入数据包
IP头部
的目的IP地址
是否为本机的IP地址
,如果是本机的IP地址
,说明数据是发送给本机的。否则说明数据包是发送给其他主机,经过本机只是进行中转。- 转发:第二个路由判定根据输出数据包
IP头部
的目的IP地址
从路由表中查找对应的路由信息,然后根据路由信息获取下一跳主机(或网关)的IP地址
,然后进行数据传输。
Netfilter 允许在同一个钩子处注册多个回调函数,因此向钩子注册回调函数时必须提供明确的优先级,以便触发时能按照优先级从高到低进行激活。由于回调函数会存在多个,看起来就像挂在同一个钩子上的一串链条,因此钩子触发的回调函数集合就被称为“回调链”(Chained Callbacks)。如下图所示:
iptables表和链(Tables and Chains)
“回调链”是由多个规则组成,但有些规则的功能又很相似。举个例子,假设你挂载规则目的是为了实现网络地址转换(NAT),那就应该对符合某种特征的流量(譬如来源于某个网段、从某张网卡发送出去)、在某个钩子上(譬如做 SNAT 通常在 POSTROUTING,做 DNAT 通常在 PREROUTING)进行 MASQUERADE 行为,这样具有相同目的的规则,就应该放到一起才便于管理,由此便形成“规则表”的概念。iptables 内置了五张不可扩展的规则表(其中 security 表并不常用,很多资料只计算了前四张表),如下所列:
- **raw 表:**用于去除数据包上的连接追踪机制(Connection Tracking)。
- **mangle 表:**拆解报文、做出修改、并重新封装,主要用于修改数据包的报文头信息,如服务类型(Type Of Service,ToS)、生存周期(Time to Live,TTL)以及为数据包设置 Mark 标记,典型的应用是链路的服务质量管理(Quality Of Service,QoS)。
- **nat 表:**network address translation,网络地址转换功能。主要用于修改数据包的源或者目的地址等信息,如SNAT、DNAT、MASQUEREDE、REDIRECT。
- **filter 表:**用于对数据包进行过滤,控制到达某条链上的数据包是继续放行、直接丢弃或拒绝(ACCEPT、DROP、REJECT)。典型的应用是防火墙,而所谓的防火墙其实基本上指这张表上的过滤规则。
- **security 表:**用于在数据包上应用SELinux,这张表并不常用。
以上五张规则表是具有优先级的:
raw → mangle → nat → filter → security
在实际应用中,不同的挂载点需要的规则类型通常不同。例如,在INPUT
挂载点上明显不需要filter
过滤规则,因为根据目标地址已经选择好了本机的上层协议栈,所以无需再挂接filter
过滤规则。目前Linux系统支持的不同挂载点使用到的规则也不同,具体表与链的对应关系如表 所示:
Tables/Chains | PREROUTING | INPUT | FORWARD | OUTPUT | POSTROUTING |
---|---|---|---|---|---|
raw | √ | × | × | √ | × |
mangle | √ | √ | √ | √ | √ |
nat(Source) | × | √ | × | × | √ |
nat(Destination) | √ | × | × | √ | × |
filter | × | √ | √ | √ | × |
security | × | √ | √ | √ | × |
让我们再结合数据包通过防火墙的流程来看,可总结为下图:
iptables规则
根据指定的匹配条件来尝试匹配每个流经此处的报文,一旦匹配成功,则由规则后面指定的动作进行处理。每条规则都有一个匹配部分和一个动作部分
匹配条件
- **S_IP:**source ip,源IP
- **S_PORT:**source port,源端口
- **D_IP:**destination ip,目标IP
- **D_PORT:**destination port,目标端口
- TCP/UDP: 传输层协议
匹配后的动作
- ACCEPT:同意数据包通过,继续执行后续的规则。
- DROP:直接将数据包丢弃。
- REJECT:给客户端返回 Connection Refused 或 Destination Unreachable 报文。
- QUEUE:将数据包放入用户空间的队列,供用户空间的程序处理。
- RETURN:跳出当前链,该链里后续的规则不再执行。
- JUMP:跳转到其他用户自定义的链继续执行。
- REDIRECT:在本机做端口映射。
- MASQUERADE:地址伪装,自动用修改源或目标的 IP 地址来做 NAT
- LOG:在/var/log/messages 文件中记录日志信息
- ……
iptables命令操作
对iptables进行操作,其实就是对“规则表”进行“增删改查”操作。
启动
Centos7 默认使用firewalld防火墙,iptables默认安装,但没安装iptables 管理服务 需要关闭firewalld防火墙 在下载开启iptables管理服务。
# 关闭firewalld防火墙
$ sysctmctl stop firewalld
# 关闭firewalld防火墙开机启动
$ sysctmctl disable firewalld
# 安装iptables的service启动工具
$ yum install -y iptables-service
安装完成后,即可通过systemctl
命令管理iptables
# 启动iptables
$ systemctl start iptables
# 查看iptables状态
$ systemctl status iptables
# 停止iptables
$ systemctl stop iptables
# 重启iptables
$ systemctl restart iptables
# 重载iptables
$ systemctl reload iptables
基本命令语法
$ iptables(选项)(参数)
常用的管理选项
-t<表>:指定要操纵的表;
-A:向规则链中添加条目;
-D:从规则链中删除条目;
-i:向规则链中插入条目;
-R:替换规则链中的条目;
-L:显示规则链中已有的条目;
-F:清楚规则链中已有的条目;
-Z:清空规则链中的数据包计算器和字节计数器;
-N:创建新的用户自定义规则链;
-P:定义规则链中的默认目标;
-h:显示帮助信息;
-p:指定要匹配的数据包协议类型;
-s:指定要匹配的数据包源ip地址;
-j<目标>:指定要跳转的目标;
-i<网络接口>:指定数据包进入本机的网络接口;
-o<网络接口>:指定数据包要离开本机所使用的网络接口。
--dport <端口>:匹配目标端口号。
--sport <端口>:匹配来源端口号。
iptables命令选项输入顺序
$ iptables -t 表 -A 链 匹配条件 处理动作
- 第一部分可以通过
-t
选项来指定操作的表,如filter
、nat
、mangle
或raw
。 - 第二部分可以通过
-A
、-D
、-I
或-R
选项来指定操作的链,如INPUT
、OUTPUT
、FORWARD
、PREROUTING
或POSTOUTING
。 - 第三部分主要设置规则的匹配条件,如匹配源IP地址或者端口等。
- 第四部分主要设置规则匹配成功后进行的动作,如接收或拒绝等。
查询规则
# 列出所有链上的规则
$ 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
# 列出INPUT链上规则
$ 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
# 结合"--line-numbers"选项还可以显示各规则在链中的顺序号
iptables -L INPUT --line-numbers
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 ACCEPT all -- anywhere anywhere state RELATED,ESTABLISHED
2 ACCEPT icmp -- anywhere anywhere
3 ACCEPT all -- anywhere anywhere
4 ACCEPT tcp -- anywhere anywhere state NEW tcp dpt:ssh
5 REJECT all -- anywhere anywhere reject-with icmp-host-prohibited
添加规则
向INPUT链的filter表中添加一条规则:
$ iptables -t filter -I INPUT -s 10.37.129.2 -j DROP
-t
: 是指定插入到哪个表中,不写的话默认为“filter”表;-I
: 指定插入到哪条链中,并且会在该链指定表(在这里是filter表)中的最前面插入(I:Input),如果用-A
则是在最后插入(A:Append)。-s
: 匹配源ip,s: source,源。-j
: jump,跳转的意思,后面可指定跳转的target(目标),比如自定义的链,当然更多的是跳转到“action(动作)”中,比如ACCEPT、DROP、REJECT等等。- 整个意思,就是向iptables中的“INPUT”链(
-I INPUT
)的“filter”表(-t filter
)的最前面(-I
)添加一条记录,这次记录会匹配源地址为“10.39.129.2”的请求(-s 10.39.129.2
),并把该请求丢弃掉(-j DROP
)。
删除、清空规则
-
根据编号删除
前面说过,查询iptables规则列表时,添加
–line-numbers
简写成–line
即可显示记录编号,我们现在就可以根据这个编号来删除了$ iptables -t filter -D INPUT 2
-t filter
指定操作的表为filter表,-D
表示delete,后面跟的两个参数,第一个是链名,第二个是要删除的规则的编号。 -
根据条件删除
$ iptables -t filter -D INPUT -s 10.37.129.2 -j DROP
删除INPUT链中的filter表中源地址为“10.37.129.2”并且动作为“DROP”的规则
-
清空
使用清空选项
-F
时,允许省略链名而清空指定表所有链的规则。例如分别清空filter表、nat表、mangle表$ iptables -F $ iptables -t nat -F $ iptables -t mangle -F
修改规则
事实上用“替换”来描述会更好一点,因为所谓的修改其实就是把整个规则替换成新的规则:
$ iptables -t filter -R INPUT 1 -s 10.37.129.3 -j ACCEPT
其中的-R
就是replace,即替换的意思,整句命令意思是从INPUT链中的filter表中替换编号为1的规则,编号1后面的-s 10.37.129.3 -j ACCEPT
就是要替换成的新规则。
保存规则
centos7中通过命令:service iptables save
保存.
$ service iptables save
在CentOS7中start/status/stop/restart/reload都可以换成systemctl的方式,但唯独save不能换成systemctl的方式
小结
Netfilter是实现包过滤防火墙功能的内核机制,iptables是管理防火墙规则的应用程序作用在用户态。Netfilter架构包含了5个钩子,iptables通过调用iptables内核模块再调用Netfilter hook API
。Netfilter hook API
也分别对应了5个挂载点(PREROUTING、INPUT、FORWARD、OUTPUT、POSTROUTING)。每个挂载点可挂载多个规则,这些规则统称为“回调链”。每个规则下的“回调链”,拥有相似的功能,我们统称为规则表(raw、mangle、nat、filter、security)。