方永、南天紫云

道亦有道

NAT穿透的问题
2022年03月29日

之前在 WireGuard使用记录 里提到 full mesh 网络的组建,但有一个关键之处, NAT的穿透问题,并未展开。

只是在文中提到,用wg set ...手动更新了 endpoint 后两个NAT之后的机器可以互相 ping 通。 是什么原理呢,在这里详述一下。

NAT概述

大家知道,NAT的出现是为了应对IPv4地址短缺的问题,顺便也会带来一点安全上的提升。 NAT是IP网络上的一个节点,它会把内部主机发起的连接的IP地址,替换为自己的IP地址, 而端口号,替换为自己的按一定规则生成的端口号。

由此知道,NAT上最重要的资源是65536个端口号,这些端口耗尽了,NAT也就处于不可用状态了(假设此NAT只有一个IP)。

NAT可以分为两类、4种类型,这两类是锥型和对称型,锥型里根据对外部地址和端口的限制,又有3种类型,如下表:

编号名称
1完全锥型NAT(Full cone NAT)
2受限锥型NAT((Address-)Restricted cone NAT)
3端口受限锥型NAT(Port-Restricted cone NAT)
4对称型NAT(Symmetric NAT)

顾名思义,锥型和对称型是 NAT 的 形状,锥型,内部主机经NAT到外部主机的所有连接, 都会通过NAT上面的1个端口,画张图,会看到很多条线汇聚到了一个端点上,也就是锥型的形状; 而对称型,不同的IP地址和端口,会映射到NAT上面的不同端口,画成图形,是很多的平行线。

NAT穿透

有3台主机,如下表,现在需要 A 和 C 直接连接。

名称描述
A锥型NAT之后
B有公网IP
C锥型NAT之后
  1. A首先连接B,于是B知道了A的NAT的IP地址和A在NAT上映射的端口号;
  2. 同理,C连接B,B也知道了C的NAT的IP地址和端口号;
  3. B告诉A,C的NAT的IP地址和端口号,B告诉C,A的NAT的IP地址和端口号;
  4. 对于NAT1型,即完全锥型,A向C的NAT IP地址和端口号发送数据,C会顺利接收到,C向A发数据同样如此,NAT穿透成功。
  5. 对于NAT2或NAT3型,C接收不了A发送的数据,原因是A发送到C的数据, NAT会认为这是一个无效的数据,它的连接表里没有A的NAT的IP地址和端口号的记录。 处理也很简单,即C向A的NAT的IP地址和端口号发送一次数据。同理,A接收C发送的数据也是如此,A和C直连成功。
  6. 对于NAT4型即对称型,A向C的NAT IP地址和端口号发数据,C接收不到,原因是NAT重新分配了端口号。 先假定A的NAT是NAT4型,C的NAT是NAT2或3型,A向B和A向C分别发送数据时,A的NAT上映射的端口号是不同的, A向C发送数据时NAT映射的端口号B和C都不知道,怎么办,暴力猜解!没错,尝试2048次,成功率可以达到99.9%(参见文末"How NAT traversal works"链接)

现实情况

真实的网络情况,要复杂一些,比如A和C之间有多个NAT,如果其中之一是NAT4型,那么穿透的难度将大大增加。 如果A和C处于同一个NAT之后,但是A和C因为各种原因隔离在了不同的网络中,它们之间还是不能直连的。

所以,NAT穿透的备用项就是中继(relay),常见是的 TURN,当然也可以自己实现。

总结

NAT的穿透,是受限于诸多因素的,要形成一个通用的、高成功率的解决办法,是需要做很多工作的。

参考

  1. 网络地址转换
  2. How NAT traversal works