一个webRTC传输协议搞得自己云里雾里的。现在主动攻克一下。先看看STUN协议。好,我们开始吧
目录
- 1.讲讲什么是NAT?
- 2.NAT有啥问题?
- 3.四种NAT类型
- 4.STUN Server
- 5.TURN Server
- STUN和TURN的实现:
- 什么是STUN?
- 为什么需要STUN?
1.讲讲什么是NAT?
原来这是因为IPV4引起的,我们上网很可能会处在一个NAT设备(无线路由器之类)之后。
NAT设备会在IP封包通过设备时修改源/目的IP地址. 对于家用路由器来说, 使用的是网络地址端口转换(NAPT), 它不仅改IP, 还修改TCP和UDP协议的端口号, 这样就能让内网中的设备共用同一个外网IP. 举个例子, NAPT维护一个类似下表的NAT表:
NAT设备会根据NAT表对出去和进来的数据做修改, 比如将192.168.0.3:8888 发出去的封包 改成120.132.92.21:9202, 外部就认为他们是在和120.132.92.21:9202通信. 同时NAT设备会将120.132.92.21:9202 收到的封包的IP和端口 改成192.168.0.3:8888, 再发给内网的主机, 这样内部和外部就能双向通信了, 但如果其中192.168.0.3:8888 == 120.132.92.21:9202这一映射因为某些原因被NAT设备淘汰了, 那么外部设备就无法直接与192.168.0.3:8888通信了。
我们的设备经常是处在NAT设备的后面, 比如在大学里的校园网, 查一下自己分配到的IP, 其实是内网IP, 表明我们在NAT设备后面, 如果我们在寝室再接个路由器, 那么我们发出的数据包会多经过一次NAT.
2.NAT有啥问题?
- NAT超时,在链路上一段时间内没有数据通讯后, 会淘汰NAT表中的对应项, 造成链路中断,超时时间一般是5分钟。
解决方案:通常我们TCP长连接的心跳设置的时间间隔为3-5分钟。 - NAT墙,所有外界对内网的请求,到达NAT的时候,都会被NAT丢弃,如果我们处于一个NAT设备后面,将无法得到任何外界数据。简言之, == 你躲在NAT后面,别人没办法请求你了。==
解决方案:就是如果我们A主动往B发送一条信息,这样A就在自己的NAT上打了一个B的洞。这样A的这条消息到达B的NAT的时候,虽然被丢掉了,但是如果B这个时候在给A发信息,到达A的NAT的时候,就可以从A之前打的那个洞中,发送给到A手上了。
简单来讲,就是如果A和B要进行通信,那么得事先A发一条信息给B,B发一条信息给A。这样提前在各自的NAT上打了对方的洞,这样下一次A和B之间就可以进行通信了。
3.四种NAT类型
在STUN标准中,根据私网IP地址和端口到NAT出口的公网IP地址和端口的映射方式,把NAT分为如下四种类型。
1.1 基础型NAT
仅将内网主机的私有IP地址转换成公网的IP地址,并不将TCP/UDP端口信息进行转换,分为静态NAT和动态NAT。
1.2 NAPT
NAPT不但会改变经过这个NAT设备的IP数据报的IP地址,还会改变IP数据报的TCP/UDP端口。
STUN中定义的NAT类型,RFC3489 中将 NAT 的实现分为四大类:
-
Full Cone NAT(完全锥型NAT)
所有从同一个私网IP地址和端口(IP1:Port1)发送过来的请求都会被映射成同一个公网IP地址和端口(IP:Port)。并且,任何外部主机通过向映射的公网IP地址和端口发送报文,都可以实现和内部主机进行通信。
这是一种比较宽松的策略,只要建立了私网IP地址和端口与公网IP地址和端口的映射关系,所有的Internet上的主机都可以访问该NAT之后的主机。
设备只是从192.168.1.101 发送给216.93.246.18,但是216.93.246.15可以直接给192.168.1.101发数据,这种即是Full Cone NAT
-
Restricted Cone NAT(限制锥型NAT)
所有从同一个私网IP地址和端口(IP1:Port1)发送过来的请求都会被映射成同一个公网IP和端口号(IP:Port)。与完全锥型NAT不同的是,当且仅当内部主机之前已经向公网主机发送过报文,此时公网主机才能向私网主机发送报文。
192.168.1.101需要先给216.93.246.18和216.93.246.15发消息,这两个服务器地址才可以给192.168.1.101回复,这个只是匹配IP地址,不会去检测端口,这就是Restricted Cone NAT
只有收过NAT内部送来的封包的地址才能将封包送入
-
Port Restricted Cone NAT(端口限制锥型NAT)
与限制锥型NAT很相似,只不过它包括端口号。也就是说,一台公网主机(IP2:Port2)想给私网主机发送报文,必须是这台私网主机先前已经给这个IP2和port2发送过报文。
需要内网先给两个服务器发送请求,才可以正常收到服务器回复数据包 ,但是会严格匹配IP和端口号
只有收过NAT内部送来的封包的地址和端口号才能将封包送入 -
Symmetric NAT(对称NAT)
所有从同一个私网IP地址和端口发送到一个特定的目的IP地址和端口的请求,都会被映射到同一个IP地址和端口。如果同一台主机使用相同的源地址和端口号发送报文,但是发往不同的目的地,NAT将会使用不同的映射。此外,只有收到数据的公网主机才可以反过来向私网主机发送报文。
请求和回复必须要对应才可以,只有有请求才能够访问内网主机
Symmetric NAT只允许先由私有网络內的使用者发送封包到公网网路中的使用者 可以回传封包
举例说明:
这些区别指的是这个蓝色的圆圈的区别
公网server1 ip是1.1.1.1, 监听端口是1111 【注意这里的公网可以理解为目的ip,如果两端通信,这就是对端。不是我们在开发环境的时候的服务器的公网ip】
公网server2 ip是2.2.2.2, 监听端口是2222
NAT router ip是8.8.8.8 NAT内部client是192.168.0.3
client发送数据的时候,不管是tcp还是udp必须本地绑定一个端口,一般来讲,这个过程都是自动的。假定client(192.168.0.3, 100)给 server(1.1.1.1, 1111)发送报文,报文到达路由器,路由器在自己的公网ip上开辟一个端口800,从而建立了一个隐射关系(8.8.8.8, 800)<—>(192.168.0.3, 100), 建立映射关系后,所以(192.168.0.3, 100)和(1.1.1.1, 1111)之间的报文都通过这个映射关系进行转发。
(二)NAT之间主要的区别分两种情况讨论
【发出去的区别,想发给别人走不走老路】
1:client(192.168.0.3, 100)和server(1.1.1.1, 1111)在路由器上建立好映射关系后,如果client(192.168.0.3, 100)又给(2.2.2.2, 2222)发送数据,路由器该怎么处理呢?
1, 复用旧的映射关系(8.8.8.8, 800)<—>(192.168.0.3, 100)和(2.2.2.2, 2222)通信, 这就是锥型(Cone) NAT—(分为下面的3个小类)
2, 创建新的映射关系(8.8.8.8, 801)<—>(192.168.0.3, 100)和(2.2.2.2, 2222)通信, 这就是对称型NAT
注: (8.8.8.8, 801)只是举例,到底用什么端口取决于路由器的端口管理策略,总之是另外的一个端口,有的路由器有多个公网IP,不同的IP也会参与到这个映射关系中。
【收到的区别,收到另一个端】
2:client(192.168.0.3, 100)和server(1.1.1.1, 1111)在路由器上建立好映射关系后,如果这个时候路由器(8.8.8.8)在800端口上收到从另外一台server(2.2.2.2, 2222)发来的数据,是不是应该转发给(192.168.0.3, 100)呢?
有四种情况:
1, 无条件转发给(192.168.0.3, 100), 这就是 全锥型(Full Cone) NAT。
2, 如果(192.168.0.3, 100)之前给**(2.2.2.2)发送过数据,则转发, 这就是受限锥型(Restricted Cone)。
3, 如果(192.168.0.3, 100)之前给(2.2.2.2, 2222)发送过数据,则转发, 这就是端口受限锥型(Port Restricted Cone)。
4, 丢弃报文,拒绝转发, 这就是对称型NAT**。
从上面也描述也可以看出,安全性系数, 对称型 > 端口受限锥型 > 受限锥型 > 全锥型
4.STUN Server
1.STUN Server主要做了两件事:
(1)接受客户端的请求,并且把客户端的公网IP、Port封装到ICE Candidate中。
(2)通过一个复杂的机制,得到客户端的NAT类型。
完成了这些STUN Server就会这些基本信息发送回客户端,然后根据NAT类型,来判断是否需要TURN服务器协调进行下一步工作。
我们来讲讲这两步具体做了什么吧:
第一件事就不用说了,其实就是得到客户端的请求,把源IP和Port拿到,添加到ICE Candidate中。
原理:客户端向STUN服务器发包,会有源ip、port,目的ip和port。STUN服务器收到包,可以解析出包的源IP和port,可以把这个数据再传回去。
来讲讲第二件事,STUN是如何判断NAT的类型的:
假设B是客户端,C是STUN服务器,C有两个公网IP分别为IP1和IP3:
STEP1.判断客户端是否在NAT后:
客户端B向STUN服务器C发送一个UDP 包(随便一个包,目的地址是C ip1,port1源地址是ip,port)。C收到这个包(源地址可能变了)后,会把C收到包的源IP和port(IP2,PORT2)写到UDP包中,然后把此UDP包发给B。这个IP2,PORT2也就是NAT的外网 IP和port,(也就是说你在STEP1中就得到了NAT的外网IP)。
一般情况下,C返回给B的这个UDP包B一定能收到(因为打洞了)。如果在你的应用中,向一个STUN服务器发送数据包后,你没有收到STUN的任何回应包,那只有两种可能:1、STUN服务器不存在,或者你弄错了port。2、你的NAT拒绝一切UDP包从外部向内部通过。
当B收到此UDP(含有IP2,PORT2)后,把此UDP中的IP2和自己的IP做比较,如果是一样的,就说明自己是在公网,下步NAT将去探测防火墙类型,我不想多说。如果不一样,说明有NAT的存在,系统进行STEP2的操作。
STEP2.判断是否处于Full Cone Nat下:
B向C的IP1发送一个UDP包,请求C通过另外一个IP2和PORT(不同与SETP1的IP1)向B返回一个UDP数据包(现在知道为什么C要有两个IP了吧,虽然还不理解为什么,呵呵)。
我们来分析一下,如果B收到了这个数据包,那说明什么?说明NAT来着不拒,不对数据包进行任何过滤,这也就是STUN标准中的full cone NAT。遗憾的是,Full Cone Nat太少了,这也意味着你能收到这个数据包的可能性不大。如果没收到,那么系统进行STEP3的操作。
STEP3.判断是否处于对称NAT下:
B向C的IP2,port2发送一个数据包,C收到数据包后,把它收到包的源IP和port写到UDP包中,然后通过自己的IP3和port3把包含C收到B的源IP和port的包(IP4,PORT4)发还给B。
和step1一样,B肯定能收到这个回应UDP包。此包中的port是我们最关心的数据,下面我们来分析:
如果这个(IP4,PORT4)port和step1中的(IP2,PORT2)port一样,那么可以肯定这个NAT是个CONE NAT,否则是对称NAT。道理很简单:根据对称NAT的规则,当目的地址的IP和port有任何一个改变,那么NAT都会重新分配一个port使用,而在step3中,和step1对应,我们改变了IP和port。因此,如果是对称NAT,那这两个port肯定是不同的。
如果在你的应用中,到此步的时候PORT是不同的,那么这个它就是处在一个对称NAT下了。如果相同,那么只剩下了restrict cone 和port restrict cone。系统用step4探测是是那一种。
STEP4.判断是处于Restrict Cone NAT还是Port Restrict NAT之下:
B向C的IP1的一个端口port1发送一个数据请求包,要求C用IP1和不同于PORT1的port3返回一个数据包给B。
我们来分析结果:如果B收到了,那也就意味着只要IP相同,即使port不同,NAT也允许UDP包通过。显然这是Restrict Cone NAT。如果没收到,没别的好说,Port Restrict NAT.
到这里STUN Server一共通过这4步,判断出客户端处于什么类型的NAT下,然后去做后续的处理:
这4步都会返回给客户端它的公网IP、Port和NAT类型,除此之外:
- 如果A处于公网或者Full Cone Nat下,STUN不做其他的了,因为其他客户端可以直接和A进行通信。
- 如果A处于Restrict Cone或者Port Restrict NAT下,STUN还会协调TURN进行NAT打洞。
- 如果A处于对称NAT下,那么点对点连接下,NAT是无法进行打洞的。所以为了通信,只能采取最后的手段了,就是转成C/S架构了,STUN会协调TURN进行消息转发。
【彻底搞明白了!!!!!】
5.TURN Server
-
为NAT打洞:
如果A和B要互相通信,那么TURN Server,会命令A和B互相发一条信息,这样各自的NAT就留下了对方的洞,下次他们就可以之间进行通信了。 -
为对称NAT提供消息转发:
当A或者B其中一方是对称NAT时,那么给这一方发信息,就只能通过TURN Server来转发了。
最后补充一下,为什么对称NAT无法打洞:
假如A、B进行通信,而B处于对称NAT之下,那么A与B通信,STUN拿到A,B的公网地址和端口号都为10000,然后去协调TURN打洞,那么TURN去命令A发信息给B,则A就在NAT打了个B的洞,但是这个B的洞是端口号为10000的洞,但是下次B如果给A发信息,因为B是对称NAT,它给每个新的IP发送信息时,都重新对应一个公网端口,所以给A发送请求可能是公网10001端口,但是A只有B的10000端口被打洞过,所以B的请求就被丢弃了。
显然Server是无法协调客户端打洞的,因为协调客户端打得洞仅仅是上次对端为Server发送端口的洞,并不适用于另一个请求。
最后的最后再补充一点,就是NAT打的洞也是具有时效性的,如果NAT超时了,那么还是需要重新打洞的。
对称nat无法穿透,这个说法不正确,对称nat与full cone nat、对称nat 与 ip受限cone、是可以穿透的,对称nat与 端口受限、对称nat与对称nat,不可穿透。
1、full cone 全椎
2、Restricted Cone ip受限
3、port Restricted Cone 端口受限
4、Symmetric 对称。
穿透关系:上述4种类型,如果定义他们的值为序列号,N为序列号相加。则N<=6可穿透。
2 和 4 序列相加 = 6 则可穿透。 3(端口受限)和4(对称)= 7 不可穿透。
STUN和TURN的实现:
什么是STUN?
P2P网络要求通信双方都能主动发起访问,但是NAT设备的存在,却阻断了这种主动访问,导致P2P应用无法正常运行。STUN是一种解决P2P应用NAT穿越问题的常用技术。它允许网络设备找出通信端点经NAT设备后的IP地址和端口号,并利用这些信息在通信双方之间建立一条可以穿越NAT设备的数据通道,实现P2P通信。
为什么需要STUN?
随着IPv4地址的枯竭,NAT功能部署越来越广泛。为了避免来自外部网络的攻击,保护网络内部的主机,NAT会过滤掉一些外网主动发送到内网的报文。因此,NAT技术虽然在一定程度上解决了IPv4地址短缺的问题,却破坏了点到点P2P(Point to Point)网络的通信。因为在P2P网络中要求通信双方都能主动发起访问,而NAT设备的存在却阻断了这种主动访问。
为了解决NAT设备给P2P网络带来的问题,出现了一些适用于P2P网络的NAT穿越技术。例如反向链接技术、应用层网关ALG(Application Level Gateway)技术、打洞技术(Hole Punching)、中间件技术等。
NAT会话穿越应用程序STUN(Session Traversal Utilities for NAT)是一种由RFC定义的网络协议,用于检测网络中是否存在NAT设备,并获取两个通信端点经NAT设备分配的IP地址和端口号。然后在两个通信端点之间建立一条可穿越NAT的P2P链接,实现P2P通信,这一过程也被形象的称为“打洞”。STUN无需现有NAT设备做任何改动,只需在组网中部署一台STUN服务器,操作起来比较简单,因此得到广泛应用。
引用:
https://www.jianshu.com/p/84e8c78ca61d
https://blog.csdn.net/lisemi/article/details/97672734?spm=1001.2014.3001.5502
https://blog.csdn.net/sj349781478/article/details/128209111#:~:text=%E4%B8%80%E8%88%AC%E6%9D%A5%E8%AE%B2%EF%BC%8C%20NAT%E5%8F%AF%E4%BB%A5%E5%88%86%E4%B8%BA%E5%9B%9B%E7%A7%8D%E7%B1%BB%E5%9E%8B%EF%BC%8C%E5%88%86%E5%88%AB%E6%98%AF%3A%201%2C%20%E5%85%A8%E9%94%A5%E5%9E%8B%20%28Full%20Cone%29%202%2C%20%E5%8F%97%E9%99%90%E9%94%A5%E5%9E%8B,Cone%29%2C%20%E6%88%96%E8%80%85%E8%AF%B4%E6%98%AF%20IP%20%2B%20PORT%E5%8F%97%E9%99%90%E9%94%A5%E5%9E%8B%204%2C%20%E5%AF%B9%E7%A7%B0%E5%9E%8B%20%28Symmetric%29
https://blog.csdn.net/wgl307293845/article/details/120450626