iptables
Table of Contents
简介
iptables 并不是并不是真正的防火墙,而是一个客户端工具。 用户通过iptables去操作真正的防火墙 netfilter。
netfilter位于内核态。
netfilter/iptables 组合提供封包过滤、封包重定向和NAT等功能。
Chain

Chain: prerouting、forward、postrouting + input、output
一个报文只有符合一个Chain上所有的匹配Rule,才会被放行(执行相应动作)。
Rule
每个Chain中可能会存在Rule(0条或者多条),一个报文只有匹配一个Chain上面的Rule,才会执行相应的动作。
一个Chain上所有的规则都会按顺序进行一次匹配过滤。
一条规则最重要的就是其中的匹配条件和动作。
匹配条件
匹配条件分为基本条件和扩展匹配条件:
- 基本条件:源地址和目的地址
- 扩展条件: 如源端口和目标端口等,需要相应内核模块的支持
处理动作
当一个报文符合一条Rule的时候,会执行相应的动作:
- ACCEPT
- DROP,直接丢弃,不会给client端任何回应,client端只能因为超时再做出反应
- REJECT,拒绝,会告诉client端
- SNAT,源地址转换,一般用于内网朝公网发送信息
- DNAT,目的地址转换,目的网络地址转换
- MASQUERADE,SANT的一种特殊形式,适用于动态的、临时会变的IP上
- REDIRECT,在本机做端口映射
- LOG,记录信息在/var/log/message,然后让下一跳Rule继续处理该报文
一个SNAT例子: 当公网宿主机接收到来自于172.1.0.0/24的报文时,把报文的源IP地址替换成公网宿主机的出口网卡eth1的ip。 从而实现在内网访问外网
1 | 在公网宿主机上设置下面路由规则 |
一个DNAT例子:当公网宿主机的80端口接收到tcp请求之后,转发到内网的地址 172.1.10.2:80 。从而实现内网的服务可以被外网访问
1 | 在公网宿主机上设置下面路由规则 |
Table
把具有相同功能的Rule放到一起,称之为一个Table。 都需要相应内核模块的支持。
Table 有4个,优先顺序从高到低是按照:raw->managle->nat->filter
- raw 表,关闭nat表上启用的连接追踪机制
- managle 表,拆解报文,做出修改,并重新封装
- nat 表,网络地址转换
- filter 表,负责过滤
有些Table是肯定不会包含某些Chain的规则。
在实际使用过程中,一般是通过 Table 作为操作入口 ,对 Rule 进行定义。
用户可以自定义 Chain,在其中针对某个应用设计一些 Rule。 但自定义的Chain不能直接使用,需要通过系统默认Chain的调用才能生效(通过Rule 的动作)。

