文章比较长,但比较详细地介绍了有关iptables工具相关的概念以及使用场景。觉得文章对你有帮助的话就给祁祁一个关注和赞同吧。也欢迎大佬们在评论区指出文档中不足的地方,大家一起交流学习!
iptables
其实只是一个简称,其真正代表的是netfilter/iptables
这个IP数据包过滤系统。为了简便,本文也将整套系统用iptables简称。iptables是3.5版本的Linux内核集成的IP数据包过滤系统。当系统接入网络时,该系统有利于在Linux系统上更好地控制IP信息包和防火墙配置。此外,iptables还可以进行NAT规则的管理。 上面有提到netfilter/iptables这个组合,这个组合中:
包过滤防火墙在网络层截取网络数据包的包头(header),针对数据包的包头,根据事先定义好的防火墙过滤规则进行对比,根据对比结果,再执行不同的动作。 包过滤防火墙一般工作在网络层,所以也称为“网络防火墙”,通过检查数据流中每一个数据包的源ip地址,目标ip地址,源端口,目标端口,协议类型(tcp,udp,icmp等),状态等信息来判断是否符合规则。
NAT(Network Address Translation)网络地址转换,常用于局域网主机想与互联网服务通信时做地址转换,因为公网IP有限,且局域网主机访问公网必须要使用公网IP才可以访问到,因此使用NAT方法对地址做转换是一个很高效的方法。根据NAT使用场景不同可以将NAT分为SNAT(Source Network Address Translation)和DNAT(Destination Network Address Translation)。
举个例子,本地Web服务器A地址为192.168.1.2
,NAT主机地址为192.168.1.1
,公网地址为1.1.1.1
;另一个局域网主机B地址为172.16.1.2
,NAT主机地址为172.16.1.1
,公网地址为1.1.1.2
。此时B想要访问A的Web服务,B对应的NAT主机会将B发出的请求的源地址转换成其公网地址1.1.1.2从而与A对应的NAT主机进行通信,这里就是SNAT。而A对应的NAT主机收到该请求后会将该请求的目的地址转换成Web服务器A在局域网内的地址,即192.168.1.2,从而与Web服务器A进行通信,这里就是DNAT。
在上面的介绍中我们了解到,Netfilter其实是内核中若干个Hook点组成的。数据包经过内核协议栈处理程序时,处理程序会触发内核模块注册在相关Hook点上的数据包处理函数
。至于处理程序会触发哪个Hook函数,取决于当前数据包的方向(ingress/egress)
、数据包的目的地址
、数据包在上一个Hook点的状态
等等。 内核中有关数据过滤的Hook点有如下几个:
NF_IP_PRE_ROUTING
:接收到的数据包进行协议栈后立即触发此Hook,在进行任何路由判断之前;NF_IP_LOCAL_IN
:接收到的数据包经过了路由判断,如果目的地址是本机,将触发此Hook;NF_IP_FORWARD
:接收到的数据包经过了路由判断,如果目的地址是其他机器,将触发此Hook;NF_IP_LOCAL_OUT
:本机产生的准备发送的数据包,在进入协议栈之前立即执行该Hook;NF_IP_POST_ROUTING
:本机产生的准备发送的或者转发的数据包,在经过路由判断之后,将执行该Hook;Netfilter Hook函数工作位置
内核处理模块在往这些Hook上注册处理函数时,必须要提供优先级
,以便Hook触发时能按照优先级高低
调用处理函数。这就可以保证多个内核模块(或者同一内核模块的多个实例)
可以在同一个Hook点进行处理函数的注册,并且有确定的调用顺序。内核模块会被依次调用,并且处理完成后返回一个结果给netfilter框架,告诉某个数据包应该做什么操作。
iptables
通过表(tables)
、链(chains)
和规则(rules)
来管理数据包处理函数,结合对netfilter的了解可知,iptables会将这些数据包处理函数注册到内核提供的五个Hook点上。三者相关定义如下:
表
将处理同一类型的数据包规则聚合在一起。内核中内置有4张表,分别是raw
、mangle
、nat
、filter
。每一张表都只包含同一类型的数据包规则,比如nat表
只包含与网络地址转换
相关的规则。链
,其规定了相关规则在什么时候执行。内核中内置有5条链,分别对应netfilter提供的5个Hook点。链
能够让管理员在数据包传输过程中的某一个点通过相关规则控制数据包的走向。规则
存在于链
中,每一条链
包含若干规则
。当链
被调用时,数据包处理函数将按照顺序依次匹配对应链中的所有规则。每条规则都由匹配部分
+动作部分
组成,如果数据包满足匹配规则,则会执行相关动作对数据包进行处理。总的来说,规则是最终对数据包进行处理的部分,而表和链则是提供规则在协议栈被触发的前后顺序。三者关系可以用下面的图来表示:
image.png
通过上面几节的介绍,我们应该了解到:数据包在进入协议栈后,触发Hook点注册的相关处理函数实际上对应的是表、链、规则中的链。也就是说,某一规则的触发优先级首先取决于chain所在的位置
。其次通过包含了该chain类型的table中所对应的实际的chain下的规则进行规则匹配和动作执行。在这段过程中,需要注意:
尝试了解一条规则被执行的条件和顺序,这对于后面理解netfilter在协议栈中处理数据包的全过程有很大的帮助,一通百通。
提到iptables,常常会提到三表五链
、四表五链
等的词汇。这些词汇中提到的“三表”,“四表”等其实指的就是Linux内核中内置的常见表。Linux内核内置的表其实有五个,分别为:
iptables提供一个有状态的防火墙,基于netfilter上建立了连接跟踪的特性,即connection tracking,简称conntrack。iptables在处理数据包时都会依赖之前已经判断过的数据包。例如一条NAT记录,在第一次处理过后就会被存储在conntrack的哈希表中,下次有相同的数据包,则复用处理结果。 raw表提供的功能很简单:提供且仅提供一个让数据包绕过连接跟踪的框架。
mangle表提供修改数据包IP头部
的功能,例如,修改数据包的TTL等。此外,mangle表中的规则还可以对数据包打一个仅在内核内有效的标记(mark)
,后续对于该数据包的处理可以用到这些标记。
nat表顾名思义是用来做网络地址转换
的。当数据包进入协议栈后,nat表中的相关规则将决定是否修改以及如何修改数据包的源/目标地址,从而改变数据包被路由的行为。nat表通常用于将数据包路由到外部网络无法直接访问到的局域网络中。
应用场景: - 企业路由或者网关主机做SNAT,实现共享上网(通过POSTROUTING链) - 做内部网络和外部网络的IP地址一对一映射,常用于dmz区域(通过PREROUTING链) - 硬件防火墙映射IP到内部服务器; - 可以做单个端口的映射,直接将外部的80相关端口映射到内部Web服务器非80端口上。
filter表是iptables中最常用的表,用来判断一个数据包是否可以通过
。在防火墙领域,filter表提供的功能通常被称为“过滤”包。这个表提供了防火墙的一些常见功能。Filter表负责的主要是和主机自身相关的数据包处理手段,是真正负责主机防火墙功能的一张表。
应用场景:主机防火墙
security表的作用是给数据包打上SELinux标记
。SELinux以及可以解读SELinux安全上下文的系统在处理由security表做了标记的数据包时,行为会相应做出改变。
内核中内置的链有且仅有5条。不难发现,这与前面提到的NetFilter提供的5个Hook点的数量是一致的。没错,内核中内置的5条链正是对应5个Hook点。即:
PREROUTING
: 由 NF_IP_PRE_ROUTING
hook 触发;INPUT
: 由 NF_IP_LOCAL_IN
hook 触发;FORWARD
: 由 NF_IP_FORWARD
hook 触发;OUTPUT
: 由 NF_IP_LOCAL_OUT
hook 触发;POSTROUTING
: 由 NF_IP_POST_ROUTING
hook 触发。前面也提到过,链是位于表中的,内核内置表与内置链之间的包含关系如下表所示:
Tables | PREROUTING | INPUT | FORWARD | OUTPUT | POSTROUTING |
---|---|---|---|---|---|
raw | ✅ | ✅ | |||
mangle | ✅ | ✅ | ✅ | ✅ | ✅ |
nat | ✅ | ✅ | ✅ | ||
filter | ✅ | ✅ | ✅ | ||
security | ✅ | ✅ | ✅ |
这里我们对最常用的两个表:filter和nat进行相关链的说明,来看看某条链在某个表中起到什么作用。
filter表中有三条链:input、forward和output。
net.ipv4.ip_forward=1
nat表中有三条链:prerouting,postrouting和output。
规则是最终影响数据包的地方,一条有效的规则必须由匹配规则+动作目标
组成:
Linux内核提供如下的终止目标动作:
动作 | 含义 |
---|---|
ACCEPT | 允许数据包通过 |
DROP | 直接丢弃数据包,不给任何回应信息,这时候客户端会感觉自己的请求没有响应,过了超时时间才会有反应。 |
REJECT | 拒绝数据包通过,必要时会给数据发送端一个响应的信息,客户端刚请求就会收到拒绝的信息 |
SNAT | 源地址转换,解决内网用户用同一个公网地址上网的问题 |
MASQUERADE | 是SNAT的一种特殊形式,适用于动态的、临时会变的ip上 |
DNAT | 目标地址转换 |
REDIRECT | 在本机做端口映射 |
LOG | 在/var/log/messages文件中记录日志信息(其实就是写入系统日志,通过dmesg也可以看到),然后将数据包传递给下一条规则,也就是说除了记录以外不对数据包做任何其他操作,仍然让下一条规则去匹配 |
我们知道,Linux内核内置的链只有5条,且这5条链是netfilter hooks触发的唯一方式。那如果我想在不影响其他链的情况下使用自己定义的链,该如何操作呢?这时就可以在内置链上配置一个Jumping Target。实际上这里指定的就是我自定义的链的名字。例如下面的配置:
[root@localhost ~]# iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
KUBE-FIREWALL all -- anywhere anywhere
Chain KUBE-FIREWALL (2 references)
target prot opt source destination
DROP all -- anywhere anywhere /* kubernetes firewall for dropping marked packets */ mark match 0x8000/0x8000
上面的配置中,INPUT链的target为一条自定义的名为KUBE-FIREWALL的链,这样,从INPUT入口进入的数据包将会沿着链到达KUBE-FIREWALL链,然后将所有带有0x8000/0x8000
标记的包丢弃。
先通过一个简单的图示来了解各个表和链在数据包处理流程上起作用的位置和效果。如下图所示,将最常用的两张表filter和nat考虑到数据包过滤流程上。
iptables filter+nat.jpg
iptables数据流处理全过程图
iptables命令的大致语法如下,详细使用参见manual手册:
iptables [-t TABLE] [COMMAND] [OPTIONS]
# 查看iptables使用手册
man iptables
# 查看iptables详细参数使用手册
man iptables-extensions
iptables -nL --line-numbers
-n:将主机信息(IP地址,端口等)以数字的形式打印出来。默认会以hostname等方式打印出来; -L:显示规则链中已有的条目; --line-numbers:显示条目序号。
iptables -I INPUT 2 -s 192.168.1.1/32 -j DROP
-I:表示insert,即向链中插入一条规则,INPUT为链名,2为规则的序号; -s: 代表匹配源地址; -j:规则目标(Target),DROP代表丢弃所有包。
iptables -D INPUT -s 192.168.1.1/32
-D:表示delete,即从链中删除相关规则。
iptables -D INPUT 2
-D:表示delete,即从链中删除相关规则,链名后面可以接数字,表示删除某个序号。序号怎么获取可以在查看链规则时使用--line-numbers选项。
iptables -A INPUT -d 192.168.1.1/32 -j DROP
-A:表示append,即向链末尾追加一条规则; -d:代表匹配目的地址。
# LOG目标通常放在对数据包过滤和处理前,可以用来分析数据包流向。
iptables -I PREROUTING -t nat -j LOG --log-prefix "[NAT_PREROUTING_LOG]"
-I:表示insert,即向链中插入一条规则,PREROUTING为链名,没有指定序号默认为1,即顶部插入; -j:规则目标(Target),LOG代表获取数据包并打印日志; --log-prefix:日志信息的前缀,只能在-j LOG
的情况下使用。可以通过man iptables-extensions
查看其他针对某个Target的配置使用方式。
iptables-save > $HOME/iptables-save.bak
iptables -I INPUT -m addrtype --dst-type LOCAL -j KUBE-NODE-PORT
-m:表示match,这里涉及到iptables扩展的用法,即 包匹配扩展模块(extended packet matching modules)。这里使用的addrtype意思是通过选项指定的地址类型进行匹配,结合--dst-type不难得知:当数据包的目的地址类型是本机时,则该包匹配该规则。
iptables -I INPUT -s 192.168.1.1/32 -p tcp --dport 22,53,80 -j DROP
-s:source address,匹配源地址 -p:protocol,匹配协议 --dport:destination port,匹配目的端口。逗号分隔多个端口。
iptables -t raw -A PREROUTING -d 192.168.1.1/32 -p tcp --dport 80 -j NOTRACK
iptables -t nat -A PREROUTING -d 192.168.1.1 -t tcp --dport 80 -j DNAT --to-destination 192.168.1.2:9000
iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -j SNAT --to-source 123.123.123.123
iptables -A INPUT -p tcp -m tcp --dport 22 -m state --state NEW -m recent --set --name SSH --rsource
iptables -A INPUT -p tcp -m tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 4 --name SSH --rsource -j DROP