NAT

在RFC3489协议中,将NAT分成4种类型,即完全锥型、IP限制锥型、端口限制锥型以及对称型。在这4种类型中,越往后的NAT类型穿越难度越大。

我们一般处于下面这样的NAT网络环境:

NAT会在无感知的情况下帮我们自动进行内外网地址映射:

NAT类型

完全锥型NAT

特点:一旦打洞成功,所有知道该洞的主机都可以通过它与内网主机进行通信。

可以理解为每一个NAT“洞”的组成结构为:{内网IP、内网端口、外网IP、外网端口}

IP限制锥型NAT

特点:NAT打洞成功后,只有与之打洞成功的外网主机才能通过该洞与内网主机通信,而其他外网主机即使知道洞口也不能与之通信。

可以理解为每一个NAT“洞”的组成结构为:{内网IP、内网端口、外网IP、外网端口、【{被访问主机的IP}】}

端口限制锥型NAT

特点:除了像IP限制锥型NAT一样需要对IP地址进行检测外,还需要对端口进行检测。

可以理解为每一个NAT“洞”的组成结构为:{内网IP、内网端口、外网IP、外网端口、【{被访问主机的IP,被访问主机的端口}】}

对称型NAT

对称型NAT是4种NAT类型中对数据包检测最严格的。

特点:内网主机每次访问不同的外网主机时,都会生成一个新洞,而不像前面3种NAT类型使用的是同一个洞。

它与端口限制型NAT最大的不同是当host主机访问外网主机A时,它与主机A之间会新建一个洞,而不是复用访问主机B时的洞。

可以理解为每一个NAT“洞”的组成结构为:{内网IP、内网端口、外网IP、外网端口、{被访问主机的IP,被访问主机的端口}}

NAT类型推断

主机向STUN服务器发送请求,请求内部带有内网源IP/PORT信息,stun可借此得知内外网映射关系。

  1. 如果内/外网地址相同,则说明主机具有公网ip,非nat环境
  2. 如果stun用另一个ip/port向主机的这个源外网ip/port发送请求能正确得到响应,则说明是完全锥形NAT
  3. 如果stun用同一个ip不同port向主机的这个源外网ip/port发送请求能正确得到响应,则说明是IP限制型NAT
  4. 如果主机用同一个内网ip/port向stun的不同端口连续发送两个请求,这两个请求的外网port不同,则说明是完全对称NAT,否则是ip/port限制型NAT

各NAT之间可穿越表

NAT类型 NAT类型 能否穿越
完全锥型NAT 完全锥型NAT 可以
完全锥型NAT IP限制型NAT 可以
完全锥型NAT 端口限制型NAT 可以
完全锥型NAT 对称型限制型NAT 可以
IP限制型NAT IP限制型NAT 可以
IP限制型NAT 端口限制型NAT 可以
IP限制型NAT 对称型限制型NAT 可以
端口限制型NAT 端口限制型NAT 可以
端口限制型NAT 对称型限制型NAT 有可行性
对称型限制型NAT 对称型限制型NAT 不可以

NAT互通

下面针对几种特定组合分别给出解释,权当抛砖引玉,相信其他组合读者也不难推断。

IP限制型NAT与对称型NAT互通

设IP限制型NAT主机为X,设对称型NAT主机为A。

  1. X和A通过STUN服务器交换双方信息。

  2. X向A的外网地址发送数据,虽然会失败但是将会在X的NAT侧留下A的外网IP

  3. A向X的外网地址发送数据即可正常通行(因为A的外网IP已经在白名单里了)

  4. X与A正常通信

端口限制型NAT与对称型NAT互通

设端口限制型NAT主机为A,设对称型NAT主机为B。

即使再和之前一样,也很难准确地把B的端口加入白名单。

有两种可行的方案,一种方式是预测式,一种方式是枚举。

预测式:能预测内网和外网端口的映射规律,那么就能准确将B的端口加入白名单

枚举:A多次向B发送很多请求,这样就能把B的多个IP/Port对加入白名单,这样B往回发送的请求有可能命中。

端口限制型NAT与端口限制型NAT互通

  1. A/B与stun交换信息,从而有了双方已经生成的洞的信息
  2. A向B发送一个请求,由于A的IP/Port未在B的NAT侧的白名单中,故请求失败,但是此后A侧NAT就加入了B的外网IP/Port
  3. B向A的外网IP/Port发送请求即可成功

对称型NAT与对称型NAT互通

通过双向预测机制。

比如A向STUN服务器多次发送请求,因为每个请求都具备内网ip/port与外网ip/port的映射信息,从而有可能推导出内外网ip/port的映射关系。这样,就能预测式打洞成功,一个示例如下:

  1. 通过A和STUN多次交互获取并计算映射关系
  2. 通过第1步得到的映射关系有意构造一个请求,设内网ip/port为(x1,y1),则能够计算出外网ip/port将为(a1,b1),同时将该请求发送给B的(a2,b2)地址。这次请求会失败,但是会在A的NAT侧形成一个洞。
  3. B通过(a2,b2)反向推导出应使用的(x2,y2)内网源地址,于是以(x2,y2)为src,(a1,b1)为dst,即可成功请求。

参考