news 2026/2/3 2:20:12

Kamailio 怎样使用 STIR/SHAKEN

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Kamailio 怎样使用 STIR/SHAKEN

AI 产生的文章,仅供参考

Kamailio 使用 STIR/SHAKEN 的流程相对复杂,因为它需要与外部的 STIR/SHAKEN 服务(例如 Secure Telephone Identity (STI) 证书颁发机构 (CA) 和验证服务)进行集成。Kamailio 本身不执行 STIR/SHAKEN 的签名和验证过程,而是充当一个信令代理,将相关信息传递给这些外部服务。

下面是一个详细的 Kamailio 集成 STIR/SHAKEN 的流程概述,并解释了每个步骤中 Kamailio 的作用:

STIR/SHAKEN 概述

在深入 Kamailio 流程之前,先简要回顾一下 STIR/SHAKEN 的核心概念:

  • STIR (Secure Telephone Identity Revisited):定义了如何使用数字证书对 SIP 呼叫的 From 字段(即主叫号码)进行签名,以证明其合法性。
  • SHAKEN (Signature-based Handling of Asserted information using toKENs):定义了如何将 STIR 签名作为 SIP P-Asserted-Identity (PAI) 头的一部分进行传递和验证。

STIR/SHAKEN 流程涉及的角色:

  1. Originating Service Provider (OSP):发起呼叫的运营商。负责生成 STIR 签名。
  2. Terminating Service Provider (TSP):接收呼叫的运营商。负责验证 STIR 签名。
  3. STI-CA (Secure Telephone Identity Certificate Authority):颁发用于签名的证书。
  4. STI-VS (Secure Telephone Identity Verification Service):提供签名验证服务。

Kamailio 集成 STIR/SHAKEN 的详细流程

一、 呼叫发起方 (Originating Service Provider) 的 Kamailio 配置

在呼叫发起方,Kamailio 的主要任务是将 SIP 呼叫路由到外部的 STIR/SHAKEN 签名服务,并将签名后的结果(SHAKEN 身份声明)重新插入到 SIP 消息中。

  1. Kamailio 收到发起呼叫的 INVITE 消息。
  2. Kamailio 识别需要签名的呼叫:Kamailio 需要通过某种逻辑(例如,基于主叫号码、被叫号码或特定的路由规则)来判断哪些呼叫需要进行 STIR/SHAKEN 签名。
    • Kamailio 模块:可以使用droutingdispatcher或自定义脚本逻辑来实现。
  3. Kamailio 将呼叫信息发送到外部 STIR/SHAKEN 签名服务:
    • 如何发送:这通常通过 SIP INVITE 的 REFER 方法、HTTP 请求(如果签名服务提供 REST API)或专门的 Kamailio 模块与外部服务进行交互。
      • 使用 REFER:Kamailio 可以向签名服务发送一个 REFER 消息,其中包含需要签名的 SIP INVITE 的相关信息。签名服务收到 REFER 后,进行签名,然后将签名后的 INVITE 返回给 Kamailio。
      • 使用 HTTP 模块:如果签名服务提供 HTTP/REST API,Kamailio 可以使用htablejson模块构造 HTTP 请求,将相关呼叫数据发送给签名服务,并解析签名服务返回的响应。
      • 自定义模块/脚本:编写一个 Kamailio C 模块或使用lua模块与签名服务进行更复杂的交互。
    • 发送的内容:主要包括主叫号码 (From Header)、被叫号码 (To Header) 和其他必要的 SIP 头信息。
  4. 外部 STIR/SHAKEN 签名服务的工作流程:
    • 接收到 Kamailio 发送的呼叫信息。
    • 向 STI-CA 请求证书(如果尚未缓存)。
    • 使用私钥和从 STI-CA 获取的证书对呼叫信息进行数字签名。
    • 将生成的 SHAKEN 身份声明(通常是一个 JSON Web Token (JWT))封装在 SIP P-Asserted-Identity (PAI) 头中,或者作为新的 SIP 头(例如Identity头)返回给 Kamailio。
  5. Kamailio 接收签名结果:
    • Kamailio 接收来自签名服务的响应(例如,新的 SIP INVITE 消息或包含 SHAKEN 声明的 HTTP 响应)。
  6. Kamailio 将 SHAKEN 身份声明插入 SIP 消息:
    • Kamailio 解析接收到的 SHAKEN 身份声明。
    • Kamailio 将其作为Identity头字段(通常在 SIP INVITE 消息中)添加到原始的 SIP INVITE 消息中。
      Identity: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdHRlc3QiOiJBIiwib3JpZyI6eyJ0ZWwiOiIrMSAxMTExNTU1MTIxMiJ9LCJkZXN0Ijp7InRlbCI6WyIrMSAxMTExNTU1MTIyMiJdfSwiaW ...
    • Kamailio 函数:可以使用insert_hf()append_hf()函数来添加Identity头。
  7. Kamailio 将带有签名的 INVITE 消息转发到下一个跳。

