kamailio TOPOH 模块

Kamailio topoh 模块分析

概述

topoh 模块是Kamailio中的一个拓扑隐藏(Topology Hiding)模块,其主要功能是隐藏SIP消息中暴露服务器拓扑结构的路由头信息,从而保护SIP代理服务器的内部网络架构不被外部知晓。

核心功能

  1. 拓扑信息隐藏:对SIP消息中的路由头信息(如Record-Route, Route)进行编码和解码,隐藏真实的服务器地址和路径。
  2. 无状态兼容:模块设计不受服务器是无状态(stateless)还是有状态(stateful)的影响。
  3. 脚本透明性:对SIP消息的编码/解码对Kamailio脚本解释器是透明的,脚本中接收到的SIP消息始终是解码后的完整内容,所有功能正常可用。
  4. 无缝重启:SIP服务器重启不会影响正在进行的通话。重启后,服务器能继续编码/解码拓扑信息,确保通话不中断。
  5. 集群支持:通过使用相同的 mask_key,多个SIP服务器(如负载均衡后的服务器群)可以共享解码能力。

依赖要求

必需模块

  • rr 模块:必须在 topoh 模块之前加载。服务器必须执行 record_routing 操作,以确保对话内请求(in-dialog requests)能够被正确编码和解码。

外部依赖

  • 无外部库或应用程序依赖。

核心参数详解

1. 安全与编码参数

  • mask_key (str): 用于编码/解码头部信息的密钥(关键词)。

    • 默认值: _static_value_
    • 重要性: 这是拓扑隐藏的核心。所有需要相互解码的服务器必须使用相同的 mask_key
    • 示例: modparam("topoh", "mask_key", "some secret here")
  • mask_ip (str): 用于构建编码后SIP URI的IP地址。

    • 默认值: 127.0.0.8
    • 说明: 可以是任何IP(包括私有IP、非真实IP),但不应是客户端可能使用的地址。该IP不用于实际SIP路由。
    • 示例: modparam("topoh", "mask_ip", "192.168.0.1")
  • mask_callid (integer): 是否对 Call-ID: 头部进行编码。

    • 默认值: 0 (不编码)
    • 注意: 如果启用且使用 dialog 模块终止通话,必须设置 dialog 模块的 lreq_callee_headers 参数包含 TH: dlh\r\n

2. 编码格式参数

  • uparam_name (str): 存储编码值的URI参数名称。
    • 默认值: line
  • uparam_prefix (str): 编码URI参数前添加的前缀。
    • 默认值: sr-
  • vparam_name (str): 存储编码值的Via头参数名称。
    • 默认值: branch
  • vparam_prefix (str): 编码Via头参数前添加的前缀。
    • 默认值: z9hG4bKsr-
  • callid_prefix (str): 编码Call-ID头部前添加的前缀。
    • 默认值: !!:

3. 安全与验证参数

  • sanity_checks (integer):

    • 默认值: 0 (不绑定)
    • 功能: 如果设置为1,模块将绑定 sanity 模块,对接收到的SIP请求执行格式检查,确保请求格式正确后再进行编码/解码。
  • uri_prefix_checks (integer):

    • 默认值: 0 (不检查)
    • 功能: 如果设置为1,模块在解码前会检查URI是否匹配预期的前缀(由 mask_ipuparam_prefix 组成),避免尝试解码非本模块编码的URI。
    • 警告: 如果SIP设备会修改Contact或Record-Route头中的URI(如添加端口5060或插入新参数),则不应启用此选项。

4. 事件回调参数

  • event_callback (str):

    • 默认值: 空(不执行函数)
    • 功能: 指定KEMI配置文件(如Lua, Python脚本)中要执行的函数名,代替 event_route[...] 块。
    • 参数: 该函数接收一个字符串参数,表示触发的事件名称。
    • 示例: modparam("topoh", "event_callback", "ksr_topoh_event")
  • event_mode (int):

    • 默认值: 3 (执行两个事件路由)
    • 功能: 位掩码控制执行哪些 event_route 块:
      • 1: 执行 event_route[topoh:msg-outgoing]
      • 2: 执行 event_route[topoh:msg-sending]
      • 3: 执行两者(默认)

事件路由 (Event Routes)

1. event_route[topoh:msg-outgoing]

  • 触发时机: 在对出站SIP消息进行拓扑隐藏处理之前
  • 目的: 允许在早期决定是否跳过拓扑隐藏。
  • 关键变量: $sndto(ip), $sndto(port), $sndto(proto) 指向目标地址。
  • 消息状态: 不是最终要发送的消息,而是一个内部生成的简化消息。这样设计是为了避免对不需要处理的消息进行完整解析,提高性能。
  • 控制: 如果在此路由中执行 drop,则模块将跳过拓扑隐藏处理。
  • 示例:
    1
    2
    3
    4
    5
    event_route[topoh:msg-outgoing] {
    if($sndto(ip)=="10.1.1.10") {
    drop; // 对此目标不进行拓扑隐藏
    }
    }

2. event_route[topoh:msg-sending]

  • 触发时机: 在 event_route[topoh:msg-outgoing] 之后,对即将发送的SIP消息进行拓扑隐藏处理之前
  • 目的: 允许在发送前对消息进行最终检查或决策。
  • 关键变量: $sndto(ip), $sndto(port), $sndto(proto) 指向目标地址。
  • 消息状态: 这是最终要发送的完整SIP消息
  • 控制: 如果在此路由中执行 drop,则模块将跳过拓扑隐藏处理。
  • 示例:
    1
    2
    3
    4
    5
    event_route[topoh:msg-sending] {
    if(is_request() && $fU=="alice") {
    drop; // 对用户alice的请求不进行拓扑隐藏
    }
    }

topohtopos 模块对比

特性 topoh 模块 topos 模块
存储机制 无状态,不依赖数据库或外部存储。通过密钥和算法直接编码/解码。 有状态,依赖数据库或Redis存储对话和分支信息。
重启影响 无缝,重启后仍能解码旧消息,通话不中断。 可能中断,如果存储数据丢失或未共享,可能无法正确还原拓扑。
复杂性 简单,配置少,易于部署。 复杂,需要配置存储后端和过期时间等。
适用场景 适合简单的拓扑隐藏需求,对性能要求高,希望避免外部依赖的场景。 适合需要更复杂拓扑管理、需要持久化状态的场景。
主要参数 mask_key, mask_ip storage, db_url, branch_expire, dialog_expire

总结

topoh 模块是一个轻量级、无状态、高性能的拓扑隐藏解决方案。它通过密码学方法直接在消息中编码拓扑信息,无需外部存储,非常适合需要简单、可靠且对重启不敏感的拓扑隐藏场景。其核心优势在于简单性和鲁棒性,配置只需关注 mask_keymask_ip 等少数几个关键参数即可。