NAT
网络地址转换协议。由于IPv4地址过于稀缺,不足以分配给每一台设备一个IP,本就不多的IP地址被列强占据大部分,再扣去保留地址,剩下的寥寥无几。不过好在有NAT,可以支撑我们能在因特网中冲浪🏄🏻。
所有同一个局域网内部的设备共用一个公网IP,在内部通过映射来区分不同设备的网络请求。
从表面上来看,NAT可以分为三大类型:静态NAT(基本)、动态地址NAT(基本)、地址端口转换NAPT(变种)
- 静态NAT:将内部私网地址与公网地址进行一对一的转换,每个内部地址的转换都是确定的
- 动态NAT:将内部私网地址与公网地址进行一对一的转换,**但是动态地址转换是从合法的地址池中动态选择一个未使用的地址来对内部私有地址进行转换。**和静态NAT的明显区别是
动态NAT有多个公网IP
- 地址端口转换NAPT:也是一种动态转换,而且内部多个地址被转换成同一个合法公网地址,使用不同的端口号来区分不同的设备和进程。
基本型NAT可以直接连接,变种NAT是无法直连的。
在NAPT中,又可以将NAT分为四类:全锥型NAT、地址受限锥型NAT、端口受限锥型NAT、对称NAT(基本的NAT已经非常少见了,NAPT才是我们常说的NAT,这里的NAT其实都是NAPT)
- 全锥型NAT:所有从同一个内网的(IP,端口)发送出来的请求都会被映射到同一个外网(IP,端口),且任何一个外网主机都可以通过访问映射后的公网地址,实现访问位于内网的主机设备功能。外网主机可以主动连接内网主机。
- 地址受限锥型NAT:所有从同一个内网的(IP,端口)发送出来的请求都会被映射到通过一个外网(IP,端口),但与全锥型不同点在于:生成的映射表项与目的IP有关,只有符合要求的目的IP(要访问的公网服务器IP)才可以通讯。此NAT还有个特点:不能主动连接内网中的主机地址,连接必须由内网地址发起。比起全锥型NAT多了地址限制。
- 端口受限锥型NAT:所有从同一个内网的(IP,端口)发送出来的请求都会被映射到通过一个外网(IP,端口),但是在地址受限锥型NAT基础上增加了端口的限制。
地址受限锥型NAT时,只有内网主机主动连接的公网主机才可与之进行通讯,而不用担心端口号是否与请求的端口相同。端口受限锥型NAT除了IP限制外,增加了端口限制。 - 对称NAT:所有从同一个内网(IP,端口)发送到同一个目的IP和端口的请求都会被映射到同一个IP和端口。(SIP,Sport, DIP, Dport)只要有一个发生变化都会使用不同的映射条目,即此NAT映射与报文四元组绑定。(较其他类型而言安全性较高,多用于3G、4G、公共WIFI等)
由于NAT的存在,我们可以在网络世界中遨游,也正是由于NAT的存在,我们无法直接在两台设备之间进行数据通讯,所以就有了——“打洞”。
P2P打洞
所谓的打洞就是STUN,Session Traversal Utilities for NAT,NAT会话穿越应用程序。STUN是一种网络协议,它允许位于NAT(或多重NAT)后的客户端找出自己的公网地址,查出自己位于哪种类型的NAT之后以及NAT为某一个本地端口所绑定的Internet端端口。这些信息被用来在两个同时处于NAT路由器之后的主机之间建立UDP通信。
当然并不是所有的NAT后面的设备都可以进行打洞,先来看表,至于原因,再了解打洞原理之后就明白了。
本端(NAT类型) | 对端(NAT类型) | 是否可以打洞 |
全锥型 | 全锥型 | ✅ |
全锥型 | 地址限制锥型 | ✅ |
全锥型 | 端口限制锥型 | ✅ |
全锥型 | 对称型 | ✅ |
地址限制锥型 | 地址限制锥型 | ✅ |
地址限制锥型 | 端口限制锥型 | ✅ |
地址限制锥型 | 对称型 | ✅ |
端口限制锥型 | 端口限制锥型 | ✅ |
端口限制锥型 | 对称型 | ❌ |
对称型 | 对称型 | ❌ |
关于UDP打洞的原理,先来看图,后面的许多内容都会基于这张图进行延伸。
B机器想要和C机器之间进行数据交换,起大致过程如下
- B、C机器都要在STUN服务器上进行注册,将各自的公网地址保存在STUN服务器;
- B、C机器分别从STUN获取对端的ip+端口;
- B机器向C的地址发送数据包,此时NAT2并不知道这条报文该发到局域网中的哪一台设备,所以丢弃此条数据,虽然这条数据并没有发送成功,但是,在NAT1中已经打开了B到C的口子,接受到来自C的数据都转发到B;
- C机器重复步骤3;
- 此时,B、C两台机器都打通了与对端都打通了与对端进行通讯的口子,这时一条穿越NAT的隧道已经打通,两端可以进行数据通讯。
在了解了打洞的过程之后,再来看一下不能打洞的情况(为了看起来方便省去了NAT层,其实是有NAT的),A所在的是端口限制锥型NAT,B所在的是对称型NAT。
- 首先双方向STUN注册自己,然后获取对端的地址;
- 分别向对端发送数据报,之前的NAT分类中说到了对称NAT的特点,所以B向A设备发送数据时的地址和注册在STUN中的地址是不一致的,此时B所在的NAT允许{A, b}和{M, h}之间进行数据交互;A设备向B在STUN注册的地址发送数据,此时A所在的NAT允许{A, b}和{M, n}之间进行数据交互;
- 所以现在的情况是,A、B所在NAT均因接收到的消息与白名单中端口不匹配而被丢弃
所以这种情况下是无法进行打洞的,同样的道理,双方均为对称型NAT时也是无法进行通讯的。这两种情况无法使用P2P直接连接,但是可以通过一台中继服务器(TURN)进行数据转发,这就要求TURN具有较高的处理能力和网络带宽。