二、 呼叫接收方 (Terminating Service Provider) 的 Kamailio 配置

在呼叫接收方,Kamailio 的主要任务是接收带有 SHAKEN 身份声明的 SIP 呼叫,将其路由到外部的 STIR/SHAKEN 验证服务,并根据验证结果决定如何处理呼叫。

  1. Kamailio 收到带有Identity头的 INVITE 消息。
  2. Kamailio 识别需要验证的呼叫:Kamailio 需要通过检查 SIP 消息中是否存在Identity头来判断该呼叫是否需要进行 STIR/SHAKEN 验证。
    • Kamailio 函数:is_present_hf("Identity")
  3. Kamailio 将呼叫信息发送到外部 STIR/SHAKEN 验证服务:
    • 如何发送:同样可以通过 REFER、HTTP 请求或专门的 Kamailio 模块与外部验证服务进行交互。
      • 使用 REFER:Kamailio 向验证服务发送 REFER 消息,包含 SIP INVITE 的相关信息(特别是Identity头)。验证服务进行验证,然后将验证结果(例如,验证通过/失败,Attestation Level 等)返回给 Kamailio。
      • 使用 HTTP 模块:Kamailio 构造 HTTP 请求,将Identity头的内容发送给验证服务。
    • 发送的内容:主要包括Identity头的内容、主叫号码、被叫号码等。
  4. 外部 STIR/SHAKEN 验证服务的工作流程:
    • 接收到 Kamailio 发送的呼叫信息和Identity头。
    • 解析Identity头中的 JWT。
    • 从 JWT 中提取证书信息。
    • 向 STI-CA 验证证书的有效性。
    • 验证签名是否正确,以及主叫号码是否与签名信息匹配。
    • 根据验证结果,生成一个验证报告(例如,Attestation Level A, B, C 或 FAILED)。
    • 将验证结果(例如,Attestation Level 和/或详细的错误信息)返回给 Kamailio。
  5. Kamailio 接收验证结果:
    • Kamailio 接收来自验证服务的响应。
  6. Kamailio 根据验证结果处理呼叫:
    • Kamailio 变量:将验证结果存储在 Kamailio 伪变量中,例如$var(stir_shaken_status)
    • 决策逻辑:Kamailio 根据$var(stir_shaken_status)的值来决定下一步操作:
      • 验证通过 (Attestation A/B/C):正常路由呼叫。可以在 SIP 消息中添加额外的头(例如X-Attestation-Level: A)以便下游系统识别。
      • 验证失败 (Attestation FAILED):
        • 拒绝呼叫 (e.g.,sl_send_reply("403", "Forbidden"))。
        • 将呼叫路由到语音邮件。
        • 将呼叫路由到欺诈检测系统。
        • 对呼叫进行降级处理(例如,播放警告音)。
        • 记录详细的日志。
      • 没有Identity头或无法联系验证服务:视为未验证,根据运营商策略进行处理(例如,路由,但标记为低信任度)。
    • Kamailio 函数:使用if()语句和route()函数进行条件路由。

Kamailio 配置示例(伪代码,仅供参考,实际配置会更复杂):

呼叫发起方 (OSP) Kamailio.cfg 片段:

