当前位置: 首页 > article >正文

kamailio关于via那点事

如果kamailio作为代理服务器,在转到目的路由时 不删除原始的via信息 会造成信息泄露

如果 Kamailio 作为代理服务器(SIP Proxy)在转发 SIP 请求时不删除原始的 Via 信息,这确实可能会造成信息泄露


📌 为什么不删除 Via 可能会泄露信息?

  1. 暴露内部网络信息

    • Via 头包含了 前一个发送者的 IP 地址、端口和传输方式(UDP/TCP/TLS)。
    • 如果 Via 头未被清理,可能会泄露 内部服务器 IP(如私有地址 192.168.x.x)或运营商信息
    • 例如,假设 Kamailio 运行在 10.10.10.1,但 SIP 服务器在 192.168.1.100,那么 Via 头可能会泄露:
      Via: SIP/2.0/UDP 192.168.1.100:5060;branch=z9hG4bK12345
      
      这个信息 不应该暴露给外网
  2. 攻击者可利用 Via 进行网络拓扑分析

    • 恶意用户可能利用 Via 头中的 IP 地址 扫描 SIP 代理的拓扑结构,寻找潜在的攻击点(如未受保护的 SIP 服务器)。
  3. SIP 设备可能错误处理额外的 Via

    • 某些 SIP 设备(特别是运营商的 SBC 或 PBX)可能不期望看到 额外的 Via,从而导致 SIP 处理异常(如 400 Bad Request483 Too Many Hops)。

✅ 解决方案:让 Kamailio 在转发请求时删除原始 Via

方法 1:使用 remove_hf("Via")

Kamailio 提供了 remove_hf("Via") 指令,可以在 SIP 代理模式下 移除所有 Via 头并重新生成,防止信息泄露。
kamailio.cfg 配置文件中:

request_route {
    if (!is_method("ACK")) {
        remove_hf("Via");  # 删除所有 Via 头
    }
    append_hf("Via: SIP/2.0/UDP $si:$sp;branch=z9hG4bK$var(branch)\r\n");
    t_relay();
}

🔹 解释

  • 移除 Via,防止泄露内部 IP。
  • 手动添加新的 Via,只显示 Kamailio 作为代理的 IP($si:$sp)。

方法 2:使用 topos 模块(推荐)

topos 是 Kamailio 提供的 “拓扑隐藏”(Topology Hiding)模块,可以自动删除 Via 头,并在响应时恢复,防止信息泄露。

📌 安装 topos 模块
sudo apt install kamailio-topos-modules
📌 在 kamailio.cfg 启用 topos
loadmodule "topos.so"

request_route {
    if (!is_method("ACK")) {
        topos_request();
    }
    t_relay();
}

onreply_route {
    topos_reply();
}

🔹 解释

  • topos_request() 删除 ViaRecord-Route,隐藏内部拓扑
  • topos_reply() 在响应时恢复正确的路由,确保 SIP 消息能正确返回。

📍 结论

不删除 Via 确实会导致信息泄露,特别是在 NAT 或运营商环境中!
推荐使用 remove_hf("Via")topos 模块来移除 Via,保护 SIP 代理的内部拓扑信息! 🚀

使用topos模块自动更正via

使用 topos 模块后,目的地路由的 Via 头信息

当 Kamailio 作为 SIP 代理(Proxy) 并启用了 topos 模块时,它会自动删除原始的 Via,并在转发 SIP 请求时仅留下 Kamailio 自己的 Via。那么,在**目的地路由(最终 SIP 服务器)**收到的请求中,Via 头的情况如下:


📌 1. 启用了 topos,最终目的地收到的 Via

示例:

📍 客户端 (EP1) 发送初始请求

INVITE sip:13545769997@222.223.190.118 SIP/2.0
Via: SIP/2.0/UDP 192.168.1.100:5060;branch=z9hG4bK111111
Via: SIP/2.0/UDP 10.10.10.1:5060;branch=z9hG4bK222222
Via: SIP/2.0/UDP 222.211.75.75:5060;branch=z9hG4bK333333

