ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

IMS注册与CALL信令分析:从403到完整呼叫链路排查

IMS注册与CALL信令分析:从403到完整呼叫链路排查 简介这份资源聚焦IMSIP多媒体子系统的注册流程与MO CALL场景下的SIP信令分析面向从事VoLTE/VoWiFi终端开发、协议栈调试及网络优化的工程师与学习者帮助理解IMS注册的完整链路与呼叫建立过程中的关键信令字段。压缩包内共1个docx文档约144KB以图文笔记形式整理便于对照日志逐条排查。内容涵盖DS通知LTE服务可用、获取APN列表与属性、触发PDN连接请求、发送SIP注册消息及通知CM注册状态变化等注册步骤并逐条拆解IMS_SIP_INVITE/INFORMAL_RESPONSE、INVITE消息中的Call-ID、Via、Contact、Route、P-Preferred-Identity、Allow等字段结合具体SDP与AMR编解码协商示例说明呼叫建立、维持与释放机制。目前已有1539人学习下载适合需要掌握IMS信令排错思路与协议细节的读者参考。1. IMS 注册与 CALL 信令分析从一次 403 到完整呼叫链路VoLTE 用户投诉“打不出去电话”核心网侧看到的往往只是一条 SIP 403 或 408。要定位到底是注册态失效、鉴权失败还是 CALL 阶段被 S-CSCF 拒绝唯一可靠的办法是把 IMS 注册和 CALL 的 SIP 信令逐条拆开看。IMS 注册解决的是“用户能不能被网络找到”CALL 信令解决的是“找到之后能不能建立会话”两者共用一套 SIP 消息体系但状态机、鉴权头域和路由逻辑完全不同。这篇文章面向做 VoLTE/VoWiFi 对接、IMS 核心网运维、SIP 信令服务器开发的工程师把注册流程、CALL 流程、抓包分析方法、常见错误码排查一次讲透让你拿到一个 pcap 就能自己定位问题。2. IMS 注册流程从 REGISTER 到 200 OK 的完整状态机2.1 注册涉及的网元与接口IMS 注册不是单一网元的事。UE 发出 REGISTER 后先经过 P-CSCF再转发到 I-CSCFI-CSCF 向 HSS 查询用户注册的 S-CSCF 能力集选好 S-CSCF 后把 REGISTER 转过去S-CSCF 再向 HSS 取鉴权向量最终由 UE 完成鉴权响应。整条链路涉及 Gm、Mw、Cx、ISC 等多个接口。网元接口作用UE ↔ P-CSCFGmSIP 信令入口IPSec 安全关联P-CSCF ↔ I-CSCFMw转发 REGISTER携带 Path 头域I-CSCF ↔ HSSCxUAR/UAA 查询 S-CSCF 能力S-CSCF ↔ HSSCxMAR/MAA 取鉴权向量SAR/SAA 注册状态S-CSCF ↔ I-CSCFMw返回 200 OK 或 4xx 错误理解这张表的意义在于当你抓到一条 401 Unauthorized它可能来自 P-CSCF 也可能来自 S-CSCF排查方向完全不同。P-CSCF 返回 401 通常是 IPSec 协商问题S-CSCF 返回 401 才是正常的鉴权挑战。2.2 首次注册与重注册的 SIP 消息序列首次注册的完整流程分两轮 REGISTER。第一轮不带鉴权信息S-CSCF 返回 401 并携带 WWW-Authenticate 头域里面包含 nonce、realm、algorithm 和 qop。UE 用 ISIM 卡里的密钥计算出 response 值在第二轮 REGISTER 的 Authorization 头域里带上。S-CSCF 验证通过后返回 200 OK并在响应中携带 Service-Route 和 P-Associated-URI。下面是一段典型的首次注册消息序列用 SIPp 内置场景可以复现# 使用 SIPp 模拟 IMS 注册需要先安装 sipp 并准备 ISIM 参数 sipp -sf register_ims.xml \ -s 460001234567890ims.mnc000.mcc460.3gppnetwork.org \ -i 192.168.10.100 \ -p 5060 \ -m 1 \ -trace_msg \ -trace_err \ 192.168.20.1:5060-sf指定自定义 XML 场景文件-s是 IMPIIP Multimedia Private Identity-i和-p指定本地监听地址和端口-m 1表示只跑一次呼叫-trace_msg把每条 SIP 消息落盘方便后续分析。实际对接时-s必须和 ISIM 卡里写入的 IMPI 一致否则 HSS 侧查不到用户I-CSCF 会直接回 404 User Not Found。重注册的触发条件有两个注册有效期expires到期前重新注册或者网络侧发起网络主动去注册。expires 值通常在 200 OK 的 Contact 头域里默认 600000 秒但运营商常配成 3600 或 1800 秒。如果 UE 在 expires 超时前没有重注册S-CSCF 会删除注册状态后续 CALL 信令直接回 480 Temporarily Unavailable。2.3 鉴权失败与 403/401 的区分方法401 和 403 是注册阶段最常见的两个错误码但含义完全不同。401 是鉴权挑战属于正常流程的一部分403 是鉴权失败说明 UE 计算的 response 和 S-CSCF 期望值不一致。排查 403 时按以下顺序检查确认 ISIM 卡里的 IMPI 和 IMPU 是否与 HSS 开户数据一致。常见问题是 IMPU 多写或少写了一个数字。检查 Authorization 头域里的 nonce 是否和 401 响应中的 nonce 完全一致。有些 UE 会重新生成 nonce导致校验失败。核对 algorithm 字段。AKAv1-MD5 和 AKAv2-MD5 的密钥派生方式不同HSS 和 UE 必须匹配。如果使用 IPSec检查 P-CSCF 下发的 Security-Client 和 Security-Server 头域是否被 UE 正确解析。提示抓包时如果只看到 403 而看不到前面的 401说明抓包点选错了。401 和 403 之间隔着 UE 的鉴权计算过程必须在 P-CSCF 的 Gm 接口抓才能看到完整两轮 REGISTER。3. CALL 信令分析INVITE 到 BYE 的逐跳拆解3.1 INVITE 消息的关键头域与 SDP 协商CALL 流程从 INVITE 开始。主叫 UE 发出 INVITE里面必须包含 From、To、Contact、P-Preferred-Identity 和 SDP offer。SDP offer 里列出 UE 支持的编解码、媒体类型和 IP 端口。P-CSCF 收到后插入 P-Called-Party-ID 和 Route 头域转发给 S-CSCF。S-CSCF 根据被叫的 IMPU 查询 HSS找到被叫注册的 S-CSCF再路由到被叫侧。INVITE 里最容易出问题的是 SDP 协商。如果主叫只 offer 了 AMR-WB 而被叫只支持 AMR-NB被叫会回 488 Not Acceptable Here。另一种常见情况是主叫的 SDP 里 c 行写的 IP 是私网地址P-CSCF 没有做媒体面锚定导致被叫侧无法建立 RTP 流。# 用 Python 解析 pcap 中的 SIP INVITE提取关键头域和 SDP 信息 from scapy.all import rdpcap, SIP, Raw packets rdpcap(ims_call.pcap) for pkt in packets: if pkt.haslayer(SIP): sip pkt[SIP] if sip.method bINVITE: print(fCall-ID: {sip.fields.get(call_id, N/A)}) print(fFrom: {sip.fields.get(from, N/A)}) print(fTo: {sip.fields.get(to, N/A)}) print(fContact: {sip.fields.get(contact, N/A)}) if pkt.haslayer(Raw): payload pkt[Raw].load.decode(errorsignore) if maudio in payload: for line in payload.split(\r\n): if line.startswith((m, artpmap, c)): print(fSDP: {line})这段脚本用 Scapy 读取 pcap过滤出 INVITE 消息打印 Call-ID、From、To、Contact 以及 SDP 中的媒体行和编解码映射。call_id是贯穿整个呼叫的唯一标识用它可以在 Wireshark 里过滤出一次完整呼叫的所有消息。artpmap行告诉你实际协商的编解码如果只看到AMR/8000而没有AMR-WB/16000说明 VoLTE 高清语音没有生效。3.2 183/180/200 OK 与 PRACK 的时序关系INVITE 发出后被叫侧可能回 100 Trying、183 Session Progress、180 Ringing最后是 200 OK。183 和 180 的区别在于183 携带 SDP answer表示被叫已经准备好媒体资源180 只是振铃提示不携带 SDP。如果网络启用了 PRACKProvisional Response AcknowledgmentUE 收到 183 后必须回 PRACK否则被叫侧会重传 183 直到超时。PRACK 的启用由 Supported: 100rel 头域决定。主叫在 INVITE 里带 Supported: 100rel被叫在 183 里带 Require: 100rel主叫就必须回 PRACK。如果主叫没回 PRACK被叫侧会每隔 500ms 重传 183通常重传 6 次后回 504 Server Time-out。排查 CALL 建立失败时重点看三个时间点INVITE 到 100 Trying 的间隔。超过 200ms 说明 P-CSCF 或 I-CSCF 处理慢。183 到 PRACK 的间隔。超过 500ms 说明 UE 侧处理有问题。PRACK 到 200 OK 的间隔。超过 1s 说明被叫侧媒体资源分配慢。3.3 呼叫释放BYE 与 CANCEL 的使用边界BYE 和 CANCEL 都用于释放呼叫但触发条件不同。CANCEL 只能在收到最终响应200 OK之前发送用于取消正在建立的呼叫。BYE 只能在收到 200 OK 之后发送用于正常挂断已建立的会话。一个典型翻车场景是主叫在收到 180 Ringing 后挂断UE 发了 CANCEL但被叫侧已经回了 200 OK此时 CANCEL 会被忽略主叫必须再发 BYE。如果 UE 只发了 CANCEL 没发 BYE被叫侧会一直保持会话直到超时产生“单通”投诉。# 用 tshark 过滤一次完整呼叫的 SIP 消息按时间排序 tshark -r ims_call.pcap \ -Y sip \ -T fields \ -e frame.time_relative \ -e sip.Method \ -e sip.Status-Code \ -e sip.Call-ID \ -e sip.r-uri \ -E separator, \ | sort -t, -k1 -n-Y sip是显示过滤器只保留 SIP 协议报文。-T fields配合-e提取指定字段frame.time_relative给出相对时间方便看消息间隔。sip.Method和sip.Status-Code分别对应请求方法和响应码。输出按时间排序后一眼就能看出 INVITE、183、PRACK、200 OK、BYE 的先后顺序和间隔。4. 抓包与信令关联把 REGISTER 和 INVITE 串起来看4.1 在 P-CSCF 侧抓包的过滤表达式P-CSCF 是 IMS 信令的必经之路在 P-CSCF 的 Gm 接口抓包能同时看到注册和呼叫。但 P-CSCF 通常处理大量用户直接抓全量包会丢包。推荐用 BPF 过滤器缩小范围# 在 P-CSCF 上抓指定 IMPU 的 SIP 信令 tcpdump -i eth0 \ -w ims_ue1.pcap \ -s 0 \ host 192.168.10.100 and port 5060-i eth0指定网卡-w写入文件-s 0抓完整包不截断host和port限定 UE 的 IP 和 SIP 端口。如果 UE 使用 IPSecSIP 消息是加密的需要在 P-CSCF 上配置 IPSec 解密或者用支持 IPSec 的解码工具。常见做法是在 P-CSCF 的日志里开启 SIP 消息明文记录配合抓包交叉验证。4.2 用 Call-ID 和 IMPU 关联注册与呼叫一次完整的用户行为是UE 先注册注册成功后发起呼叫。在 Wireshark 里先用sip.Call-ID过滤出注册的 Call-ID再用sip.From.user或sip.To.user过滤出该用户的所有消息。注册的 Call-ID 和呼叫的 Call-ID 不同但 IMPU 相同。关联分析时重点看注册的 200 OK 里 Contact 头域的 expires 值确认注册有效期。呼叫的 INVITE 里 From 头域是否和注册的 IMPU 一致。如果注册已过期INVITE 会被 S-CSCF 回 480此时需要先解决注册问题。注意有些 UE 在注册失效后不会立即重注册而是继续发 INVITE导致 CALL 失败。排查时要先确认注册状态再看 CALL 信令。5. 避坑与排查IMS 注册和 CALL 信令的 5 个血泪教训5.1 现象REGISTER 一直重传收不到 401原因P-CSCF 没有回 401通常是 IPSec 安全关联未建立。UE 发的 REGISTER 是明文但 P-CSCF 期望 IPSec 加密直接丢弃。解决检查 P-CSCF 下发的 Security-Server 头域确认 UE 是否支持对应的加密算法。如果 UE 不支持 IPSec需要在 P-CSCF 上关闭 IPSec 强制策略或者换用支持 IPSec 的 UE。5.2 现象收到 401 后 UE 不回第二轮 REGISTER原因UE 解析 WWW-Authenticate 头域失败常见于 nonce 里包含特殊字符或 algorithm 字段不被识别。解决抓包对比 401 里的 algorithm 和 UE 支持的算法列表。如果 UE 只支持 AKAv1-MD5 而网络下发 AKAv2-MD5需要修改 HSS 配置。5.3 现象INVITE 发出后收到 100 Trying 但没有后续响应原因I-CSCF 向 HSS 查询被叫 S-CSCF 时超时或者被叫未注册。解决检查 I-CSCF 的 Cx 接口日志确认 UAR/UAA 是否正常。如果被叫未注册S-CSCF 会回 480 Temporarily Unavailable此时需要先让被叫完成注册。5.4 现象183 之后没有 PRACK被叫侧重传 183原因主叫 UE 没有正确处理 Require: 100rel或者 PRACK 发送到了错误的地址。解决检查主叫 INVITE 里的 Supported 头域和 Contact 地址。PRACK 必须发到 183 的 Contact 地址而不是 INVITE 的 Request-URI。5.5 现象BYE 发出后收到 481 Call/Transaction Does Not Exist原因BYE 里的 Call-ID 或 From tag 和 INVITE 不一致或者对话已经超时被网络侧清除。解决对比 INVITE 和 BYE 的 Call-ID、From tag、To tag。三个字段必须完全一致。如果对话超时检查 S-CSCF 的对话定时器配置通常 session-expires 默认 1800 秒。6. 进阶技巧用 SIPp 自定义场景复现注册与呼叫异常6.1 构造带鉴权的 REGISTER 场景SIPp 自带的 register 场景只发一轮 REGISTER不带鉴权。要复现完整的鉴权流程需要自定义 XML 场景在收到 401 后计算 response 并发送第二轮 REGISTER。关键是在 XML 里用[authentication]关键字SIPp 会自动处理 MD5 鉴权。!-- register_auth.xml带鉴权的 IMS 注册场景 -- scenario nameIMS Register with Auth send retrans500 ![CDATA[ REGISTER sip:[remote_ip] SIP/2.0 Via: SIP/2.0/[transport] [local_ip]:[local_port];branch[branch] From: sip:[service][remote_ip];tag[call_number] To: sip:[service][remote_ip] Call-ID: [call_id] CSeq: 1 REGISTER Contact: sip:[service][local_ip]:[local_port] Expires: 3600 Content-Length: 0 ]] /send recv response401 authtrue / send retrans500 ![CDATA[ REGISTER sip:[remote_ip] SIP/2.0 Via: SIP/2.0/[transport] [local_ip]:[local_port];branch[branch] From: sip:[service][remote_ip];tag[call_number] To: sip:[service][remote_ip] Call-ID: [call_id] CSeq: 2 REGISTER Contact: sip:[service][local_ip]:[local_port] Expires: 3600 [authentication username[service] passwordsecret] Content-Length: 0 ]] /send recv response200 rtdtrue / /scenarioauthtrue告诉 SIPp 在收到 401 后自动提取 WWW-Authenticate 头域。[authentication username... password...]是 SIPp 的内置关键字它会根据 nonce、realm、method 和密码计算 response 值。实际使用时password 要替换成 ISIM 卡里的密钥或者用-ap参数从外部文件读取。rtdtrue记录往返时延方便统计注册耗时。6.2 用 SIPp 模拟 CALL 并注入异常模拟 CALL 时SIPp 需要同时处理 INVITE、PRACK、ACK 和 BYE。下面是一个简化的 CALL 场景重点演示如何在 183 后发送 PRACK!-- call_prack.xml带 PRACK 的呼叫建立场景 -- scenario nameIMS Call with PRACK send retrans500 ![CDATA[ INVITE sip:[service][remote_ip] SIP/2.0 Via: SIP/2.0/[transport] [local_ip]:[local_port];branch[branch] From: sip:caller[local_ip];tag[call_number] To: sip:[service][remote_ip] Call-ID: [call_id] CSeq: 1 INVITE Contact: sip:caller[local_ip]:[local_port] Supported: 100rel Content-Type: application/sdp Content-Length: [len] v0 ocaller 1 1 IN IP4 [local_ip] s- cIN IP4 [local_ip] t0 0 maudio 49170 RTP/AVP 97 artpmap:97 AMR/8000 ]] /send recv response100 optionaltrue / recv response183 rtdtrue / send ![CDATA[ PRACK sip:[remote_ip] SIP/2.0 Via: SIP/2.0/[transport] [local_ip]:[local_port];branch[branch] From: sip:caller[local_ip];tag[call_number] To: sip:[service][remote_ip][peer_tag_param] Call-ID: [call_id] CSeq: 2 PRACK Content-Length: 0 ]] /send recv response200 / recv response180 optionaltrue / recv response200 rtdtrue / send ![CDATA[ ACK sip:[remote_ip] SIP/2.0 Via: SIP/2.0/[transport] [local_ip]:[local_port];branch[branch] From: sip:caller[local_ip];tag[call_number] To: sip:[service][remote_ip][peer_tag_param] Call-ID: [call_id] CSeq: 1 ACK Content-Length: 0 ]] /send pause milliseconds2000 / send ![CDATA[ BYE sip:[remote_ip] SIP/2.0 Via: SIP/2.0/[transport] [local_ip]:[local_port];branch[branch] From: sip:caller[local_ip];tag[call_number] To: sip:[service][remote_ip][peer_tag_param] Call-ID: [call_id] CSeq: 3 BYE Content-Length: 0 ]] /send recv response200 / /scenario[peer_tag_param]是 SIPp 自动填充的 To tag来自 183 或 180 响应。optionaltrue表示该消息可以不存在避免因为网络不回 100 Trying 导致场景失败。pause milliseconds2000模拟通话 2 秒后挂断。实际压测时可以把pause改成随机值模拟不同通话时长。6.3 用 Wireshark 统计注册成功率和呼叫建立时延Wireshark 的 Statistics 菜单里有 SIP 统计功能但更灵活的方式是用 tshark 导出字段后用脚本统计。下面这条命令统计注册成功率# 统计 REGISTER 请求和 200 OK 响应的数量 tshark -r ims_register.pcap \ -Y sip.Method \REGISTER\ or sip.Status-Code 200 \ -T fields \ -e sip.Method \ -e sip.Status-Code \ | awk -F\t $1 REGISTER { reg } $2 200 { ok } END { printf REGISTER: %d, 200 OK: %d, Success Rate: %.2f%%\n, reg, ok, (ok/reg)*100 } -Y过滤出 REGISTER 请求和 200 OK 响应-T fields提取方法和状态码。awk 脚本分别计数最后计算成功率。如果成功率低于 95%说明注册流程存在系统性问题需要检查 P-CSCF 的 IPSec 配置或 HSS 的鉴权向量生成逻辑。呼叫建立时延的统计类似用frame.time_relative计算 INVITE 到 200 OK 的间隔# 统计 INVITE 到 200 OK 的时延 tshark -r ims_call.pcap \ -Y sip.Method \INVITE\ or sip.Status-Code 200 \ -T fields \ -e frame.time_relative \ -e sip.Method \ -e sip.Status-Code \ -e sip.Call-ID \ | awk -F\t $2 INVITE { start[$4] $1 } $3 200 start[$4] { delay $1 - start[$4] printf Call-ID: %s, Setup Delay: %.3f s\n, $4, delay delete start[$4] } 这段脚本用 Call-ID 关联 INVITE 和 200 OK计算每条呼叫的建立时延。VoLTE 的典型建立时延在 1.5 到 3 秒之间超过 5 秒就需要排查是哪个网元处理慢。我一般会把这个脚本存成sip_delay.sh每次拿到新 pcap 先跑一遍心里有个底再逐条看信令。做 IMS 信令分析这些年最大的教训是不要一上来就盯着错误码看先把完整消息序列拉出来确认注册态和对话态是否正常再去抠具体头域。很多所谓的“信令异常”其实是注册过期或者对话超时导致的连锁反应。希望帮到你。本文还有配套的精品资源点击获取
返回列表