# ... 其他 Kamailio 配置 ... loadmodule "xhttp.so" # 假设使用 HTTP 与签名服务交互 loadmodule "json.so" loadmodule "htable.so" route { # 假设你的签名服务是 http://stir_shaken_signer.example.com/sign if (is_from_local_domain() && $rU =~ "^\+1") { # 仅对本地域的E.164号码进行签名 # 构建发送给签名服务的 JSON 请求 # 注意:这里需要你根据签名服务的API来构建请求体 $var(request_body) = "{ \"from\": \"" + $ruri + "\", \"to\": \"" + $fU + "\" }"; # 发送 HTTP POST 请求到签名服务 if (xhttp_post("http://stir_shaken_signer.example.com/sign", "application/json", $var(request_body), "$var(response_code)", "$var(response_body)")) { if ($var(response_code) == "200") { # 解析签名服务返回的 JSON 响应,获取 Identity 头内容 if (json_get("$.identity_header", "$var(identity_value)", $var(response_body))) { # 将 Identity 头添加到 SIP INVITE 消息中 append_hf("Identity: " + $var(identity_value) + "\r\n"); } else { xlog("L_ERR", "STIR/SHAKEN signer: Failed to parse identity_header from response.\n"); } } else { xlog("L_WARN", "STIR/SHAKEN signer: HTTP POST failed with code $var(response_code).\n"); } } else { xlog("L_ERR", "STIR/SHAKEN signer: HTTP POST failed.\n"); } } # 继续路由呼叫 route(NATDETECT); route(RELAY); }

呼叫接收方 (TSP) Kamailio.cfg 片段:

# ... 其他 Kamailio 配置 ... loadmodule "xhttp.so" loadmodule "json.so" loadmodule "htable.so" route { # 假设你的验证服务是 http://stir_shaken_verifier.example.com/verify if (is_method("INVITE")) { if (is_present_hf("Identity")) { # 提取 Identity 头内容 $var(identity_header_value) = $hdr(Identity); # 构建发送给验证服务的 JSON 请求 $var(request_body) = "{ \"identity_header\": \"" + $var(identity_header_value) + "\", \"from\": \"" + $fU + "\", \"to\": \"" + $rU + "\" }"; # 发送 HTTP POST 请求到验证服务 if (xhttp_post("http://stir_shaken_verifier.example.com/verify", "application/json", $var(request_body), "$var(response_code)", "$var(response_body)")) { if ($var(response_code) == "200") { # 解析验证服务返回的 JSON 响应,获取验证结果 if (json_get("$.attestation_level", "$var(attestation_level)", $var(response_body))) { xlog("L_INFO", "STIR/SHAKEN verification result: $var(attestation_level)\n"); if ($var(attestation_level) == "A" || $var(attestation_level) == "B" || $var(attestation_level) == "C") { # 验证通过,正常路由 append_hf("X-Attestation-Level: " + $var(attestation_level) + "\r\n"); # 可选:添加自定义头 route(RELAY); } else if ($var(attestation_level) == "FAILED") { xlog("L_WARN", "STIR/SHAKEN verification failed for call from $fU to $rU.\n"); sl_send_reply("403", "Forbidden - STIR/SHAKEN Failed"); exit; } else { xlog("L_WARN", "STIR/SHAKEN unknown attestation level: $var(attestation_level).\n"); # 默认处理,例如继续路由或拒绝 route(RELAY); } } else { xlog("L_ERR", "STIR/SHAKEN verifier: Failed to parse attestation_level from response.\n"); route(RELAY); # 继续路由,但标记为未验证 } } else { xlog("L_WARN", "STIR/SHAKEN verifier: HTTP POST failed with code $var(response_code).\n"); route(RELAY); # 继续路由,但标记为未验证 } } else { xlog("L_ERR", "STIR/SHAKEN verifier: HTTP POST failed.\n"); route(RELAY); # 继续路由,但标记为未验证 } } else { xlog("L_INFO", "No Identity header found for call from $fU to $rU. Routing as unverified.\n"); route(RELAY); # 没有 Identity 头,直接路由 } } # ... 其他路由逻辑 ... }