filter表、nat表、mangle表的作用总结
filter表 是专门过滤包的,它内建三个链,可以毫无问题地对包进行DROP、LOG、ACCEPT和REJECT等操作。
- FORWARD链过滤所有不是本地产生的并且目的地不是本地的包,
- 而 INPUT 是针对那些目的地是本地的包。
- OUTPUT 用来过滤所有本地生成的包。
nat表 的主要用处是网络地址转换,即Network Address Translation,缩写为NAT。做过NAT操作的数据包的地址就被改变了,当然这种改变是根据我们的规则进行的。属于一个流的包只会经过这个表一次。如果第一个包被允许做NAT或Masqueraded,那么余下的包都会自动地被做相同的操作。也就是说,余下的包不会再通过这个表,一个一个的被NAT,而是自动地完成。
- PREROUTING 链的作用是在包刚刚到达防火墙时改变它的目的地址(DNAT),如果需要的话。
- OUTPUT链改变本地产生的包的目的地址(DNAT)。
- POSTROUTING链在包就要离开防火墙之前改变其源地址(SNAT)。
- DNAT 是做目的网络地址转换的,就是重写包的目的IP地址。如果一个包被匹配了,那么和它属于同一个流的所有的包都会被自动转换,然后就可以被路由到正确的主机或网络。DNAT是非常有用的。比如,你的Web服务器在LAN内部,而且没有可在Internet上使用的真实IP地址,那就可以使用DNAT让防火墙把所有到它自己HTTP端口的包转发给LAN内部真正的Web服务器。DNAT的目的地址也可以是一个范围,这样的话,DNAT会为每一个流随机分配一个地址。因此,我们可以用这个DNAT做某种类型的负载均衡。
mangle表 主要用来修改数据包。我们可以改变不同的包及包头的内容,比如TTL,TOS或MARK。 注意MARK并没有真正地改动数据包,它只是在内核空间为包设了一个标记。防火墙内的其他的规则或程序可以使用这种标记对包进行过滤或高级路由。这个表有五个内建的链:PREROUTING,POSTROUTING,OUTPUT,INPUT和FORWARD。
- PREROUTING在包进入防火墙之后、路由判断之前改变包,POSTROUTING是在所有路由判断之后。
- OUTPUT在确定包的目的之前更改数据包。
- INPUT在包被路由到本地之后,但在用户空间的程序看到它之前改变包。
- FORWARD在最初的路由判断之后、最后一次更改包的目的之前mangle包。
- 注意,mangle表不能做任何NAT,它只是改变数据包的TTL,TOS或MARK。
结合kube-proxy源码分析
从上面iptables路由次序图,可以看出来,如果我们要让某台Linux主机充当路由和负载均衡角色的话,我们显然应该在该主机的nat表的prerouting链中对数据包做DNAT操作。
Kubernetes可以利用iptables来做针对service的路由和负载均衡,其核心逻辑是通过定义在/kubernetes-1.5.2/pkg/proxy/iptables/proxier.go中的函数syncProxyRules()来实现的。
syncProxyRules()就是在service所在node的nat表的prerouting链中对数据包做DNAT操作。
Kubernetes通过在目标node的iptables中的nat表的PREROUTING和POSTROUTING链中创建一系列的自定义链,这些自定义链主要是:
- “KUBE-SERVICES”链
- “KUBE-POSTROUTING”链
- 每个服务所对应的”KUBE-SVC-XXXXXXXXXXXXXXXX”链
- “KUBE-SEP-XXXXXXXXXXXXXXXX”链
然后通过这些自定义链对流经到该node的数据包做DNAT和SNAT操作以实现路由、负载均衡和地址转换。
1 | // This is where all of the iptables-save/restore calls happen. |
iptables基本使用命令
所谓的定义iptables规则,其实就是对raw、managle、nat、filter这四张表进行增删改查操作。
查
如果不指定一个表,默认操作的是filter表
1 | iptables -L -t nat |
讲一下里面的属性:
- Chain INPUT (policy ACCEPT 11 packets, 644 bytes) ,表示filter表中的INPUT 关卡默认动作是ACCEPT, packets是当前Chain默认规则匹配到的包数量,644 bytes则是包大小。
- pkts ,对应规则匹配到的报文个数
- bytes,对应规则匹配到的报文大小总和
- target,匹配成功后的动作
- prot,协议,针对哪些协议使用此规则
- opt,此规则对应的选项
- in,报文是从哪个网卡流入的需要匹配此规则
- out,报文是从哪个网卡流出的
- source,报文源地址,可以是一个IP或一个网段
- destination
增
注意点:添加规则时,需要注意规则的顺序
在指定表的最后增加一条规则
1 | 命令语法:iptables -t 表名 -A 链名 匹配条件 -j 动作 |
在指定表的指定位置增加一条规则
1 | 命令语法:iptables -t 表名 -I 链名 规则序号 匹配条件 -j 动作 |
设置表的默认策略
1 | 命令语法:iptables -t 表名 -P 链名 动作 |
删
注意点:如果没有保存规则,谨慎删除规则
删除指定序号的规则
1 | 命令语法:iptables -t 表名 -D 链名 规则序号 |
根据匹配条件来删除规则
1 | 命令语法:iptables -t 表名 -D 链名 匹配条件 -j 动作 |
删除指定表的指定Chain 的所有规则
1 | 命令语法:iptables -t 表名 -F 链名 |
删除指定表的所有规则
1 | 命令语法:iptables -t 表名 -F |
最后要说的是对iptables rule的进行的操作只是临时生效的,如果要想让其永久生效,需要使用iptables save来保存规则。