基础知识
连通性挑战NAT
**ICE需要处理多种NAT类型的连通性问题。**可学习往期NAT文章
STUN协议
TURN中继服务
关联:NAT(网络地址转换)是一种网络技术,用于在私有网络和公共互联网之间转换IP地址和端口,NAT技术作为解决IPv4地址枯竭的临时方案,将私有IP地址转换为公网IP地址,使多个设备能够共享有限的公网IP资源。而STUN(会话穿越实用工具)是一种协议,旨在帮助客户端发现其在NAT设备后面的公网地址(即server reflexive地址)以及检测NAT类型,从而实现NAT穿越,确保点对点通信的建立。TURN则是用于STUN无法实现NAT穿越,使用中继服务节点,来协调C/S双端数据收发。
1)概述
ICE(Interactive Connectivity Establishment,交互式连通建设形式)是WebRTC中用于解决NAT穿越问题的核心技术。ICE的基本思想是每个代理都有各种各样的Candidate Transport地址(IP地址和端口的组合),用于与其他代理进行通信。ICE协议解决了现代网络中NAT设备和防火墙带来的连接难题,使浏览器和设备能够直接建立实时媒体传输连接。
ICE模式
ICE协议中角色分为controlling和controlled两种。Full ice agent必须是controlling role,lite ice agent是controlled:
-
Offer(主动发起)的一方为controlling角色 。
-
Answer(被动接受)的一方为controlled角色 。
SRS服务器采用Lite ICE模式。ICE模式分为两种:
-
FULL ICE:双方都要进行连通性检查,完成的走一遍流程
-
Lite ICE:在FULL ICE和Lite ICE互通时,只需要FULL ICE一方进行连通性检查,Lite一方只需回应response消息
SRS仅支持lite ice模式,该模式对于部署在公网的设备比较常用。在SDP中可以看到**a=ice-lite
**字样来标识。只回应不主动
ICE状态管理
ICE定义了五种状态:
-
Waiting:还未开始连通性检查
-
Frozen:连通性检查还未开始
-
In-Progress:连通性检查已开始但未结束
-
Succeeded:连通性检查完成并成功
-
Failed:检查失败

ICE候选地址类型
Host候选地址
Host候选地址是通过绑定到主机上接口(物理或虚拟,包括VPN接口)的IP地址获得的。这是设备本地网络接口的直接地址,具有最高的连接优先级。在候选地址中标记为"typ host"
Server Reflexive候选地址
Server reflexive候选地址是通过STUN或TURN服务器收集的,代表设备在经过NAT转换后在公网侧的映射地址。在SDP中通常标记为"typ srflx"。
当向STUN服务器发送STUN Binding Request时,服务器返回的STUN Binding Response中的XOR-MAPPED-ADDRESS属于Server Reflexive候选地址
Peer Reflexive候选地址
Peer reflexive候选地址是在ICE后期阶段,作为连通性检查的结果获得的。当对等端发送数据包时发现的新候选地址。标记为"typ prflx"
在ICE连通性检查阶段,当对等端(peer)返回STUN binding response时,其中的XOR-MAPPED-ADDRESS属于Peer Reflexive候选地址,通过连通性检查发现新的网络路径。
Relayed候选地址
Relayed候选地址通过TURN服务器获得,用于在无法打洞建立直接连接时进行数据中继。
候选地址收集过程
候选地址类型(Host > Server Reflexive > Relayed)
候选地址类型 Type Preference推荐值 说明 Host 126 本地网络接口地址,延迟最低,优先级最高 Peer-reflexive 110 对等端反射地址,连通性检查中发现 Server-reflexive 100 服务器反射地址,通过STUN服务器获得 Relayed 0 中继地址,通过TURN服务器分配,优先级最低
候选地址格式
根据RFC 8839规范,以下是一个典型的SDP候选地址格式示例:
a=candidate:2 1 UDP 1694498815 192.0.2.3 45664 typ srflx raddr
203.0.113.141 rport 8998

