上一篇介绍了 webrtc 是如何建立连接的,也知道了连接的三种方式,直连、间接直连和中介连接。最好的当然是直连,但也是最难实现的。使用最多的还是间接直连的方式,连通率高且没那么难。兜底方案的话,则是使用中介连接,无论如何都能连上。从优先级上来说,排除第一个最难的,就是考虑间接直连了。但要使用间接直连,即 STUN 协议 连接,则必须要知道 NAT洞穿 是什么,知道了这个才能更好的理解 STUN协议的工作原理,才能在遇到问题时更好的排查。
下面就来介绍下NAT洞穿。
NAT
在WebRTC中,NAT(网络地址转换)是一种在网络通信中广泛使用的技术,用于解决IPv4地址不足的问题。它通过将私有IP地址映射到公网IP地址上,使得多个私有IP地址可以共享一个公网IP地址访问互联网。
最常见的NAT设备通过改变通过它的数据包的IP报头信息得以运行。通常情况下NAT技术与防火墙结合完成,大多数家用路由器都如此,这些路由器通常在保证安全性的同时还保留了IPv4的地址空间,可谓一举两得。
通常,局域网上的主机可以将数据包发送给互联网上的主机,但是当来自互联网的任何数据包尝试发送到局域网上的主机时,防火墙都会进行阻止。也就是说,NAT 或防火墙设备阻止数据包通过。但多数防火墙都允许来自互联网的某些特定的数据包通过,即当局域网中的主机 首先 通过防火墙发送数据包时才能通过。实质上,连接必须由局域网上的主机开启。同时,NAT会应用于通过NAT或防火墙设备加载的数据包。比如说,线上的每个数据包都有一个五元组的TCP / IP基本信息:源IP,源端口,目标IP,目标端口,传输协议(UDP / TCP / SCTP)。当数据包通过NAT或防火墙设备时,它会将数据包的源IP和源端口更改为新的源IP和源端口。然后它在“内部”源IP和源端口以及“外部”源IP和源端口之间保存此绑定。 这称为NAT绑定,NAT 或防火墙会将此路线存储在表中。
互联网上的主机只会看到并了解到已更改的“外部”IP端口。如果互联网上的主机了解到这个外部IP端口,并且想要向其发送数据包,这些数据包首先会到达NAT或/防火墙设备。 NAT 或防火墙设备将在其NAT表中查找,并根据NAT绑定,通过更改目标IP端口将数据包转发到内部主机。
通过上面的描述,应该大致了解了NAT的工作原理了,一句话解释就是将 内部源IP和源端口 与 外部源IP和源端口 进行绑定,形成一张映射表,在接收和发送数据时进行根据映射表进行相应的转换。
NAT洞穿
那么什么是NAT洞穿呢?当然就是 映射了。但是怎么个映射法呢?根据NAT的类型,又大致可以分为以下四种:
- 完全锥型NAT (Full Cone NAT)
- 受限锥型NAT (Restricted Cone NAT)
- 端口受限锥型NAT (Port Restricted Cone NAT)
- 对称型NAT (Symmetric NAT)
从名称应该就能大致知道,这四种类型的限制性是逐渐递增的,即要求越来越高。下面就来详细介绍下这四种类型:
完全锥型NAT (Full Cone NAT)
完全锥型NAT是最理想的NAT类型。同一内网主机和端口映射一个固定的外网IP和端口。任何外部主机只要向该外网IP和端口发送数据,内网主机都能接收到。当然,还得是内部主机先访问某个外部主机,这时就会在NAT上留下一个 映射表,比如 内网主机192.168.1.100:5000映射到外网IP 1.2.3.4:10000。之后,任何外部主机只要向1.2.3.4:10000发送数据,内网主机192.168.1.100:5000都能收到。
这是最为理想的,限制最小的NAT类型。只要知道了映射的外网地址,无论谁都能发送数据。
受限锥型NAT (Restricted Cone NAT)
受限锥型NAT与完全锥型NAT类似,同一内网主机和端口映射一个固定的外网IP和端口。但外部主机发送的数据要通过该外网IP和端口到达内网主机,内网主机必须先发送过数据给外网主机。
这个同上面 完全锥型NAT,但是多了一个非常严格的限制,就是限制了能发送数据的IP地址。只有内网主机访问过的外部主机,才能对内网主机发送数据,其他外部主机即使知道了内网主机映射的外网地址,也不能对内网主机发送数据。就相当于是内网主机会将访问过的外部主机记录下来,当接收到外部数据时,会校验外部数据的地址,如果不在登记册内就会拒绝接收。比如内网主机192.168.1.100:5000映射到公网IP 1.2.3.4:10000。内网主机必须先向外网主机5.6.7.8:12000发送过数据,外网主机5.6.7.8:12000才能向1.2.3.4:10000发送数据,内网主机才能收到。
这个类型的NAT也还能接受,只是限制了IP地址,端口啥的没有要求。
端口受限锥型NAT (Port Restricted Cone NAT)
端口受限锥型NAT进一步限制了受限锥型NAT,同一内网主机和端口映射一个固定的外网IP和端口。只有内网主机先给外网主机和端口发送过数据,外网主机的该端口发送给内网主机的映射外网IP和端口时,内网主机才能接收。
就是说这个类型的NAT 不光是限制了IP地址,也限制了端口。只有 IP地址和端口号 同时对上了才能发送消息,限制性进一步提高。例如:内网主机192.168.1.100:5000映射到公网IP 1.2.3.4:10000。内网主机必须先向外网主机5.6.7.8:12000发送过数据,外网主机5.6.7.8:12000才能向1.2.3.4:10000发送数据,内网主机才能收到。如果外网主机从其他端口发送,内网主机将无法收到。
这个也不是不能接受,只要 IP地址和端口 同时对上也可以连接。
对称型NAT (Symmetric NAT)
这个则是最为严格的NAT,内网主机映射的外网IP和端口根据目的地址的不同而不同。就是假如内网主机给外网主机A发送过一次数据,有了一层映射关系。下一次内网主机给外网主机B发送一次数据,则是另一种映射关系。每次连接的地址不一样,则映射关系不一样,可能IP变了,或者端口变了,又或者IP和端口都变了。
这个是最难连接的,每次连接都会发生变化。基本上很难连接成功,特别是两个都是对称型NAT。
在这四种类型中,两个对称型NAT是没法连接上的。同样,端口受限锥型NAT和对称型NAT也是没法连接上的。因为,他们的限制太多了,很难匹配上。这种情况下,就应该使用 TURN 协议来进行兜底连接。对于其他类型的话,则是比较好连接上的。
当然,这些事情我们并不用去自己操作。上一篇也说过,ICE 协议按优先级顺序进行连通性检测,就是说它会自动的进行NAT洞穿,会对NAT类型做出判断,分析是否能连接成功。如果连接不成功,则会使用 TURN 协议来进行连接。我们要做的就是部署好 STUN服务器 和 TURN服务器,并且把相关的信息配置好,其他的全都交给 webrtc即可。
小节
本文介绍了 STUN协议中的 NAT和NAT洞穿。NAT会将内网地址和端口与外网地址和端口进行绑定映射,形成一张映射表。不同类型的NAT则会进行不同程度的限制,其中无法进行连接的是对称型和对称型,以及对称型和端口受限锥型。NAT洞穿在 webrtc连接中是一个非常重要的过程,很有必要了解一下。
到这里就把webrtc的前端连接过程都介绍完了。当然,还有一个很重要的后端组成部分 信令服务器 还没介绍。这也是webrtc连接成功必不可少的部分。下面一小节就会介绍下如何用node实现一个简单的信令服务器。