您现在的位置是:首页 >其他 >Nat内网穿透详解与实战原理网站首页其他
Nat内网穿透详解与实战原理
作者:小成Charles
商业工作,学习交流请添加Vx:Lcc-Triumph
原创作品
转载请标注原创文章地址:https://blog.csdn.net/weixin_42999453/article/details/130303370
一、引言
在解释内网穿透这件事之前,我先抛出一个问题:如果让你来设计一套框架去实现两台内网主机进行通信,你会怎么做?
一个非常直观的设计就是先准备一台拥有公网ip的服务器命名为Server
,然后两台处于同内网下的客户端主机,分别为ClientA
和ClientB
,然后两台客户端机器分别连接服务器。这时候服务器充当一个数据中转站,把ClientA
发送的数据转发给ClientB
,反正同理,这就实现了两台内网的客户端之间的数据通信。(如图所示)
但是细心的同学会发现,这样做导致服务器的压力太大了,数据信息全都要经过服务器进行转发。那有没有一种方式去实现两台内网主机直接通信进行数据传输呢?当然有,那这就涉及到内网穿透的知识了。
二、什么是Nat?
想知道内网穿透实现原理,先弄清楚我们平时在网络冲浪的时候,数据是如何发到服务器的又是如何接受到数据的?我相信大家都知道,我们客户端在发送数据给服务器的时候,首先服务器的ip地址和端口我们是事先知道的,服务器接收到客户端的数据请求的同时也获取到了客户端的公网ip地址和端口,然后服务器根据客户端的公网ip地址和端口返回数据。
那就很清晰了,数据接收和发送都是通过公网ip和端口进行传输的,那我们直接获取到两台主机的公网ip地址和端口就可以实现跳过服务器中转站直接进行数据通信,其实这就是实现内网穿透的原理。但现实情况没那么简单。
因为IPV4的地址太少了,我们不可能每个人都有一个公网ip地址,所以运营商会在一个固定区域内设置Nat服务器
,这个Nat服务器拥有一个公网IP地址。当我们网上冲浪的时候,客户端会先将数据信息发送给Nat服务器,这个Nat服务器会为你这个内网IP的客户端分配一个固定的公网ip地址+端口
,然后再把数据发给服务器,服务器接收到数据之后会先根据这个公网IP地址和端口返回相应的数据,但是此时数据只是发到了Nat服务器,内网客户端并没有接收到,此时Nat会根据端口号映射到指定的内网主机,实现数据的传输。具体流程如下图
例子:ClientA
的内网IP为192.168.1.2:4567,ClientB
的内网IP为192.168.1.3:2389.经过Nat被映射为公网Ip地址,ClientA
被映射为10.2.6.4.1:6666,ClientB
被映射为10.3.5.7.8:9999。当服务器发送数据给10.2.6.4.1:6666
,就会被转发到192.168.1.2:4567
,也就是ClientA。如果有多个Client在同一Nat服务器发送数据时,Nat就会就会通过给每个内网ip映射一个IP地址:端口号
,其中IP地址是不会变的,改变的是端口号。
总结:所以Nat其实就是一个用来给内网IP地址分配公网地址的服务器
三、内网穿透实现原理
搞清楚了Nat服务器
,那实现起来就很简单了。如图所示。ClientA发送数据的Ip为192.168.1.2:4567,经过Nat映射为公网IP10.2.6.4.1:6666,然后将当前的公网IP发送给Server实现注册保存,同样的ClinetB把公网Ip10.3.5.7.8:9999发送到服务器注册保存。接着服务器把双方的的公网IP地址发送给对方,这时候双方都有对方的IP地址了,就可以直接对两个客户端直接建立连接实现数据的传输了。而这个过程中,服务器的数据流只有IP信息,实际数据通过两台客户端建立连接直接传输,这也是P2P网络的经典实现方法。
但是Nat又分为很多种,主流的分为锥型和对称型Nat,对于不同的Nat在做内网穿透的规则有不一样。
1)Full Cone NAT(完全圆锥型)
这种会将同一私网地址端口192.168.1.2:4567
发至公网的所有请求都映射成同一个公网地址端口10.2.6.4.1:6666
,192.168.1.2
可以收到任意外部主机发到10.2.6.4.1:6666
的数据报,这种类型的客户端局限性最低。
也就是说,只要知道私网地址被映射成的公网ip,任何公网IP
对其发送数据,这个私网下的所有端口都能接收到此数据。
2)Address Restricted Cone NAT (地址限制圆锥型)
这会将从同一私网地址端口192.168.1.2:4567
发至公网的所有请求都映射成同一个公网地址端口10.2.6.4.1:6666
,只有当内部主机192.168.1.2
先给服务器Server 6.7.8.9
发送一个数据报后,192.168.1.2
才能收到服务器Server 6.7.8.9
发送到公网地址端口10.2.6.4.1:6666
的数据报。
注意理清楚这里面的细节,地址限制圆锥型的意思就是说,私网地址接收到数据的这个公网IP必须是这个私网地址曾经发送过数据的IP地址(这就是一种映射规则
),当前私网地址下的所有端口都能接收到此数据。
3)Port Restricted Cone NAT(端口限制圆锥型)
与受限制锥型基本一样,区别就是最后私网地址下只有指定的端口号才能接收到数据。
这会将从同一私网地址端口192.168.1.2:4567
发至公网的所有请求都映射成同一个公网地址端口10.2.6.4.1:6666
,只有当内部主机192.168.1.2:4567
先给服务器Server 6.7.8.9
发送一个数据报后,192.168.1.2:4567
才能收到服务器Server 6.7.8.9
发送到公网地址端口10.2.6.4.1:6666
的数据报。
4)对称NAT(Symmetric)
对不同的外网IP地址都会分配不同的端口号。把所有来自相同内部主机IP地址和端口号,到特定目的IP地址和端口号的请求映射到相同的外部IP地址和端口。如果同一主机使用不同的源地址和端口对,发送的目的地址不同,则使用不同的映射。只有收到了一个IP包的外部主机才能够向该内部主机发送回一个UDP包。对称的NAT不保证所有会话中的(私有地址,私有端口)和(公开IP,公开端口)之间绑定的一致性。相反,它为每个新的会话分配一个新的端口号。
如果是对成型的Nat不适合做内网穿透,最后总结我会说。
这几种类型的Nat逐渐局限型越来越高,接下来我会根据端口限制圆锥型Nat
设计一个穿透过程:
UDP穿透流程
- ClientA 和 ClientB分别通过
Nat
与服务器进行通信,服务器只存储两个客户端的公网IP地址信息。 - 服务器接收到数据时分别将对方的IP地址信息发送给双方
- 此时,ClientA 拥有了 ClientB的公网地址,ClientA先发送一个
探测数据
给ClientB的公网IP,但是ClientB接收不到数据,因为根据协议,NatB中的映射没有这条规则,也就是说NatB并没有发送过数据给NatA,那就接收不到来自NatA的数据,但此时NatA添加了一条NatB信息的映射规则。
- NatB发送一条探测数据给NatA, NatA收到了。因为NatA在上一步骤中发送数据给NatB了,有了这条映射规则。
- NatA 在发送一条探测数据给NatB,NatB此时也收到了。
- 现在,UDP隧道建立成功,可以进行数据传输了。这个过程也叫做UDP打洞。
对称NAT(Symmetric)的内网穿透
根据这个流程我们会发现对称NAT(Symmetric)
不适合做内网穿透,举个例子,如果两个客户端都是对称NAT根据上述流程就没法穿透了。
- ClientA 和 ClientB分别通过
Nat
与服务器进行通信,服务器只存储两个客户端的公网IP地址信息。 - 服务器接收到数据时分别将对方的IP地址信息发送给双方
- 此时,ClientA 拥有了 ClientB的公网地址,ClientA先发送一个
探测数据
给ClientB的公网IP,但是此时对于ClientB发送数据的IP已经和服务器所保存的IP不一样了,因为对称NAT对于不同的公网IP地址发送数据所对应的端口是不一样的。那后面流程就没法继续了。
那两个对成型如何穿透呢,除非你能够准确的猜出客户端每次映射的端口号是多少(这个理论上可以实现,但是稳定性很低)
是否可穿透组合
下面是是否可穿透的Nat组合
Nat类型检测工具
工具下载地址:https://github.com/HMBSbige/NatTypeTester
打开软件导航选择RFC 3489,点击Test 。
四、总结
实际上操作内网穿透可能会更加的复杂,两台主机在同一个Nat下可能会无法穿透,因为有的Nat不允许数据回流,还有可能出现多层Nat穿透的情况,关于这一部分已经代码实现,我将会在下一期更新。
作者:小成Charles
商业工作,学习交流请添加Vx:Lcc-Triumph
原创作品
转载请标注原创文章地址:https://blog.csdn.net/weixin_42999453/article/details/130303370