kamailio TOPOS 模块
Kamailio TOPOS 模块分析
概述
TOPOS模块是Kamailio的一个核心功能模块,主要用于实现SIP通信中的拓扑隐藏(Topology Hiding)。该模块通过剥离显示网络拓扑细节的SIP路由头信息,保护SIP代理服务器的内部架构不被外部知晓。
核心功能
- 拓扑隐藏:对基于INVITE的对话、MESSAGE请求、OPTIONS请求等进行路由头信息的剥离和还原
- 透明操作:对配置编写者完全透明,只需加载模块并根据需要调整参数
- 对话支持:同时支持INVITE-based对话和SUBSCRIBE-based的presence对话
- 特殊请求处理:自动跳过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):在运行时更新上下文,可从任何路由使用
事件路由
- event_route[topos:msg-outgoing]:出站SIP消息拓扑隐藏前执行
- event_route[topos:msg-sending]:发送SIP消息前执行,在msg-outgoing之后
- event_route[topos:msg-incoming]:入站SIP消息拓扑隐藏前执行
- event_route[topos:msg-receiving]:接收SIP消息前执行,在msg-incoming之后
这些事件路由允许在拓扑隐藏处理前后进行条件判断和控制,如使用drop命令可跳过拓扑隐藏处理。
使用建议
- 性能优化:根据实际业务需求合理设置过期时间,避免存储过度增长
- 安全性:启用sanity_checks进行请求格式验证,提高系统安全性
- TLS支持:当使用TLS时,确保contact_host包含受信任CA签名的域名
- 监控:利用事件路由功能实现对拓扑隐藏过程的监控和日志记录
TOPOS模块是构建安全、可扩展SIP基础设施的关键组件,通过合理配置可以有效保护网络架构,同时保持SIP通信的完整性和可靠性。
在Kamailio的TOPOS模块中,outgoing/incoming 和 sending/receiving 这四组事件路由代表了两个不同的处理阶段,理解它们的关键在于区分内部处理决策阶段和最终发送/接收阶段。
我们可以将这四个事件路由分为两组来理解:
第一组:决策与预处理阶段 (outgoing/incoming)
这些事件发生在模块决定是否进行拓扑隐藏之前,使用的是内部生成的简化消息,目的是避免不必要的消息解析开销。
event_route[topos:msg-outgoing]- 时机:当Kamailio准备向外部发送一个SIP消息时,TOPOS模块即将开始处理这个出站消息。
- 目的:让你有机会基于目标地址(
$sndto(ip),$sndto(port))决定是否完全跳过拓扑隐藏处理。 - 消息状态:这是一个内部生成的简化消息,不是最终要发送的完整SIP消息。这样设计是为了性能,避免对不需要处理的消息进行完整解析。
- 典型用法:根据目标IP地址黑名单,决定不对此流量进行拓扑隐藏。
1
2
3
4
5event_route[topos:msg-outgoing] {
if($sndto(ip)=="10.1.1.10") { # 特定目标
drop; # 跳过拓扑隐藏
}
}event_route[topos:msg-incoming]- 时机:当Kamailio从外部接收到一个SIP消息时,TOPOS模块即将开始处理这个入站消息。
- 目的:让你有机会基于源地址(
$si,$sp)决定是否完全跳过拓扑隐藏处理。 - 消息状态:同样是一个内部生成的简化消息。
- 典型用法:根据源IP地址白名单,决定不对特定来源的消息进行拓扑隐藏。
1
2
3
4
5event_route[topos:msg-incoming] {
if($si=="10.1.1.10") { # 特定来源
drop; # 跳过拓扑隐藏
}
}
核心思想:这一组是快速决策通道,用于在早期、低成本地决定是否应用拓扑隐藏功能。
第二组:最终处理与执行阶段 (sending/receiving)
这些事件发生在模块已经决定进行拓扑隐藏之后,使用的是即将发送或刚接收的完整SIP消息。
event_route[topos:msg-sending]- 时机:在
msg-outgoing之后,TOPOS模块已经完成了拓扑隐藏处理,消息即将被发送到网络。 - 目的:让你有机会在消息发出前,对最终的、完整的出站SIP消息进行检查或修改。
- 消息状态:这是最终要发送的完整SIP消息,已经过拓扑隐藏处理。
- 典型用法:检查或修改特定用户(如alice)的请求头。
1
2
3
4
5event_route[topos:msg-sending] {
if(is_request() and $fU=="alice") {
# 可以在此处修改消息或记录日志
}
}- 时机:在
event_route[topos:msg-receiving]- 时机:在
msg-incoming之后,TOPOS模块已经完成了拓扑隐藏处理(如还原路由信息),消息刚刚从网络接收并处理完毕。 - 目的:让你有机会在消息进入主路由逻辑前,对最终的、完整的入站SIP消息进行检查或修改。
- 消息状态:这是已处理完毕的完整SIP消息,拓扑信息已还原,准备进入Kamailio的主处理流程。
- 典型用法:对特定用户的消息进行特殊处理或审计。
- 时机:在
核心思想:这一组是精细操作通道,让你在拓扑隐藏处理完成后的最终时刻,对完整的SIP消息进行干预。
总结与流程图
可以将整个流程想象成一个管道:
1 | 出站消息流程: |
outgoing/incoming:早期决策点,使用简化消息,决定是否应用功能。sending/receiving:后期执行点,使用完整消息,在功能应用后进行最终操作。
这种设计既保证了性能(早期决策避免不必要的解析),又提供了灵活性(后期可以操作完整消息)。