在传统的标准的 TCP/IP 通信过程中,所有的路由器仅仅是充当一个中间人的角色,也就是通常所说的存储转发,路由器并不会对转发的数据包进行修改,更为确切的说,除了将源 MAC 地址换成自己的 MAC 地址以外,路由器不会对转发的数据包做任何修改。NAT(Network Address Translation)恰恰是出于某种特殊需要而对数据包的源 IP 地址、目的 IP 地址、源端口、目的端口进行改写的操作。 一般说来,有如下几种情况下需要做 NAT:
Linux 将 NAT 分成了两种类型,即源 NAT(SNAT) 和目的 NAT(DNAT),顾名思义,所谓 SNAT 就是改变转发数据包的源地址,所谓 DNAT 就是改变转发数据包的目的地址。前面提到过,Netfilter 是 Linux 核心中一个通用架构,它提供了一系列的"表"(tables),每个表由若干"链"(chains) 组成,而每条链中可以有一条或数条规则 (rule) 组成。并且系统缺省的表是"filter"。但是在使用 NAT 的时候,我们所使用的表不再是"filter",而是"nat"表,所以我们必须使用"-t nat"选项来显式地指明这一点。因为系统缺省的表是"filter",所以在使用 filter 功能时,我们没有必要显式的指明"-t filter"。同 filter 表一样,nat 表也有三条缺省的"链"(chains),这三条链也是规则的容器,它们分别是:
如前所述,在使用 iptables 的 NAT 功能时,我们必须在每一条规则中使用"-t nat"显示的指明使用 nat 表。然后使用以下的选项: (1)对规则的操作
(2)指定源地址和目的地址 通过 --source/--src/-s 来指定源地址 ( 这里的 / 表示或者的意思,下同 ),通过 --destination/--dst/-s 来指定目的地址。可以使用以下四中方法来指定 IP 地址:
(3)指定网络接口 可以使用 --in-interface/-i 或 --out-interface/-o 来指定网络接口。从 NAT 的原理可以看出,对于 PREROUTING 链,我们只能用 -i 指定进来的网络接口 ; 而对于 POSTROUTING 和 OUTPUT 我们只能用 -o 指定出去的网络接口。 (4)指定协议及端口 可以通过 --protocol/-p 选项来指定协议,如果是 udp 和 tcp 协议,还可使用 --source-port/--sport 和 --destination-port/--dport 来指明端口。 源地址 NAT (1)标准的 SNAT SNAT 的目的是进行源地址转换,应用于 POSTROUTING 规则链。在路由决定之后应用 SNAT 与出站接口相关 , 而不是入站接口。语法如下:
(2)MASQUERADE 源 NAT MASQUERADE 没有选项来指定在 NAT 设备上使用的特定源地址,使用的源地址就是出站好接口的地址。
举一个简单的例子:更改所有来自 192.168.1.0/24 的数据包的源 IP 地址为 1.2.3.4:
这里需要注意的是,系统在路由及过虑等处理直到数据包要被送出时才进行 SNAT。 另外,有一种 SNAT 的特殊情况是 IP 欺骗,也就是所谓的 Masquerading,通常建议在使用拨号上网的时候使用,或者说在合法 IP 地址不固定的情况下使用。比如:
可以看出,这时候我们没有必要显式的指定源 IP 地址等信息。 目的地址 NAT 目的地址 NAT 有两种形式:DNAT 和 REDIRECT。REDIRECT 是目的地址转换的特殊形式,将数据包重定向到 NAT 设备的输入或回环接口。目的地址 NAT 应用于 nat 表的 PREROUTING 和 OUTPUT 规则链,在做出路由决定前对目的地址进行修改。在 PREROUTING 中,DNAT 和 REDIRECT 规则与用来接受通过本地路由转发或送到主机的入站接口的数据包的入站接口有关。在 OUTPUT 中,DNAT 和 REDIRECT 规则用来处理来自 NAT 主机本身生成的出站数据包。 (1)标准目的地址 NAT(DNAT)
目的地址用来替换数据包中的原始目的地址和多位本地服务器地址。 (2)REDIRECT
REDIRECT 重定向数据包到执行 REDIRECT 操作的那台主机。 举个简单的例子:更改所有来自 192.168.1.0/24 的数据包的目的 IP 地址为 1.2.3.4:
这里需要注意的是,系统是先进行 DNAT,然后才进行路由及过虑等操作。有一种 DNAT 的特殊情况是重定向,也就是所谓的 Redirection,这时候就相当于将符合条件的数据包的目的 IP 地址改为数据包进入系统时的网络接口的 IP 地址。通常是在与 Squid( 一种开源代理服务器 ) 配置形成透明代理时使用,假设 Squid 的监听端口是 3128,我们可以通过以下语句来将来自 192.168.1.0/24,目的端口为 80 的数据包重定向到 Squid 监听端口:
|