🔹 这里 Via 头中包含了所有中间代理的 IP(内部网络信息)


📍 Kamailio 代理(启用了 topos

topos_request() 处理后,Kamailio 会:

  • 删除原始 Via192.168.1.10010.10.10.1222.211.75.75)。
  • 只留下 Kamailio 自己的 Via

🔹 Kamailio 转发后的 SIP 请求

INVITE sip:13545769997@222.223.190.118 SIP/2.0
Via: SIP/2.0/UDP 47.100.62.225:5060;branch=z9hG4bKabcdef

📌 🔹 这里 Via 只保留了 Kamailio 自己的 IP(47.100.62.225),不会暴露任何内部 IP!


📌 2. 目的地收到的 Via

最终,目的地路由(222.223.190.118) 只会看到 Kamailio 的 Via

INVITE sip:13545769997@222.223.190.118 SIP/2.0
Via: SIP/2.0/UDP 47.100.62.225:5060;branch=z9hG4bKabcdef

原始 Via(192.168.1.100、10.10.10.1、222.211.75.75)已被隐藏,保护了 SIP 代理的内部网络结构!


📌 3. 响应中的 Via 处理

当 目的地(222.223.190.118) 发送 200 OK 响应时,它的 Via 头如下:

SIP/2.0 200 OK
Via: SIP/2.0/UDP 47.100.62.225:5060;branch=z9hG4bKabcdef

然后 Kamailio 会使用 topos_reply() 恢复正确的返回路径但不会暴露目的地的 Via,所以客户端最终收到的响应仍然不会看到 222.223.190.118 的 Via


📍 结论

目的地路由(最终 SIP 服务器)收到的 Via 头只包含 Kamailio 的 IP,不包含原始的 Via 头,确保了内部网络信息不被泄露!
响应时 Kamailio 也会正确恢复路径,确保 SIP 消息能够正确返回! 🚀

下面是一个完整的 Kamailio 作为 SIP 代理服务器(Proxy)kamailio.cfg 配置,结合 Lua 脚本 进行 呼叫计费,并使用 topos 模块隐藏 Via 信息,确保 SIP 请求的安全性。


📌 功能概述

  1. 基本 SIP 代理功能
  2. 启用 topos 模块,隐藏 Via
  3. 使用 Lua 进行通话计费
  4. 转发 INVITE、ACK、BYE 等必要的 SIP 请求
  5. 防止环路、错误处理
  6. 超时释放通话

📌 Lua 计费脚本 (/usr/local/kamailio/lua/billing.lua)

-- billing.lua - 计费逻辑(计算通话费用)
local billing = {}

function billing.calculate_fee(duration)
    local rate_per_second = 0.05  -- 每秒 0.05 元
    local cost = duration * rate_per_second
    return cost
end

function billing.log_call(call_id, caller, callee, duration)
    local cost = billing.calculate_fee(duration)
    local log_str = string.format(
        "CALL BILLING - Call-ID: %s, From: %s, To: %s, Duration: %d sec, Cost: %.2f 元",
        call_id, caller, callee, duration, cost
    )
    -- 记录日志
    KSR.info(log_str)
end

return billing

📌 Kamailio kamailio.cfg 配置

####### 全局配置 ########

#!KAMAILIO
#!define WITH_LUA
#!define WITH_TOPO

loadmodule "sl.so"                # SIP 事务管理
loadmodule "tm.so"                # SIP 事务管理
loadmodule "rr.so"                # 记录路由
loadmodule "maxfwd.so"            # Max-Forwards 处理
loadmodule "siputils.so"          # 处理 SIP 头
loadmodule "topos.so"             # 隐藏 Via 头
loadmodule "topos_redis.so"       # Redis 版本的 topos(推荐)
loadmodule "lua.so"               # Lua 脚本支持

modparam("topos", "storage", "redis://127.0.0.1:6379/0")  # 存储 SIP 会话信息到 Redis
modparam("lua", "load", "/usr/local/kamailio/lua/billing.lua")

