向SIP会话注入BYE消息强制挂断UAC失败问题排查
实验场景
分机111通过PBX呼叫分机222,从PBX提取Invite中的To、From(含标签)、Call-ID及通信IP/端口,构造BYE消息通过UDP发送给111号电话(CSeq使用无符号整数最大值,符合RFC中UAC接受更大CSeq的规则),但发送后电话未挂断。
原始发送的UDP报文:
BYE sip:111@172.31.253.20:5060 SIP/2.0 To: "Phone x111" <sip:111@mydomain.com>;tag=r1j.i3 From: "Phone x222" <sip:222@mydomain.com;user=phone>;tag=efbedc0a-cc6f-4163-b51b-84840ae16313 Call-ID: 6s8em8wuckjy2t40u01p1nucpcnta.@mydomain.com CSeq: 4294967295 BYE Max-Forwards: 70 User-Agent: Test-Agent Reason: Q.850;cause=41;text="Test Agent Clearing" Content-Length: 0
注:报文每行结尾为CRLF,末尾含空行;发送地址为Invite中111号电话的IP和端口,源地址为会话本地地址但端口不同(原端口占用),期望BYE端到端传输(不显示来自PBX)。
无效原因分析
- From头格式错误:From字段中的SIP URI
<sip:222@mydomain.com;user=phone>未闭合尖括号,属于语法错误,111的UA会直接丢弃不符合规范的SIP报文。 - 源端口不匹配触发会话校验:SIP UA会校验消息的源IP和端口是否与当前会话的远端(222的UA)一致,你的BYE源端口与原会话端口不同,UA会判定为非法消息,拒绝处理。
- 缺失会话验证信息:部分UA会要求SIP消息携带Authorization或Proxy-Authorization头进行完整性校验,未携带的话会直接拒绝BYE请求。
- Reason头潜在格式问题:虽然RFC 3326允许当前Reason头格式,但部分UA对文本引号的处理或字段格式要求严格,可能导致解析失败。
修改方案
修正From头语法错误
补全From头中SIP URI的闭合尖括号,修正后内容:From: "Phone x222" <sip:222@mydomain.com;user=phone>;tag=efbedc0a-cc6f-4163-b51b-84840ae16313模拟原会话的源端口发送
实验场景下可暂时释放原会话占用的端口,或使用RAW套接字修改UDP报文的源端口(需系统权限),确保BYE的源IP和端口与222 UA发送消息的地址完全一致,绕过UA的会话合法性校验。添加会话验证头
检查原会话中Invite或后续消息的Authorization/Proxy-Authorization头,将对应验证信息复制到BYE报文中,确保UA认可消息合法性。简化报文(排除干扰)
暂时移除Reason头,只保留核心SIP字段(BYE行、To、From、Call-ID、CSeq、Max-Forwards、Content-Length),测试是否能触发挂断,确认核心字段有效后再逐步添加扩展头。优化CSeq值(可选)
虽然RFC允许使用最大值,但优先使用比111 UA收到的最后一个CSeq编号更大的合理值(比如原Invite的CSeq+1),避免部分UA对极端值的异常处理。
修改后的示例报文
BYE sip:111@172.31.253.20:5060 SIP/2.0 To: "Phone x111" <sip:111@mydomain.com>;tag=r1j.i3 From: "Phone x222" <sip:222@mydomain.com;user=phone>;tag=efbedc0a-cc6f-4163-b51b-84840ae16313 Call-ID: 6s8em8wuckjy2t40u01p1nucpcnta.@mydomain.com CSeq: 4294967295 BYE Max-Forwards: 70 User-Agent: Test-Agent Content-Length: 0
内容的提问来源于stack exchange,提问作者TSG

