在实时通信(如WebRTC、VoIP)领域,STUN(NAT会话穿透工具)与ICE(交互式连接建立)协议的组合是保障点对点连接稳定性的核心技术。当双方设备处于不同NAT环境时,ICE通过一系列步骤协商可用路径,其中第三步——服务器向客户端发起STUN请求——是连接检查的关键环节。那么,在这一步中,该请求必须包含哪些属性(attribute)?若缺少某属性,为何会导致握手失败?本文将结合RFC规范与实际部署,为您梳理其中的强制性要求。
ICE三步曲:从候选收集到连接检查
要理解第三步的“必要属性”,首先需回顾ICE的整体流程:
- 候选收集:客户端向STUN/TURN服务器发送绑定请求(Binding Request),获取自身公网地址及中继地址,形成候选列表。
- 候选交换:双方通过信令通道交换候选信息(SDP中携带)。
- 连接检查:双方互为服务器与客户端,向对方发送STUN绑定请求,测试候选对(Candidate Pair)的连通性。此处的第三步即指一方(通常称为“服务器”)向另一方(“客户端”)发送的STUN请求。
在ICE中,每一对候选的检查都由一个STUN事务完成。当主机A作为“控制方”向主机B发送请求时,该请求本质上扮演了“服务器”的角色——它发起验证,要求对方回复。根据RFC 5245(ICE)与RFC 5389(STUN),这份请求必须携带若干关键属性,否则对方会直接丢弃数据包,导致检查失败。
必须包含的属性清单
1. MESSAGE-INTEGRITY(消息完整性校验)
必要性:任何STUN消息若包含用户名属性(USERNAME),则必须同时包含MESSAGE-INTEGRITY。在ICE连接检查中,请求中会携带USERNAME属性(格式为“本地用户名:远程用户名”),因此MESSAGE-INTEGRITY必不可少。它通过HMAC-SHA1算法计算消息的哈希值,防止伪造或篡改。缺少该属性,接收方将无法认证消息来源,按规范应直接丢弃。
2. FINGERPRINT(指纹)
必要性:虽非强制,但RFC 5389建议所有STUN消息包含FINGERPRINT(CRC32校验)。在ICE的实际实现中(如libwebrtc),FINGERPRINT已成为事实标准。它用于区分STUN包与可能的非STUN流量(如漏包的RTP),并辅助检测传输层错误。若不加此属性,在某些NAT盒或中间件可能被误解而丢弃。
3. USE-CANDIDATE(使用候选)
必要性:这是ICE特有的属性,其值为空(无内容)。发送方设置该标志,表示希望将此候选对列入最终的提名列表。在普通连接检查中,该属性是必须的——若缺少USE-CANDIDATE,接收方不会将该候选对视为有效结选(nominated),即便链路可达,也不会进入连接控制阶段。RFC 5245明确要求,只有当请求中包含USE-CANDIDATE时,接收方才应在回复中携带NOMINATION(提名)信息。
4. PRIORITY(优先级)
必要性:每个候选都有计算好的优先级(基于类型、地址等),该值在请求中以32位整数形式传输。PRIORITY是强制属性,接收方根据该值决定是否交换候选对以及排序。若缺少此属性,接收方无法判断该候选的偏好等级,会视为非法请求。
5. ICE-CONTROLLING / ICE-CONTROLLED(控制角色)
必要性:ICE会话中,双方必须协商出“控制方”与“被控方”。控制方负责发起最终提名(nomination),被控方则被动应答。每个STUN请求中必须携带ICE-CONTROLLING或ICE-CONTROLLED属性之一(两者不可兼得),以表明发送方在本次检查中的角色。如果不包含任一属性,接收方无法确定自己应响应还是拒绝,导致死锁。RFC 5245要求该属性在连接检查阶段始终存在。
6. USERNAME(用户名)
必要性:用于标识对端的身份,与MESSAGE-INTEGRITY配合完成认证。在ICE中,USERNAME格式固定为“本地用户名+冒号+远程用户名”,每个请求必须包含。实际上,该属性是除上述属性之外的另一项强制项。若缺少USERNAME,接收方无法提取校验的密钥,后续所有校验均无法进行。
缺失任一属性的后果
试想,如果某客户端在第三步中发出的STUN请求缺少了USE-CANDIDATE,那么对端收到的将只是一个普通的连通性测试包,即使链路通顺,也不会将其标记为可用路径。双方会继续检查其他候选,直至超时,最终连接建立失败。同样,若缺少ICE-CONTROLLING,双方都可能认为自己是控制方,导致提名冲突,或陷入无限循环。
在实际网络环境中,许多NAT设备会依赖STUN消息中的FINGERPRINT来判断是否为有效包。若缺失该属性,某些路由器可能将其误判为畸形报文而直接丢弃,造成“可达但无法连接”的假象。
开发者必须重视的规范细节
RFC 5245第7.2.4节明确定义了STUN连接检查请求的格式:必须包含MESSAGE-INTEGRITY、USERNAME、PRIORITY、ICE-CONTROLLING/ICE-CONTROLLED,以及可选但推荐的FINGERPRINT和USE-CANDIDATE。尽管USE-CANDIDATE在严格意义上不算“每次必带”(非提名检查可不带),但在完整握手过程中,最终提名时必须携带。许多开源库(如libnice、pion/ice)会默认在所有连接检查请求中添加USE-CANDIDATE以及FINGERPRINT,以简化逻辑并提高兼容性。
结语
STUN-ICE交互的第三步,是建立可靠P2P连接的“临门一脚”。其中必须包含的MESSAGE-INTEGRITY、PRIORITY、角色属性和USERNAME等,不仅保障了安全性,更直接决定了候选对能否被正确提名。对于实时通信开发者而言,理解这些属性的强制性含义,有助于调试网络问题、优化协议栈,最终为用户带来更低延迟、更稳定的通话体验。随着WebRTC技术的广泛应用,这些底层细节正变得更加重要——它们虽不常被人提及,却是每一次成功连接的基石。