最近被人抓去研究 Switch 联机的 NAT 类型,经过一晚上的折腾,总算有了点收获,这里就来总结一下好了(
ToC
NAT?
我们知道,由于 IP 地址短缺的问题日益严重,为了缓解这个问题,NAT 开始流行起来。NAT 是 Network Address Translation 的缩写,意为网络地址转换。
NAT 有两种基本的类型,最为简单的就是 IP 地址的一对一映射,这种 NAT 被称为 Basic NAT。但这种 NAT 并不能解决上面所说的问题,因此我们实际遇到的情况很少。
而另外一种就相当普遍了。基于目前我们使用的所有传输层协议基本都是 TCP 和 UDP,而作为客户端一般很难将 65535 个端口耗尽的特点,出现了以端口映射为原理的 NAT,称作 NAPT。这种 NAT 的一个特点就是端口可能会因为大量的连接而耗尽,因此需要辅以一些对客户端的限制以保持端口资源的持续可用。
圆锥型 NAT
出于不同需求,NAT 也有着不同的类型。
NAT 的类型主要分为两类:圆锥型和对称型。圆锥型的特点是:只根据源地址和源端口这两个因素分配外部 IP 和端口。
换句话说,一旦客户端尝试用 12345 端口访问网络,那么之后再用 12345 端口访问网络时,分配到的还是原来的外部 IP和端口。
根据不同的安全需要,圆锥型 NAT 分为以下三类:
完全圆锥型(Full Cone)

完全圆锥型 NAT,又称一对一 NAT,其特点就是完全的一对一。一个端口一旦分给了一个人,那它就是你的,谁都可以访问。
这个特性对于点对点通讯而言是至关重要的,因为这样就相当于 NAT 不存在了。因此对于使用了 UDP 的游戏联机,我们都希望自己的 NAT 类型是 Full Cone,这样一旦连接建立,那么那个端口就代表我们,因而任意的其他用户就可以通过那个端口与我们连接了。
正如同上文描述的一样,这种 NAT 对源主机的 IP 地址和端口都没有限制。
受限圆锥型(Address Restricted Cone)

这种 NAT 的特点是:服务端和客户端通信的前提是客户端和服务端通信过。换句话说,也就是没有跟客户端通信过的主机无法使用这个端口。
如图所示,图中 Server1 是可以和 Client 正常通信的,而 Server2 则不行。可以看到 Server2 在尝试通信时遇到了一面“墙”,即图中箭头坐标的黑色竖线。
这种 NAT 实质上是限制了源主机的 IP,对源主机的端口没有限制。可以看出,相比于 Full Cone,这种 NAT 更加安全;但作为安全的代价,它没有 Full Cone 那么灵活。
端口受限圆锥型(Port-Restricted cone NAT)

这种 NAT 光看图的话看起来可能有点不明所以,但其实是相对于 Address Restricted Cone 又增加了一条限制:只能接收从与其通信主机的通信端口发来的数据。
图中的 Server1 尝试用另一个端口(也就是下面的圆点)向 Client 发送数据,在这种 NAT 下这是做不到的。
这种 NAT 同时限制了源主机的 IP 和端口。
小结
可以看到,从 Full Cone 到 Port-Restricted Cone,这三种 NAT 的安全策略是逐渐收紧的,但与之对应的,灵活性也是依次收紧的。
但尽管灵活性收紧,但圆锥型的 NAT 还是都可以做到 P2P 的,但下面介绍的对称型 NAT 就不是这样了。
圆锥为什么称作圆锥呢?可能是因为内部主机的多个请求对应到同一个外部 IP 和端口?也有可能是所有的服务器返回都从一个端口像圆锥一样涌进目标主机?没有考证到来源可能就是这样的吧(笑)
对称型 NAT(Symmetric NAT)

最后就是对称型 NAT 了。这种 NAT 和之前的三种有着本质性的区别,也就是“对称”。对称的话需要考虑的东西就多了:不仅是源 IP 和源端口,还要考虑目标 IP 和目标端口。
对「源 IP、源端口、目标 IP、目标端口」这样一个四元组,对称型 NAT 会为这个连接专门分配一个外部 IP 和端口;而当任何一项发生改变时,对称型 NAT 又会分配不同的外部 IP和端口组合。
而为了安全性,这种 NAT 也只能接收你访问的服务器发回的内容。这样的分配方式对于每个连接都好像是对称的,我想这就是它的名字的来源吧。
检测 NAT 类型
我们知道,NAT 也就意味着我们没有属于自己的公网 IP,因此各种需要公网 IP 的协议也就无法正常使用了。不过好在我们有圆锥型 NAT,而这种类型的 NAT 由于其「可复用外部 IP/端口」的特性,可以实现一定的内网穿透。而对称型 NAT 就比较麻烦了,两个对称型 NAT 下的设备是一定无法实现 P2P 的。
那我们又怎么知道我们在 NAT 下,或者换句话说,怎么知道我们在哪种 NAT 下呢?于是就出现了 STUN 协议。
STUN 是 Session Traversal Utilities for NAT 的缩写,它允许位于 NAT(或多重 NAT)后的客户端找出自己的公网地址,查出自己位于哪种类型的 NAT 之后以及 NAT 为某一个本地端口所绑定的 Internet 端端口。这些信息被用来在两个同时处于 NAT 路由器之后的主机之间创建 UDP 通信。该协议由 RFC 5389 定义。[5]
下面这张图是我从维基百科 STUN 的页面拿到的,简单翻译了一下。源地址是 [6]。

观察图中各个圆角矩形,分为了绿色、黄色和红色三种。绿色和黄色都可以实现 P2P,而红色一定无法实现 P2P(想一想,为什么?)。
结语
本文简单地整理了一下各种 NAT 的特点,以及 NAT 类型发现:STUN 协议的基本探测过程。
毕竟是初探,其实全文自己的理解还是比较少的