语义:在NAT环境下,设备的公网映射地址为192.0.2.3,端口为45664,基础地址(即设备的本地地址)为203.0.113.141,基础端口为8998,使用UDP协议,候选地址的唯一标识符(foundation)为2,组件ID为1(RTP流),优先级为1694498815。
字段名称 | 示例值 | 数据类型 | 取值范围 | 详细说明 |
---|---|---|---|---|
Foundation | 2 | 字符串 | 1-32个字符 | 唯一标识符,用于标识具有相同特性的候选地址。相同foundation的候选地址具有相同的类型、基础地址、STUN服务器来源和传输协议 |
Component ID | 1 | 正整数 | 1-256 | 标识数据流组件类型:1=RTP组件(音视频数据),2=RTCP组件(控制信息) |
Transport | UDP | 字符串 | UDP/TCP | 指定传输协议,WebRTC中主要使用UDP协议进行实时音视频传输 |
Priority | 1694498815 | 正整数 | 1 到 2^31-1 | 候选地址优先级,数值越高优先级越高。计算公式:(2^24)×(type preference) + (2^8)×(local preference) + (256-component ID) |
Connection Address | 192.0.2.3 | IP地址 | IPv4/IPv6/FQDN | 候选地址的IP地址,支持IPv4、IPv6地址和完全限定域名 |
Port | 45664 | 正整数 | 1-65535 | 传输端口号,与IP地址组合形成完整的网络传输地址 |
Candidate Type | typ srflx | 关键字 | host/srflx/prflx/relay | 候选地址类型标识:host=本地地址,srflx=服务器反射地址,prflx=对等端反射地址,relay=中继地址 |
Related Address | raddr 203.0.113.141 | IP地址 | IPv4/IPv6或省略 | 相关base基础地址,用于诊断。对于反射候选地址,表示对应的本地基础地址 |
Related Port | rport 8998 | 正整数 | 1-65535或省略 | 相关基础端口,与Related Address配对使用 |
特殊规则说明
字段组合 | 规则 | 示例/说明 |
---|---|---|
Host候选地址 | 必须省略raddr和rport | 本地地址无需相关地址信息 |
反射候选地址 | raddr/rport指向基础地址 | 如示例中203.0.113.141:8998为本地基础地址 |
中继候选地址 | raddr/rport指向TURN服务器映射地址 | 显示TURN服务器分配的映射关系 |
隐私保护 | 地址可设为0.0.0.0/::/端口设为9 | 用于隐藏真实的相关地址信息 |
2) ICE完整流程
1. 收集Candidates
-
获取本机host address
-
从STUN服务器获取srvflx address
-
从TURN服务器获取relay address
-
生成foundation标识
2. 删除重复Candidate
如果两个candidate的地址一样且Base地址也一样,则删除重复项。
3. 交换Candidates
通过SDP协商交换candidate信息,包括type、foundation、base、component id、transport等。
4. 生成Candidate Pairs
将Component ID和transport protocol相同的candidates组成pair,按优先级排序供连通性检查使用。
5. 连通性检查
每个对等端使用候选地址对(每端一个候选地址)向另一端发送STUN绑定请求,验证路径是否可达。主要通过:
-
使用STUN binding request/response进行检查,携带USERNAME属性,两端在SDP协商时交换ice-pwd和ice-ufrag,以得对端用户名和密码。需注意是否有加密规则!
-
采用STUN short-term credential方式认证(stun短期认证),也就过⼀段时间如果没有stun包发送时, 这个连接会过期失效,因此需要不断地发送stun包并收到回复的stun包,⽤来保持连接有效性。刚 开始建联时,⼤概以 50 ms间隔频率发送,后期稳定后是以 2 . 5 s的间隔频率发送,维持链接有效性。
-
包含Ordinary checks和Triggered checks两种方式
Ordinary Checks 是由ICE代理根据预设定时器周期性触发的连通性检查动作,包括向远端候选地址发送STUN Binding Request,并对远端发来的同类请求进行Binding Response。通过这种双向请求/响应,双方可以确认候选地址对在两端网络环境中的可用性与双向连通性。
特性 | Ordinary Checks | Triggered Checks |
---|---|---|
触发方式 | 定时器周期性触发 | 收到远端STUN请求后立即触发 |
目的 | 按优先级系统性覆盖所有候选地址对 | 加速已探测到的候选地址对的双向连通性验证 |
发送方角色 | 任一Full ICE实现的代理 | 主要用于Full ICE实现,当收到远端请求自动回应 |
状态更新 | 更新Check List中的状态 (Frozen→Waiting→In-Progress) | 标记对应候选对为In-Progress并快速完成验证 |
连通性检查的流程:
-
初始化:在收发Offer/Answer并交换候选信息后,双方各自生成Check List,并对候选对赋予Priority与Foundation。
-
定期发起:每当定时器Ta触发时,代理从Check List中选择下一个"Waiting"状态的候选对,发送STUN Binding Request。
-
接收与回应:收到请求的一端即刻发送STUN Binding Response,双方均标记该候选对为"Succeeded"并更新关联Foundation下的其他候选对状态。
-
完结条件:当每个组件至少有一个候选对通过验证后,由Controlling Agent发起Nomination或Aggressive Nomination以选定最终用于媒体传输的候选对,ICE进程结束。
6. 生成ValidList
将连通性检查成功的candidate pair按优先级排序加入validlist。
7. 提名Candidate Pair
Nomination(提名)是ICE协议中的关键步骤,用于在多个可用的候选地址对中选择最终用于媒体传输的连接路径。控制方通过在STUN检查中包含USE-CANDIDATE属性来提名候选对。
由controlling角色提名,分为普通提名和进取型提名两种方式:
-
普通提名:做两次连通性检查,第二次带上USE-CANDIDATE属性
-
进取型提名:每次检查都带上USE-CANDIDATE属性
角色分工
-
Controlling Agent(控制端):负责发起nomination,决定选择哪一对连接作为最终的媒体通道
-
Controlled Agent(被控端):被动接受nomination,当收到带有USE-CANDIDATE标志的STUN请求时接受这次提名
Aggressive Nomination(激进提名)特点:
在每个STUN请求中都携带USE-CANDIDATE标志5
一旦第一次检查成功,ICE处理就完成,不需要第二次STUN请求
减少了提名所需的时间和消息交换次数
Regular Nomination(常规提名)特点:
先完成常规的连通性检查(不带USE-CANDIDATE标志)
检查成功后,controlling端再次发送带有USE-CANDIDATE标志位的STUN Binding Request。需要额外的一次握手过程
在WebRTC实现中,浏览器通常使用激进提名方式以加快连接建立速度。当需要使用renomination功能时,需要在SDP中添加
a=ice-options:renomination
标识。
8. 选择最终传输地址
在提名的valid pair里选择优先级最高的作为传输地址,然后建立DTLS连接 SRTP传输数据。
总结

4)技术细节
角色冲突解决
当两端角色都为controlling或controlled时发生冲突,在连通性检查阶段,要求发送binding request消息⾥必须要带上tie-breaker属性。通过比较tie-breaker值大小解决,值大的为controlling,并回应487错误给对端进行角色切换。
保活机制
ICE通道需要进行保活,采用STUN binding request或indication,如果没有收到响应则会重传直到最大重传次数。
SDP和ICE并行
如果使用单独信令交换 sdp中应该存在:
a=ice-options:trickle
使用trickle方式,sdp里面描述媒体信息和ice后选项的信息可以分开传输,先发送sdp过去,在收集地址信息,目的是为了同时进行,而不是等待收集地址信息完成后才开始。
多说一点,其实sdp也是通过信令传输的,理论上sdp是可以不通过信令的,可以在等待两个peer建立完连接后,在交换sdp是可以的。