Android network — iptables四表五链
本文主要介绍了iptables的基本工作原理和四表五链等基本概念以及NAT的工作原理。
1. iptables简介
我们先来看一下netfilter官网对iptables的描述:
也就是说iptables
实际上只是位于用户空间的一个面向系统管理员的Linux防火墙的管理工具而已,而真正实现防火墙功能的是netfilter
,它是Linux内核中实现包过滤的内核模块,iptables
对应在内核中的模块应该是ip_tables
,我们查看系统内核中ip_tables
的信息的时候可以看到ip_tables.ko
这个模块是在netfilter
这个目录下的。
实际上除了iptables
还有如nftables
、firewalld
等防火墙工具都是在用户空间(用户层)对相应的内核空间中对应的netfilter
相关的模块进行操作的工具。
2. iptables的四表五链
2.1 iptables流程图
首先我们来看一下下面的这张图了解一下iptables中的表和链的概念。图中使用箭头展示了用户访问使用了iptables的机器的过程,其中按照箭头的顺序我们就可以将其梳理为一条大的带有分支的链条,在每个需要进行操作的模块处都标有名称和相应的括号,括号内的就是iptables的四表,而每个模块都可以视为一个链。
之所以叫做链就是因为在访问该链的时候会按照每个链对应的表依次进行查询匹配执行的操作,如PREROUTING
链对应的就是(raw
->mangle
->nat
),每个表按照优先级顺序进行连接,每个表中还可能有多个规则,因此最后看起来就像链一样,因此称为链。而iptables
的表中存储的就是对应的规则和需要执行的操作,这里以路由器为例查看其中iptables
的filter
表:
注意每一个链对应的表都是不完全一样的,表和链之间是多对多的对应关系。但是不管一个链对应多少个表,它的表都是按照下面的优先顺序来进行查找匹配的。
表的处理优先级:raw
>mangle
>nat
>filter
。
2.2 四表
iptables
的四个表iptable_filter
,iptable_mangle
,iptable_nat
,iptable_raw
,默认表是filter
(没有指定表的时候就是filter表)。
-
filter 表
:用来对数据包进行过滤,具体的规则要求决定如何处理一个数据包。对应的内核模块为:
iptable_filter
,其表内包括三个链:input
、forward
、output
; -
nat 表
:nat 全称:network address translation 网络地址转换,主要用来修改数据包的 IP 地址、端口号信息。对应的内核模块为:
iptable_nat
,其表内包括三个链:prerouting
、postrouting
、output
; -
mangle 表
:主要用来修改数据包的服务类型,生存周期,为数据包设置标记,实现流量整形、策略路由等。对应的内核模块为:
iptable_mangle
,其表内包括五个链:prerouting
、postrouting
、input
、output
、forward
; -
raw 表
:主要用来决定是否对数据包进行状态跟踪。对应的内核模块为:
iptable_raw
,其表内包括两个链:output
、prerouting
;
2.3 五链
iptables
的五个链PREROUTING
,INPUT
,FORWARD
,OUTPUT
,POSTROUTING
。
input 链
:当收到访问防火墙本机地址的数据包时,将应用此链中的规则;output 链
:当防火墙本机向外发送数据包时,将应用此链中的规则;forward 链
:当收到需要通过中转发给其他地址的数据包时,将应用此链中的规则,注意如果需要实现forward转发需要开启Linux内核中的ip_forward功能;prerouting 链
:在对数据包做路由选择之前,将应用此链中的规则;postrouting 链
:在对数据包做路由选择之后,将应用此链中的规则;
2.4 iptables的常见情况
下面我们利用上面的流程图来对几种常见的情况解析:关键点在于发往iptables主机的数据包的目的地址是否是iptables主机本机。如果是,那我们就可以理解为常见的开启了iptables防火墙的网站服务器主机;如果不是,那就是走ip_forward进行转发,比如我们常见的NAT路由器的NAT服务和策略路由等。如下图为开启了ip_forward功能。
3. NAT工作原理
接下来介绍一些NAT(Network Address Translation,网络地址转换)的基本知识,众所周知,IPv4的公网IP地址已经枯竭,但是需要接入互联网的设备还在不断增加,这其中NAT就发挥了很大的作用(此处不讨论IPv6)。NAT服务器提供了一组私有的IP地址池(10.0.0.0/8、172.16.0.0/12、192.168.0.0/16),使得连接该NAT服务器的设备能够获得一个私有的IP地址(也称局域网IP/内网IP),当设备需要连接互联网的时候,NAT服务器将该设备的私有IP转换成可以在互联网上路由的公网IP(全球唯一)。NAT的实现方式有很多种,这里我们主要介绍三种:静态NAT、动态NAT和网络地址端口转换(NAPT)。
3.1 BNAT
- 静态NAT:LVS的官方文档中也称为(N-to-N mapping)
,前面的N指的是局域网中需要联网的设备数量,后面的N指的是该NAT服务器所拥有的公网IP的数量。既然数量相等,那么就可以实现静态转换,即一个设备对应一个公网IP,这时候的NAT服务器只需要维护一张静态的NAT映射转换表。
内网IP | 外网IP |
---|---|
192.168.1.55 | 219.152.168.222 |
192.168.1.59 | 219.152.168.223 |
- 动态NAT:LVS的官方文档中也称为(M-to-N mapping)
,注意这时候的M>N,也就是说局域网中需要联网的设备数量多于NAT服务器拥有的公网IP数量,这时候就需要由NAT服务器来实现动态的转换,这样每个内网设备访问公网的时候使用的公网IP就不一定是同一个IP。
3.2 NAPT
以上的这两种都属于基本网络地址转换(Basic NAT),这种转换在技术上比较简单,仅支持地址转换,不支持端口映射,这也就带来了另一个问题就是资源的浪费。我们知道一个IP实际上可以对应多个端口,而我们访问应用实际上是通过IP地址+端口号的形式来访问的,即客户端访问的时候发送请求到服务器端应用程序监听的端口即可实现访问。那么NAPT就是在这基础上的扩展延申,它在IP地址的基础上加上了端口号,支持了端口映射的功能。
- NAPT:NAPT实际上还可以分为 源地址转换(SNAT) 和 目的地址转换(DNAT) 两种。注意这个源地址和目的地址是针对NAT服务器而言,我们通过下面一张图来说明:
首先我们这里有一个客户端,上面运行着一个浏览器,假设它使用的是5566
端口,它需要访问14.25.23.47
这个Web服务器的HTTPS服务的443
端口,它在访问的时候需要经过局域网出口的这个路由器网关(同时也是NAT服务器),路由器对它进行一个NAPT的源地址转换(SNAT),这个时候客户端的请求经过NAT服务器之后变成了222.17.23.45:7788
这个IP端口对Web服务器的443
端口进行访问。注意在这个过程中,目标服务器(Web服务器)的IP和端口是一直没有改变的。
接下来在Web服务器接收到请求之后,需要返回数据给发送请求的设备,注意这时候web服务器返回数据的指向IP应该是刚刚NAT服务器发送请求的227.17.23.45:7788
这个IP端口,这时候路由器网关再进行一次NAPT的目标地址转换(DNAT),目标的IP端口就是最开始发送请求的192.168.1.77:5566
这个端口。
实际上对于大多数人来说日常接触到最多的就是路由器做的SNAT和DNAT操作,它们一般成对出现用于解决公网IP资源不足的问题,需要注意的是NAT是可以进行嵌套操作的,即NAT下面的网络设备还可以继续做NAT,只要做NAT的网段不和上层的NAT的网段相同即可。
4. iptables配置
在了解清楚iptables的工作原理和每个表以及链的作用之后,我们就可以根据其特点进行针对性的配置。本篇先介绍简单
iptables 的基本语法命令格式
iptables [-t 表名] 管理选项 [链名] [匹配条件] [-j 控制类型]
表名、链名
:指定iptables
命令所操作的表
和链
,未指定表名时将默认使用filter
表;管理选项
:表示iptables
规则的操作方式,比如:插入
、增加
、删除
、查看
等;匹配条件
:指定要处理的数据包的特征,不符合指定条件的数据包不处理;控制类型
:指数据包的处理方式,比如:允许accept
、拒绝reject
、丢弃drop
、日志LOG
等;
iptables 命令的常用管理选项
-A:在指定链的末尾添加一条新的规则
-D:删除指定链中的某一条规则,可删除指定序号或具体内容
-I:在指定链中插入一条新规则,未指定序号时默认作为第一条规则
-R:修改、替换指定链中的某一条规则,可指定规则序号或具体内容
-L:列出指定链中所有的规则,未指定链名,则列出表中的所有链
-F:清空指定链中所有的规则,未指定链名,则清空表中的所有链
-P:设置指定链的默认策略
-n:使用数字形式显示输出结果
-v:查看规则列表时显示详细的信息
-h:查看命令帮助信息
--line-numbers:查看规则列表时,同时显示规则在链中的顺序号