NAT,全称Network Address Translation,网络地址转换。

是一种使得内网的计算机可以访问外网的技术。

这个本来是写在Net9 Wiki上的,现在这里也弄一份……

基础

是在网关上进行的一种过程,是在转发数据包的过程中干的。

因此,依赖于网关的功能。

样例与分析

环境

  • 有某内网,网段192.168.1.0,网络掩码255.255.255.0。
  • 其中有某机,IP 192.168.137.3。
  • 网关对内IP 192.168.137.1。
  • 网关对外IP 59.66.132.114。
  • 网关对外环境下的默认路由IP 59.66.132.1。

目的

某机想上网,访问ibm.com的80端口。

常量定义

 A: ibm.com 的IP地址
 B: 某机IP(192.168.137.3)
 C: 网关对外IP(59.66.132.114)
 D: 网关IP(192.168.137.1)
 a: 网关内网接口的MAC地址(对应192.168.137.1)
 b: 网关外网上默认路由的MAC地址(对应59.66.132.1)
 c: 某机MAC地址(对应192.168.137.3)
 d: 网关外网接口MAC地址(对应59.66.132.114)
 x: 某机认为的源端口
 y: 经过NAT变换之后的源端口
 m: ibm.com 域名

数据包

某机发出的开始连接TCP数据包:

MAC头 IP头 TCP头
a<-c A<-B 80<-x

于是这个包被网关收到,经过篡改,当它在外网出现的时候,成了这样:

MAC头 IP头 TCP头
b<-d A<-C 80<-y

对面收到之后发了回复,回复抵达网关的外网接口的时候,是这样:

MAC头 IP头 TCP头
d<-b C<-A y<-80

然后又被篡改,当某机收到的时候,是这样:

MAC头 IP头 TCP头
c<-a B<-A x<-80

对某机来说,看上去就有了一条A:80 <-> B:x的连接。 但是对对面来说,看上去其实是有一条A:80 <-> C:y的连接。

分析

为啥要篡改?因为如果在外网出现了一个192.168.137.3的数据包,谁知道这个包是干啥的,因为外网的网段是59.66.132.0/24,不应该有这种包。所以就会被扔掉,即使没有扔掉,回复也发不回来。

所以,要伪造成网关发出去的包才有人管。所以,首先要把IP篡改成网关的对外IP。

当对面收到并且发了回复回来的时候,还需要改回去。问题是,如何区分哪些包是应该改的?对于TCP/UDP包,有个很好的依据:端口号。

所以,只要在之前篡改的时候,记录下源端口号,和源IP,那么当收到数据包的时候,如果目的端口号就是记下的这个,那就篡改回去,并且发给记下来的来源地址。

简单来说,这样就可以了。MAC地址那边的变化,只是为了数据包能够抵达目的地而已。这方面可以参考基础的网关转发数据包的过程。

那么为啥有时候还要篡改端口号?因为可能,网关对外出口上,已经有一个程序在用这个端口号了。比如有一个人listen在1025端口上,而内网的一个机子发给外网一个数据包,源端口号也是1025。那么,当有一个新的数据包到来,并且其目的端口号是1025的时候,我们要不要篡改呢?我们怎么知道,这个是到那个listen的人的一个新连接,还是对原来内网那个数据包的回应呢?

所以,有时候要篡改一下端口号,同时记录下源IP和源端口号,以及篡改后的端口号。这样,当收到向篡改后的端口号发送的数据包的时候,我们就要把目的地址和目的端口都篡改回去,再发给原来的发送者。