####### SIP 请求路由 ########

request_route {
    if (!mf_process_maxfwd(10)) {
        sl_send_reply("483", "Too Many Hops");
        exit;
    }

    if (is_method("OPTIONS")) {
        sl_send_reply("200", "OK");
        exit;
    }

    # 处理 INVITE
    if (is_method("INVITE")) {
        record_route();
        topos_request();  # 删除原始 Via 信息
        route(1);
        exit;
    }

    # 处理 BYE(通话结束)
    if (is_method("BYE")) {
        handle_bye();
        topos_request();  # 确保 Via 头处理
        route(1);
        exit;
    }

    route(1);
}

route[1] {
    if (!t_relay()) {
        sl_reply_error();
    }
    exit;
}

####### 响应处理 ########

onreply_route {
    topos_reply();  # 确保 Via 头处理
}

####### 处理 BYE 进行计费 ########

event_route[tm:local-request] {
    if (is_method("BYE")) {
        handle_bye();
    }
}

####### 计费逻辑(Lua 计费) ########

route[handle_bye] {
    xlog("L_INFO", "Handling BYE request for call billing");

    # 获取通话时长
    if ($Ts - $T_req_time > 0) {
        $var(duration) = $Ts - $T_req_time;
    } else {
        $var(duration) = 0;
    }

    # 获取通话 ID、主叫和被叫
    $var(call_id) = $ci;
    $var(caller) = $fU;
    $var(callee) = $tU;

    # 调用 Lua 计费
    $var(lua_result) = lua_runstring(
        string.format("require 'billing'.log_call('%s', '%s', '%s', %d)",
            $var(call_id), $var(caller), $var(callee), $var(duration))
    );

    xlog("L_INFO", "Billing logged: " + $var(lua_result));
}

📌 代码解析

  1. topos 模块

    • topos_request(); 删除 Via,防止信息泄露
    • topos_reply(); 确保返回路径正确
    • 使用 Redis 存储会话信息,防止 Kamailio 重启导致 Via 丢失
  2. Lua 计费

    • calculate_fee(duration) 计算通话费用
    • log_call(call_id, caller, callee, duration) 记录计费日志
  3. 计费触发时机

    • onreply_route {} 处理 SIP 响应
    • event_route[tm:local-request] {} 监听 BYE 事件并触发 Lua 计费
  4. SIP 代理功能

    • 转发 INVITE、ACK、BYE
    • 防止环路(Max-Forwards 机制)
    • 记录路由(Record-Route 机制)

📌 运行流程

📞 呼叫过程:

  1. EP1 -> Kamailio 发送 INVITE
  2. Kamailio 使用 topos_request() 删除原始 Via
  3. Kamailio -> 目的地 转发 INVITE
  4. 目的地 -> Kamailio 发送 200 OK
  5. Kamailio 使用 topos_reply() 恢复路径 并转发给 EP1
  6. EP1 发送 BYE
  7. Kamailio 调用 Lua 计算通话时长和费用
  8. Kamailio 记录计费日志,并转发 BYE目的地

📌 示例日志

CALL BILLING - Call-ID: c12345abcd, From: 01089672389, To: 13545769997, Duration: 120 sec, Cost: 6.00 元

📌 结论

隐藏 Via 头,保护代理服务器信息
使用 Lua 实现通话计费
支持 topos,防止 Via 泄露
支持基本 SIP 代理功能(INVITE、BYE、ACK) 🚀

已经使用了lua脚本,为什么还要把路由相关代码写入到kamailio.cfg中呢?

这是因为 Kamailio 的路由逻辑必须在 kamailio.cfg 中定义,Lua 主要是用于 业务逻辑扩展(如计费),而不是完全替代 kamailio.cfg 的 SIP 处理能力。下面详细解释 为什么 kamailio.cfg 仍然需要路由逻辑


📌 为什么 kamailio.cfg 仍然需要路由逻辑?

