UDP网络穿透/打洞

STUN详细文档看 https://tools.ietf.org/html/rfc3489
UDP网络穿透, 实现两个设备之间的点对点的UDP通信, 主要应用在视频传输上.
如今, 这已经是很偏门的东西了, 现在都流行采用云的模式.

应用: ICE协议 https://tools.ietf.org/html/rfc5245
webrtc, pjsip, linphone等开源即时通信工具, 都实现了ICE协议

打洞流程

如果你不懂基本原理, 先阅读后面章节的内容.

主叫
被叫
创建udp socket
stun server请求
初始化socket
若Rx不在列表R1,R2...中
若Rx在列表R1,R2...中
探测包
探测应答包
确认应答包
若Lx不在列表 L1,L2...中
若Lx在列表 L1,L2...中
确认包
探测包
探测应答包
苦Lx同时满足被探测和已探测两种状态
开始
发起方
被叫方
获取主机地址 L1
获取NAT地址 L2,
生成地址列表L1, L2..
通过sip等协议, 将L1,L2...传给对方
通过sip等协议,拿到L1, L2...
通过同样的方式,
获取到本机地址和NAT地址R1, R2...
通过sip等协议, 将R1,R2...传给对方
向R1,R2...发送探测包
向L1,L2...发送探测包
接收对方的数据包,
并处理数据包的源地址Rx
加入到地址列表,
并发送探测包
处理数据包
回复一个
探测应答包,
将Rx标记为
被探测
将Rx标记为
已探测
穿透成功
如果Rx同时满足被探测和已探测两种状态
发送确认包
接收对方的数据包,
并处理数据包的源地址Lx
加入到地址列表,
并发送探测包
处理数据包
检查Lx的状态
回复一个
探测应答包,
将Lx标记为
被探测
将Lx标记为
已探测
发送确认应答包, 穿透成功
穿透过程结束

NAT网络类型

  1. Full Cone(全锥型): 内部地址(IP1, PORT1)映射到外部地址(IP2, PORT2), 任意外部主机都可以通过(IP2, PORT2)发送数据给内部主机(IP1, PORT1);
  2. Restricted Cone(IP限制型): 内部地址(IP1, PORT1)映射到外部地址(IP2, PORT2), 且内部主机(IP1, PORT1)向外部主机(IP3, 任意端口)发送过数据, 外部主机(IP3, 任意端口)才能通过(IP2, PORT2)发送数据给内部主机(IP1, PORT1); 可以看出, 限制型是在全锥型的基础上, 添加了IP限制;
  3. Port Restricted Cone(端口限制型): 内部地址(IP1, PORT1)映射到外部地址(IP2, PORT2), 且内部主机(IP1, PORT1)向外部主机(IP3, PORT3)发送过数据, 外部主机(IP3, PORT3)才能通过(IP2, PORT2)发送数据给内部主机(IP1, PORT1); 端口限制型是在IP限制型的基础上, 又增加了端口限制;
  4. Symmetric(对称型): 最严格的类型, 内部地址(IP1, PORT2)所映射的外部地址是动态的, 向不同的外部主机发送数据, NAT将分配不同的IP和端口. 如果内部主机不向外部主机发送数据, 那么外部主机完全无法连接到内部主机.

端口映射规则

对于对称型的NAT, 外部地址的IP和PORT都可能是变化, 比如长城宽带, 打开不同地址的网站, 运营商可能会为你分配不同的IP, 这种情况本文暂不讨论.

PORT的映射规则可能有以下几种:

  1. 随机型, 每次都分配一个随机的PORT, 无法预测. 这种情况应当很少见
  2. 一对一映射, 这种应当也很少见
  3. 递增型, 当NAT需要分配新的端口时, 会在上一次分配的端口的基础上递增, 通常是每次+1
    一旦知道了端口映射规律, 那么下一次映射的端口就可以预测出来.

NAT类型检测原理

