WebRTC 中两个或多个主机进行 P2P 连接是通过 STUN、TURN、ICE 等技术实现的。主机往往都是在 NAT 之后,且不同的 NAT 导致外部主机向内网主机发送数据的可见性不同。内网主机通过 STUN 协议可以获得 NAT 分配的外部地址。ICE 是主机之间发现 P2P 传输路径机制,ICE 中使用了 STUN 协议进行连通检测、传输路径的指定和保活。本文将对 STUN 和 ICE 协议进行分析和解读,希望能为开发者们带来一些启发和帮助。
1. NAT 类型
网络地址转换, 简称 NAT,节省了 IPv4 地址空间的使用并且隔离了内网和外网。NAT 对待 UDP 的实现方式有 4 种,分别如下:
1.1 完全圆锥型一个内网地址(iAddr:iPort)被映射到一个外网地址(eAddr:ePort)。这个内网(iAddr:iPort)地址发送的数据包都会通过这个外网地址(eAddr:ePort)。外部主机可以通过这个外网地址(eAddr:ePort)向这个内网地址(iAddr:iPort)发送数据包。
1.2 地址受限锥型
一个内网地址(iAddr:iPort)被映射到一个外网地址(eAddr:ePort)。这个内网(iAddr:iPort)地址发送的数据包都会通过这个外网地址(eAddr:ePort)。外部主机 (hAddr:any)只有接收过从内网(iAddr:iPort)发送来的数据包后,才能通过外部地址 (eAddr:ePort)发送数据包给内网地址(iAddr:iPort)。其中外部主机的端口可以是任意的。
1.3 端口受限锥型
一个内网地址(iAddr:iPort)被映射到一个外网地址(eAddr:ePort)。这个内网(iAddr:iPort)地址发送的数据包都会通过这个外网地址(eAddr:ePort)。外部主机(hAddr:hPort) 只有接收过从内网(iAddr:iPort)发送来的数据包后,才能通过外部地址 (eAddr:ePort)发送数据包给内网地址(iAddr:iPort)。其中外部主机的端口 hPort 是受限的。
1.4 对称型
一个内网地址(iAddr:iPort)向外网地址 (sAddr1:sPort1)发送的多次请求时,NAT会分配同一个外网地址(eAddr1:ePort1)。若向不同的外网地址如(sAddr2:sPort2)发送数据包时,NAT 分配另外一个外网地址(eAddr2:ePort2)。外网地址(sAddr1:sPort1)只有接收过从内网(iAddr:iPort)发送来的数据后,才能通过已经在NAT上开辟的(eAddr1:ePort1)发送数据包给内网。
2.STUN 简介
STUN 是 Session Traversal Utilities for NAT 简写,RFC5389规定了具体内容。STUN 协议是用来获取内网地址对应在 NAT 上的外网地址,NAT 穿越。STUN 是 C/S 模式的协议,由客户端发送 STUN 请求;STUN 服务响应,告知由 NAT 分配给主机的 IP 地址和端口号。
2.1 STUN 消息结构
STUN 消息头为 20 字节,后面紧跟 0 或多个属性。STUN 头部包含一 STUN 消息类型、magic cookie、事务 ID 和消息长度。
(图)STUN 消息结构