呼叫身份
What
SIP 里主叫身份分三层,抓包时要分开读:From(声明)、P-Asserted-Identity(可信网断言)、Identity / `RFC8224`_(密码学认证)。三者可以同时出现,含义不同,不必相同。
Abstract
RFC3325 的 PAI 只在 trusted 域传递,RFC 5411 也指出它部署极广。 RFC4916 Connected Identity 告诉主叫实际接听的是谁。 STIR/SHAKEN 解决 PSTN 侧“这个号码是不是呼叫者拥有的”,与 PAI 不是同一层。
Why
弹屏、计费、呼出显示若用 From,会被话机随意填写,导致找错客户或主叫被运营商拦截。
把 PAI 和 STIR 混为一谈:内网断言过了,出 PSTN 仍可能被当诈骗号码。
出网不剥 PAI、不尊重 Privacy,会把内部身份泄到不可信 UA。
How
三层对照(不要混)
层 |
Header |
谁写、凭什么信 |
抓包时用来做什么 |
|---|---|---|---|
声明 |
|
UA 自己填,无认证 |
话机屏幕上的显示名 / URI;不可作计费或防伪 |
断言 |
|
可信 Proxy / SBC / 网关在入网时插入 |
弹屏、CDR、Trunk 主叫号码;只在 trusted 域有效 |
认证 |
|
认证服务签 PASSporT(JWT) |
出 PSTN / 互联时判断号码是否被伪造(STIR/SHAKEN) |
From 声明身份(可被终端随便填)
P-Asserted-Identity 可信网络内的断言身份
Identity (RFC 8224) 密码学认证的主叫身份(STIR/SHAKEN)
读一条 INVITE:先看 From(显示),再看 PAI(内网认谁),再看有没有 Identity(出网能不能证明)。缺哪一层,就缺哪一种结论。
P-Asserted-Identity
RFC3325 定义在 可信网络 中传递断言身份。典型部署点:SIP Trunk、运营商、PSTN 网关、SBC、FreeSWITCH、PBX。
规则直觉:
只在 trusted 域里传,出网到不可信 UA 时应删掉,改用
P-Preferred-Identity或普通 From常与
Privacy(RFC3323)一起:Privacy: id表示不要把 PAI 暴露给不可信下游From 可以显示“客户姓名”,PAI 才是运营商认的主叫号码
一条消息里可以有两个 PAI:一个
sip:,一个tel:(E.164)
呼叫中心用途:呼入弹屏用 PAI;呼出时 SBC 按 PAI / 配置号码送 PSTN;CDR / 计费以 PAI 为准。
Connected Identity
RFC4916 允许在对话中更新已连接身份,例如转接到另一人、总机应答后再接分机。 常见实现:200 OK 或 UPDATE 里更新 PAI,或刷新 From 的 id(实现各异)。很多系统用应用层事件代替。
STIR / SHAKEN 与 RFC 8224
PAI 只在可信 SIP 网里有意义。一旦到 PSTN / 不可信互联,主叫号码可以被伪造。
RFC8224 已取代 RFC 4474。核心是 SIP Identity header 携带 PASSporT(JWT)。
STIR 是 SIP 身份签名框架;SHAKEN 是北美电话网的部署规范(Attestation A/B/C)。
P-Asserted-Identity → Trusted SIP network 里的断言
RFC 8224 / STIR → 密码学认证的主叫身份
attest A 已认证用户,且确认其有权用该号码
attest B 已认证用户,号码权属未完全确认
attest C 网关穿越,几乎未认证
涉及美国外呼、SIP Trunk、被运营商拦截时,不能只停留在 RFC 3325。
同一 INVITE 里 PAI 与 Identity 可以并存:PAI 回答“内网断言是谁”,JWT 回答“签名是否覆盖这个 orig.tn”。冲突时,出 PSTN 以签名为准判断“是否伪造”。
实践注意
FreeSWITCH 可用
sip_h_P-Asserted-Identity读写。呼出前确认 Trunk 要的是 PAI、Remote-Party-ID 还是 From(老设备还在用 RPID)。Remote-Party-ID 是非标准遗留,和 PAI 类似,对接老 PBX 时仍会遇到。
显示名(display name)和号码是两回事:防诈骗看号码认证,弹屏看号码 + CRM。
WebRTC 浏览器没有 PAI;网关入 SIP 网时由 FreeSWITCH / SBC 插入。
Example
Trunk 呼入 INVITE 应类似(用 siptrace 对照真实号码):
INVITE sip:+18005551212@192.168.1.10:5080 SIP/2.0
From: "Alice" <sip:+14155551212@trunk.example.com>;tag=a
To: <sip:+18005551212@192.168.1.10>
P-Asserted-Identity: "Alice" <sip:+14155551212@trunk.example.com>
P-Asserted-Identity: <tel:+14155551212>
Privacy: none
Call-ID: 1h23@trunk
CSeq: 1 INVITE
对照这一条:
From display-name = Alice → 屏幕显示,不可信
From URI = +14155551212 → 声明号码,话机可改
PAI sip / tel = +14155551212 → 弹屏 / CDR 用这个
Identity = (本例没有) → 不能据此判断 PSTN 侧真伪
Privacy = none → 允许把身份传给可信下游
呼出到 Trunk 时在 dialplan 设置后再抓:
<action application="set" data="sip_h_P-Asserted-Identity=<sip:+14155550000@fs.example.com>"/>
带 Privacy: id 的呼叫,出网到不可信 UA 后不应再出现 PAI;From 常变成匿名:
From: "Anonymous" <sip:anonymous@anonymous.invalid>;tag=a
Privacy: id
# 此处不应再有 P-Asserted-Identity
若有 STIR,INVITE 另有 Identity,形态是 compact JWT + 参数(不要拿占位 JWT 去验签,用真实抓包解码):
Identity: <header>.<payload>.<signature>;info=<https://cert.example.com/passport.cer>;alg=ES256;ppt=shaken
验证:
弹屏 / CDR 用 PAI 的
+14155551212,不要用 From 显示名带
Privacy: id的呼叫,出网 INVITE 不应再出现 PAI解码 PASSporT payload:
orig.tn应对上 PAI/From 号码,dest.tn对上被叫,attest为 A/B/C;与 PAI 同时存在时以签名为准判断“是否伪造”
fs_cli -x "sofia profile external siptrace on"
Conclusion
弹屏和计费读 PAI 的 tel/sip 号码;From 的 display-name 只是显示。
同一条 INVITE 有 PAI、没有 Identity,只能信内网断言,不能信 PSTN 主叫真伪。
Privacy: id 出可信网后不应再出现 P-Asserted-Identity。