NAT穿透/打洞
为什么要打洞
打洞主要是因为IPv4资源枯竭导致运营商没有为每个用户分配一个IP,详细的原因太长就不一一说明,读者可以自己查询,不过既然看这篇文章相信大多数都知道为什么要打洞以及打洞解决的问题。
打洞的条件
打洞是个很麻烦的事,不同的NAT类型打洞方法也不一样,甚至能不能打洞也是看NAT类型的,那么NAT都有什么类型呢?下面简单介绍下四种NAT类型:
Full Cone
这种NAT内部的机器A连接外网机器B后,NAT会打开一个端口用来跟外网机器B通信,这时外网的任何主机发往该端口的UDP数据都会到达A,不管是不是B发送的。主机A后续如果需要和其他主机通信将会使用已打开端口。
Restricted Cone
这种NAT内部的机器A连接外网机器B后,NAT会打开一个端口用来跟外网机器B通信,这时B主机可以用任何端口通过该打开端口和A通信,但是其他主机的任何端口的数据将会被拦截。主机A后续如果需要和其他主机通信将会使用已打开端口。
Port Restricted Cone
这种NAT内部的机器A连接外网机器B后,NAT会打开一个端口用来跟外网机器B通信,这时B主机只能通过之前的端口和A主机通信,其他端口都不行,其他主机的任何端口的数据将会被拦截。主机A后续如果需要和其他主机通信将会使用已打开端口。
Symmetic
该NAT和Port Restricted Cone差不多,不同的是该NAT类型后的主机A后续如果需要和其他主机通信那么将不会使用原来的端口而是会新开一个端口。
打洞原理
假设B是服务器有公网IP,A和C是两个不同NAT后面的主机,当A和C需要直接通信时,需要下述操作:
A发送一个请求到B,B记录下A的端口和IP;
C发送一个请求到B,B记录下C的端口和IP;
B将A的端口和IP发给C,将C的端口和IP发给A;
A往B发来的C的端口和IP发送数据,此时数据将会被C拒绝,但是A的NAT设备会记录下A与C通信过;
C进行与A同样的操作,但不同的是由于A的NAT设备记录了A与C通信过,所以A的NAT设备不会拦截C的数据,这样C就能与A通信了,同时由于C也往A发送过数据,所以下一个A发往C的数据C的NAT设备也不会拦截了,这样A与C就能正常通信了,一个打洞流程结束。
以上是打洞的大概步骤,同时上述的NAT类型描述会发现,A与C能通信的基本条件是A与C和C与A通信时NAT设备分给A、C的端口需要与A与B、C与B通信时分配的端口一致,这样可以看出Symmetic类型的NAT是不满足条件的,也就是说Symmetic几乎是无法打洞的,而所有Cone类型则可以正常打洞,同时上述操作可以看出是按照最严格的Port Restricted Cone类型来打洞的,实际上如果是另外两种Cone类型的NAT,就不需要这么麻烦,具体原因及流程各位同学可以自己想一下。为什么说Symmetic类型的NAT是几乎无法打洞而不是一定不能打洞呢?原因就是虽然Symmetic类型的NAT后的设备与不同主机通信时会分配不同的端口,但是还有一定可能通过端口猜测来成功进行连接的,不过就是几率太低,可以忽略,所以这种NAT类型就可以直接忽略,幸好该类型的NAT也并不常见。
NAT类型检测
可以看出能否成功打洞和NAT类型是有直接关系的,那么如何判断NAT设备的类型呢?可以根据NAT类型特征来判断,例如Full Cone类型,只需要外网主机构造出两个IP、端口不同的数据报发送给NAT后面的设备,如果都能接收到就是Full Cone类型,否则就不是,其他类型类似,都可以这样检测。
安全问题
由于打洞需要是UDP,而UDP是无连接的,UDP的数据报很容易伪装,这样就很容易出现安全问题,比如如果用户A伪造一个来源为用户B地址、端口的数据报,那么服务器回复确认消息的时候就会回复到用户B的地址上,恶意用户A可以利用这个方法来DDoS用户B,或者如果用户A想连接的是用户C,但是恶意用户B却将自己伪装成用户C,这时用户A将错误的连接上用户B,用户B就可以对用户A进行一些操作了。所以使用UDP时需要充分考虑安全问题。
TCP/UDP服务端程序可以参考https://github.com/JoeKerouac/socket
不要错过
领取专属 10元无门槛券
私享最新 技术干货