Kamailio 主要用于 SIP 代理、注册和路由控制,其核心逻辑(如 INVITE 处理、路由转发、事务管理等)都是由 kamailio.cfg 配置完成的。Lua 只是一个辅助工具,不能完全代替 Kamailio 处理 SIP 消息。

🚀 Kamailio kamailio.cfg 主要职责

  1. 解析 SIP 请求

    • 识别 SIP 方法(如 INVITEBYE
    • 处理 Max-Forwards 以防止循环
    • 记录路由 (Record-Route) 以保持通话链路
  2. 管理 SIP 事务

    • tm(事务管理)模块用于 SIP 事务控制
    • sl(状态回复)模块用于无事务性消息回复
  3. 控制 SIP 代理逻辑

    • 进行 t_relay()(SIP 请求转发)
    • 处理 onreply_route{}(SIP 响应处理)
    • 通过 topos 隐藏 Via

📌 Lua 主要职责

  1. 提供业务逻辑(如计费、日志记录)
  2. 与外部系统交互(如数据库、Redis、REST API)
  3. 增强 Kamailio,但不能完全取代 kamailio.cfg

Lua 不能直接控制 Kamailio 的 SIP 代理行为,它只是一个扩展工具。例如,Lua 不能执行 t_relay() 这样的 SIP 代理操作,必须在 kamailio.cfg 中完成。


📌 为什么不能只用 Lua 处理 SIP?

  • Lua 不能直接处理 SIP 事务(如 t_relay(),必须在 kamailio.cfg 内调用。
  • Lua 不能替代 kamailio.cfg 的核心 SIP 处理逻辑(如 record_route())。
  • Kamailio 是一个高性能 SIP 代理,C 语言模块比 Lua 解析更快,直接在 kamailio.cfg 处理 SIP 逻辑可以提升性能。

📌 最佳实践:结合 kamailio.cfg 和 Lua

  • kamailio.cfg 负责 SIP 代理、转发、事务管理
  • Lua 负责计费、日志、数据库交互

例如:

  • Kamailio 处理 BYE 请求并调用 Lua 计费
  • Lua 计算通话时长,并将费用存入数据库
  • Kamailio 继续处理 SIP 路由

📌 结论

不能完全用 Lua 替代 kamailio.cfg,因为 Lua 不能直接处理 SIP 代理逻辑。
最佳方式是:kamailio.cfg 处理 SIP 代理,Lua 负责计费、日志等业务逻辑。 🚀


http://www.kler.cn/a/543002.html

相关文章:

  • 探索技术新边界:让 HTML 电子凭证与二维码、PDF 完美融合
  • 计算机毕业设计SpringBoot校园二手交易小程序 校园二手交易平台(websocket消息推送+云存储+双端+数据统计)(源码+文档+运行视频+讲解视频)
  • WebSocket 握手过程
  • data attributes
  • HTML5--网页前端编程(上)
  • DeepSeek做赛车游戏
  • 将 AMD Zynq™ RFSoC 扩展到毫米波领域
  • 软件工程-决策树决策表
  • Unity 打造游戏资源加密解密系统详解
  • ElementUI的<el-image>组件引用网络图片加载失败
  • 从词袋到Transformer:自然语言处理的演进与实战
  • Maven 多模块项目管理
  • 回溯---相关习题,经验总结
  • DeepSeek-V2 论文解读:混合专家架构的新突破
  • 青少年编程与数学 02-009 Django 5 Web 编程 07课题、数据迁移
  • 从零构建高可用MySQL集群:Percona XtraDB Cluster 实战部署
  • 《qt open3d中添加最远点采样》
  • STM32 如何将printf函数和串口函数重定向
  • Redis主从复制高延迟问题解决思路
  • 【Elasticsearch】Bucket Selector Aggregation
  • 微信小程序的behaviors和vuex功能对比
  • 如何在Java中使用JUnit进行单元测试
  • 19.1.2 DML
  • Ubuntu22.04 配置deepseek知识库
  • 【Linux】修改语言编码
  • 通过命令行运行py文件与通过ide运行py文件,对文件中模块的引用方式的影响