Node.js UDP实现SIP注册Asterisk始终遭401未授权问题排查
1. 核对请求头完整性
第一次发送REGISTER请求时无需携带Authorization,但必须包含以下核心请求头:
From: 格式为<sip:用户名@域名/IP>;tag=随机字符串,tag是本地生成的唯一标识,不可省略To: 与From的SIP URI完全一致,暂无需带tag,示例:<sip:用户名@域名/IP>Call-ID: 全局唯一字符串,同一注册周期内建议保持不变CSeq: 格式为序号 REGISTER,序号从1开始,每次请求递增Contact: 必须包含客户端SIP地址,示例:<sip:用户名@客户端IP:端口>;expires=3600,expires字段控制注册有效期Via: 格式为SIP/2.0/UDP 客户端IP:端口;branch=z9hG4bK随机字符串,branch必须以z9hG4bK开头(SIP 2.0强制要求)Max-Forwards: 建议设为70,示例:Max-Forwards: 70Content-Length: 无消息体时必须设为0,示例:Content-Length: 0
所有头字段需以\r\n分隔,最后以\r\n\r\n结尾,确保Asterisk能正确解析请求。
2. 验证Digest认证计算(收到401后的第二次请求)
Asterisk返回401时会携带WWW-Authenticate头,从中提取realm、nonce、algorithm(通常为MD5),严格按以下步骤计算Authorization头:
- 计算HA1:
MD5(用户名:realm:密码),注意realm需完全匹配响应中的值(包括引号内的内容) - 计算HA2:
MD5(REGISTER:sip:目标域名/IP),方法名必须大写,SIP URI要与请求行中的URI完全一致 - 计算Response:
MD5(HA1:nonce:HA2) - 组装Authorization头:
Authorization: Digest username="用户名", realm="realm值", nonce="nonce值", uri="sip:目标域名/IP", response="计算出的Response", algorithm=MD5
常见错误点:
- realm/nonce复制不全或格式错误(比如漏了引号)
- HA2中的方法名小写或URI与请求行不一致
- 用户名/密码含特殊字符时未按UTF-8编码计算MD5
3. 检查Asterisk配置与日志
- 配置核对:
- 若使用传统SIP(chan_sip),检查
sip.conf中是否存在对应用户,secret字段密码是否正确,type设为user或peer,allowguest设为no - 若使用PJSIP,检查
pjsip.conf中endpoint是否关联正确的auth配置,认证类型为md5
- 若使用传统SIP(chan_sip),检查
- 日志分析:
- 执行
sip set debug on(chan_sip)或pjsip set logger on(PJSIP)开启调试 - 查看Asterisk是否在日志中提示请求解析错误(如缺少某头字段)
- 关注认证失败日志(如
Failed to authenticate user),日志会明确提示错误原因(如nonce不匹配、Response计算错误)
- 执行
4. Node.js UDP发送校验
- 确保UDP数据包完整,SIP请求必须以
\r\n\r\n结尾,避免因截断导致Asterisk无法解析 - 确认发送的目标IP和端口与Asterisk的SIP监听端口一致(默认5060 UDP)
- 解析401响应时,用正则正确提取
WWW-Authenticate中的参数,避免因匹配错误导致计算用的realm/nonce值不正确
内容的提问来源于stack exchange,提问作者Nik Hendricks
相关产品推荐
相关产品推荐

