kamailio TOPOS 模块

Kamailio TOPOS 模块分析

概述

TOPOS模块是Kamailio的一个核心功能模块,主要用于实现SIP通信中的拓扑隐藏(Topology Hiding)。该模块通过剥离显示网络拓扑细节的SIP路由头信息,保护SIP代理服务器的内部架构不被外部知晓。

核心功能

  1. 拓扑隐藏:对基于INVITE的对话、MESSAGE请求、OPTIONS请求等进行路由头信息的剥离和还原
  2. 透明操作:对配置编写者完全透明,只需加载模块并根据需要调整参数
  3. 对话支持:同时支持INVITE-based对话和SUBSCRIBE-based的presence对话
  4. 特殊请求处理:自动跳过REGISTER和PUBLISH请求的处理,这些请求通常在本地SIP服务器终止

依赖要求

必需模块

  • rr模块:必须在TOPOS模块之前加载,用于执行record routing,确保对话内请求能够正确编码/解码
  • 数据库模块:用于存储拓扑剥离和还原所需的数据

外部依赖

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

存储机制

TOPOS模块支持两种存储后端:

  • db:数据库后端(默认)
  • redis:Redis后端

可通过storage参数配置,如:modparam("topos", "storage", "redis")

主要参数分析

基础配置

  • db_url:数据库连接URL,默认为mysql://kamailio:kamailiorw@localhost/kamailio
  • context:设置TOPOS实例的全局上下文,值长度不超过12个字符

过期时间设置

  • branch_expire:分支记录删除间隔,默认180秒(3分钟)
  • dialog_expire:对话记录删除间隔,默认10800秒(3小时),建议设置为最长通话时长
  • clean_interval:存储记录清理间隔,默认60秒(1分钟)

安全与隐私

  • mask_callid:是否用Kamailio生成的唯一ID替换Call-ID,默认不替换(0)
  • sanity_checks:是否绑定sanity模块进行SIP请求格式检查,默认不检查(0)

联系人控制

  • contact_host:控制Contact头部分的主机部分,默认从Record-Route URI获取
  • contact_mode:控制数据库/redis服务器查找消息数据的键存储模式
    • 0:使用Contact用户(默认)
    • 1:使用Contact URI参数
    • 2:使用AVP变量
  • cparam_name:自定义Contact URI参数名称,默认为”tps”

高级功能

  • event_callback:KEMI配置文件中执行事件的函数名
  • event_mode:控制执行哪些event_route块的位掩码
  • rr_update:是否跟踪和更新re-INVITE中的记录路由变化,默认不更新(0)

XAVU配置

  • xavu_cfg:保存运行时模块使用配置值的根XAVU名称
  • xavu_field_a_contact:A侧Contact头用户部分的字段名(仅contact_mode=2时需要)
  • xavu_field_b_contact:B侧Contact头用户部分的字段名(仅contact_mode=2时需要)
  • xavu_field_contact_host:从XAVU获取Contact头主机部分的字段名

函数与事件路由

函数

  • tps_set_context(ctx):在运行时更新上下文,可从任何路由使用

事件路由

  1. event_route[topos:msg-outgoing]:出站SIP消息拓扑隐藏前执行
  2. event_route[topos:msg-sending]:发送SIP消息前执行,在msg-outgoing之后
  3. event_route[topos:msg-incoming]:入站SIP消息拓扑隐藏前执行
  4. event_route[topos:msg-receiving]:接收SIP消息前执行,在msg-incoming之后

这些事件路由允许在拓扑隐藏处理前后进行条件判断和控制,如使用drop命令可跳过拓扑隐藏处理。

使用建议

  1. 性能优化:根据实际业务需求合理设置过期时间,避免存储过度增长
  2. 安全性:启用sanity_checks进行请求格式验证,提高系统安全性
  3. TLS支持:当使用TLS时,确保contact_host包含受信任CA签名的域名
  4. 监控:利用事件路由功能实现对拓扑隐藏过程的监控和日志记录

TOPOS模块是构建安全、可扩展SIP基础设施的关键组件,通过合理配置可以有效保护网络架构,同时保持SIP通信的完整性和可靠性。

在Kamailio的TOPOS模块中,outgoing/incomingsending/receiving 这四组事件路由代表了两个不同的处理阶段,理解它们的关键在于区分内部处理决策阶段最终发送/接收阶段