服务器需要两个公网地址ip1, ip2, 需要两个端口port1, port2
创建4个服务端socket, 分别监听 (ip1, port1) , (ip1, port2), (ip12, port1), (ip2, port2);

  1. 客户端使用socket X向(ip1, port1)发送数据
  2. 服务端通过(ip2, port2)回复数据, 如果客户端能够收到消息, 则为全锥型, 否则, 继续判断
  3. 服务器通过(ip2, port1)回复数据, 如果客户端能够收到消息, 则为IP限制型, 否则, 继续判断
  4. 客户端使用socket X向(ip1, port2)发送数据, 如果服务端发现客户端的端口发生变化, 则为对称型, 否则为端口限制型

UDP穿透过程

首先双方通过stun服务器及sip服务器, 或其它手段, 拿到自己的和对方的内部地址和外部地址

  1. 相互向对方的内部地址发送数据, 主要是兼容局域网模式. (本文略)
  2. 相互向对方的外部地址发送数据, 对于全锥型的NAT, 这过程太简单了, 就不说了; 本文主要讲解复杂的NAT的穿透过程

以下的穿透过程都是不区分先后顺序的, 因此同一个操作会多次执行.

两个端口限制型的NAT穿透

这个过程很简单

第一次: A给B发消息, 不通
因为B还没有向A发送过消息, 所以A的消息被NAT-B拒绝

对端
本端
不通
NAT-A端口映射
NAT-B端口映射
B内部端口
A内部端口

第二次: B给A发消息, 通过

对端
本端
通过
NAT-B端口映射
NAT-A端口映射
B内部端口
A内部端口

最终A-B双向都能通

IP限制型与对称型的NAT穿透

以下设A为IP限制型, B为对称型
第一次: A给B发消息, 不通
因为B还没有向A发送过消息, 所以A的消息被B的NAT拒绝

对端
本端
不通
NAT-A端口映射
NAT-B端口映射, 端口为X
B内部端口
A内部端口

第二次: B给A发消息, 通过

对端
本端
通过
失效
NAT重新分配了端口
NAT-B端口映射, 端口为Y
NAT-A端口映射
B内部端口
NAT-B端口映射, 端口为X
A内部端口

第二次: A纠正信息, 再次给B发消息, 通过

对端
本端
通过
失效
NAT-A端口映射
NAT-B端口映射, 端口为Y
B内部端口
NAT-B端口映射, 端口为X
A内部端口

端口限制型与对称型的NAT穿透

设A为端口限制型, B为对称型.
这一次需要预测B的映射端口是多少 (说直白点, 就是靠猜)

第一次: A给B发消息, 不通
很显示, 因为B还没有向A发送过消息, 所以A的消息被B的NAT拒绝

对端
本端
不通
NAT-A端口映射
NAT-B端口映射, 端口为X
B内部端口
A内部端口

第二次: B给A发消息, 仍不通
因为B给A发消息时, B的映射端口变了, A不认这个端口.

对端
本端
不通
失效
NAT重新分配了端口
NAT-B端口映射, 端口为Y
NAT-A端口映射
B内部端口
NAT-B端口映射, 端口为X
A内部端口

第三次: A预测出B的端口, 再次给B发消息, 仍不通
如果预测的不对, 那怎么都不通. 这里假设猜对了

对端
本端
不通
失效
NAT-A端口映射
NAT-B端口映射, 端口为Y
B内部端口
NAT-B端口映射, 端口为X
A内部端口

第四次: B给A发消息, 通了
因为A给Y端口发过消息, 所以通过Y端口发给A的消息被认可

对端
本端
通过
失效
NAT-B端口映射, 端口为Y
NAT-A端口映射
B内部端口
NAT-B端口映射, 端口为X
A内部端口

对称型与对称型的NAT穿透

条件比上一节还苛刻, 双方都需要预测对方的端口, 都预测成功, 才能穿透成功

TCP穿透

下次再写

猜你喜欢

转载自blog.csdn.net/wzj_whut/article/details/86838344