关键考虑事项和注意事项:

  • 外部 STIR/SHAKEN 服务的选择:Kamailio 本身不提供 STIR/SHAKEN 签名或验证功能,你需要选择一个或多个符合标准的外部服务提供商或部署自己的 STIR/SHAKEN 签名/验证服务器。
  • API 接口:确保 Kamailio 能够与外部 STIR/SHAKEN 服务的 API 进行通信。HTTP/REST API 是最常见的选择,Kamailio 的xhttpjson模块可以很好地支持。
  • 性能:STIR/SHAKEN 签名和验证过程会增加呼叫设置的延迟。确保你的外部服务具有足够的处理能力,并且 Kamailio 与其通信是高效的。
  • 错误处理和降级:必须考虑当 STIR/SHAKEN 签名/验证服务不可用或返回错误时如何处理呼叫。通常会有一个降级机制,例如将呼叫标记为“未验证”并继续路由,或者在特定情况下直接拒绝。
  • 证书管理:无论是签名方还是验证方,都需要妥善管理 STI 证书。这通常由 STIR/SHAKEN 服务自动处理,但需要了解其工作原理。
  • Attestation Level (A/B/C):
    • A (Full Attestation):运营商可以验证主叫号码和发起呼叫的客户。最高信任度。
    • B (Partial Attestation):运营商可以验证客户,但无法完全验证主叫号码。
    • C (Gateway Attestation):运营商仅验证呼叫是否来自其网络。最低信任度。
    • Kamailio 在接收方应根据这些级别来制定不同的呼叫处理策略。
  • SIP 头修改:除了Identity头,有时还会涉及其他 SIP 头,例如P-Attestation-Info或自定义的X-头,用于传递额外的 STIR/SHAKEN 相关信息。
  • 日志和监控:详细记录 STIR/SHAKEN 签名和验证的成功与失败情况,以及 Attestation Level,对于故障排除和合规性审计至关重要。
  • 测试:在生产环境中部署之前,进行严格的测试,包括正常流程、错误情况和性能测试。

总而言之,Kamailio 在 STIR/SHAKEN 架构中扮演着重要的集成点角色。它负责将 SIP 信令流与外部的 STIR/SHAKEN 签名和验证服务连接起来,并根据这些服务的输出进行智能的呼叫路由和处理决策。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/2/3 0:15:04

回归测试的优化策略:从成本控制到效能提升

在敏捷开发和DevOps普及的当下,回归测试作为保证软件质量的核心环节,正面临日益严峻的挑战。随着迭代周期缩短和系统复杂度提升,传统的回归测试方法往往陷入“测试用例膨胀而覆盖不足”的矛盾境地。本文旨在为软件测试从业者提供一套系统的回…

作者头像 李华
网站建设 2026/2/3 0:19:33

Dify平台在医疗问答系统中的适配性研究

Dify平台在医疗问答系统中的适配性研究 在当今智慧医疗快速演进的背景下,一个现实问题日益凸显:患者对即时、专业健康咨询的需求持续增长,而优质医疗资源却高度集中且供不应求。尤其是在慢性病管理、用药指导和初筛分诊等场景中,传…

作者头像 李华
网站建设 2026/2/3 0:54:48

BDD在金融系统测试中的实践与思考

当业务语言遇见测试代码 在支付风控系统的重构项目中,我们首次引入了BDD框架。业务方抛出的需求是:"当单笔转账金额超过5万元时,必须触发人工审核流程"。这个看似简单的业务规则,过去常常因为开发与测试的理解偏差导致…

作者头像 李华
网站建设 2026/2/2 23:38:31

Unity2D小游戏《蜗牛跳》全关卡演示

Unity2D 小游戏《蜗牛跳》包含两个关卡,玩家通过点击或长按屏幕进行跳跃,目标是取得红色蘑菇并通关。游戏支持切换操作模式,并具备玩法说明、关卡预览、加载进度显示、数据持久化、关卡重启、退出游戏及蓄力提示等功能。 Unity2D小游戏《蜗牛…

作者头像 李华
网站建设 2026/2/2 23:02:38

Selenium WebDriver的进阶用法

对于软件测试工程师而言,Selenium WebDriver是实施Web自动化测试的利器。然而,许多测试脚本在复杂多变的真实环境中显得脆弱不堪。究其原因,往往是只停留在了基础API的使用层面。要构建能够在持续集成管道中稳定运行的自动化用例,…

作者头像 李华