我们可以将这四个事件路由分为两组来理解:


第一组:决策与预处理阶段 (outgoing/incoming)

这些事件发生在模块决定是否进行拓扑隐藏之前,使用的是内部生成的简化消息,目的是避免不必要的消息解析开销。

  1. event_route[topos:msg-outgoing]

    • 时机:当Kamailio准备向外部发送一个SIP消息时,TOPOS模块即将开始处理这个出站消息。
    • 目的:让你有机会基于目标地址$sndto(ip), $sndto(port))决定是否完全跳过拓扑隐藏处理。
    • 消息状态:这是一个内部生成的简化消息,不是最终要发送的完整SIP消息。这样设计是为了性能,避免对不需要处理的消息进行完整解析。
    • 典型用法:根据目标IP地址黑名单,决定不对此流量进行拓扑隐藏。
    1
    2
    3
    4
    5
    event_route[topos:msg-outgoing] {
    if($sndto(ip)=="10.1.1.10") { # 特定目标
    drop; # 跳过拓扑隐藏
    }
    }
  2. event_route[topos:msg-incoming]

    • 时机:当Kamailio从外部接收到一个SIP消息时,TOPOS模块即将开始处理这个入站消息。
    • 目的:让你有机会基于源地址$si, $sp)决定是否完全跳过拓扑隐藏处理。
    • 消息状态:同样是一个内部生成的简化消息
    • 典型用法:根据源IP地址白名单,决定不对特定来源的消息进行拓扑隐藏。
    1
    2
    3
    4
    5
    event_route[topos:msg-incoming] {
    if($si=="10.1.1.10") { # 特定来源
    drop; # 跳过拓扑隐藏
    }
    }

核心思想:这一组是快速决策通道,用于在早期、低成本地决定是否应用拓扑隐藏功能。


第二组:最终处理与执行阶段 (sending/receiving)

这些事件发生在模块已经决定进行拓扑隐藏之后,使用的是即将发送或刚接收的完整SIP消息

  1. event_route[topos:msg-sending]

    • 时机:在msg-outgoing之后,TOPOS模块已经完成了拓扑隐藏处理,消息即将被发送到网络。
    • 目的:让你有机会在消息发出前,对最终的、完整的出站SIP消息进行检查或修改。
    • 消息状态:这是最终要发送的完整SIP消息,已经过拓扑隐藏处理。
    • 典型用法:检查或修改特定用户(如alice)的请求头。
    1
    2
    3
    4
    5
    event_route[topos:msg-sending] {
    if(is_request() and $fU=="alice") {
    # 可以在此处修改消息或记录日志
    }
    }
  2. event_route[topos:msg-receiving]

    • 时机:在msg-incoming之后,TOPOS模块已经完成了拓扑隐藏处理(如还原路由信息),消息刚刚从网络接收并处理完毕
    • 目的:让你有机会在消息进入主路由逻辑前,对最终的、完整的入站SIP消息进行检查或修改。
    • 消息状态:这是已处理完毕的完整SIP消息,拓扑信息已还原,准备进入Kamailio的主处理流程。
    • 典型用法:对特定用户的消息进行特殊处理或审计。

核心思想:这一组是精细操作通道,让你在拓扑隐藏处理完成后的最终时刻,对完整的SIP消息进行干预。


总结与流程图

可以将整个流程想象成一个管道:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
出站消息流程:
[原始消息] --> event_route[topos:msg-outgoing] (决策: 是否隐藏?)
|
+--(如果未drop)--> [拓扑隐藏处理]
|
+--> event_route[topos:msg-sending] (最终检查)
|
+--> [发送到网络]

入站消息流程:
[从网络接收] --> event_route[topos:msg-incoming] (决策: 是否隐藏?)
|
+--(如果未drop)--> [拓扑还原处理]
|
+--> event_route[topos:msg-receiving] (最终检查)
|
+--> [进入主路由处理]
  • outgoing/incoming早期决策点,使用简化消息,决定是否应用功能。
  • sending/receiving后期执行点,使用完整消息,在功能应用后进行最终操作。

这种设计既保证了性能(早期决策避免不必要的解析),又提供了灵活性(后期可以操作完整消息)。