本文档旨在详细解释基于提供的 kamailio_sbc_dual_nic.cfg 配置文件,在双网卡SBC(Session Border Controller)场景下,Kamailio (5.8.3) 如何与rtpengine协同工作,处理SIP信令以及音频、视频和RTCP媒体流的转发。该方案利用dispatcher模块实现对公网和私网多网关的负载均衡。

1. 系统概览

核心组件包括:

  • Kamailio (5.8.3):作为SIP信令服务器,负责处理呼叫路由、负载均衡和与rtpengine的交互。
  • rtpengine (mr13.1.1.6):作为媒体代理,负责处理RTP/RTCP媒体流的转发、NAT穿透(本场景为无NAT,但rtpengine仍管理媒体端口和IP)、以及可能的媒体处理(如编解码转换,本例未重点配置)。rtpengine配置为双网卡模式,拥有公网和私网IP接口。
  • Dispatcher模块:Kamailio内置模块,用于将呼叫分发到公网或私网的多个目标网关,实现负载均衡和高可用性。

Kamailio监听其公网IP和私网IP上的SIP请求。rtpengine通过NG协议与Kamailio在本地回环地址通信。

2. 呼叫流程:公网用户呼叫私网用户/网关

假设一个公网SIP用户通过互联网呼叫一个位于私网的企业IP-PBX分机或私网网关。

  1. INVITE请求到达Kamailio公网接口
    • 公网用户发送SIP INVITE请求,目标是Kamailio的公网IP地址(例如 PUBLIC_IP:5060)。SDP中包含公网用户的媒体信息(IP和端口)。
    • Kamailio的request_route首先执行通用检查(Max-Forwards, Sanity Checks)。
    • 通过if ($Ri == "PUBLIC_IP")判断请求来自公网接口,进入route[FROM_PUBLIC]逻辑。
  1. 选择私网目标网关 (Dispatcher)
    • route[FROM_PUBLIC]中,调用ds_select_dst("2", DS_ALGORITHM_PRIVATE)。这会从预定义的私网网关组(Set ID 2,例如 /etc/kamailio/dispatcher_private.list 中定义的网关)中根据指定算法(例如轮询)选择一个可用的私网网关。
    • 如果选择失败(没有可用网关),则回复503 Service Unavailable
    • 选中的私网网关URI被存入$du
  1. rtpengine处理媒体协商 (Offer)
    • 如果INVITE请求中包含SDP (has_body("application/sdp")),则调用rtpengine_manage(RTPENGINE_COMMON_FLAGS + " direction=public direction=private")
      • RTPENGINE_COMMON_FLAGS 通常包含 trust-address replace-origin replace-session-connection RTP/AVP rtcp-mux-offer 等。
      • 关键在于direction=public direction=private:这个flag指示rtpengine,对于这个呼叫的“对端”(即私网侧),应该使用rtpengine配置的“私网”接口来分配媒体端口和宣告IP地址。而对于“本端”(即公网用户侧),rtpengine会使用其“公网”接口。
    • rtpengine收到指令后:
      • 私网接口上为私网网关分配RTP/RTCP端口(例如 PRIVATE_RTPENGINE_IP:port_private)。
      • 公网接口上为公网用户分配RTP/RTCP端口(例如 PUBLIC_RTPENGINE_IP:port_public)。
      • 修改INVITE中的SDP:将o=行和会话级c=行中的IP地址替换为rtpengine的公网接口IP (PUBLIC_RTPENGINE_IP),并将媒体端口替换为rtpengine在公网接口上分配的端口 (port_public)。这个修改后的SDP将发往公网用户(在最终的200 OK中)。
      • rtpengine内部记录媒体流的映射关系:PUBLIC_RTPENGINE_IP:port_public <-> PRIVATE_RTPENGINE_IP:port_private
    • 如果rtpengine_manage失败,回复500 Media Proxy Error
  1. 转发INVITE到私网网关
    • Kamailio通过t_set_destination_uri($du)设置请求的目标为选中的私网网关。
    • record_route()确保后续请求(如ACK, BYE)经过Kamailio。
    • Kamailio通过t_relay()将带有rtpengine修改后SDP(此时SDP中的媒体地址是rtpengine的公网地址,这是发往私网网关的INVITE中SDP的视角,它应该宣告rtpengine的私网地址给私网网关)的INVITE请求转发给选定的私网网关。
      • 更正与澄清:当rtpengine_manageroute[FROM_PUBLIC]中为发往私网的INVITE处理SDP时,它修改的SDP内容是准备给私网对端的。因此,SDP中的c=行和媒体端口应该是rtpengine的私网接口IP和端口。rtpengine知道呼叫的另一端(公网用户)的媒体信息,并将使用其公网接口与公网用户通信。
  1. 私网网关响应 (例如200 OK)
    • 私网网关处理INVITE,并回复一个包含其自身媒体信息(私网IP和端口)的200 OK。
    • 200 OK通过Kamailio返回(由于Record-Routing)。
  1. rtpengine处理媒体协商 (Answer)
    • Kamailio的onreply_route捕获到200 OK。
    • 如果响应中包含SDP,再次调用rtpengine_manage(RTPENGINE_ANSWER_FLAGS + " direction=private direction=public") (或者根据保存的呼叫方向上下文确定正确的direction)。
      • direction=private direction=public仍然适用,因为这是对始于公网、终于私网的呼叫的响应路径。
    • rtpengine接收到私网网关的SDP,确认媒体参数。它会修改200 OK中的SDP,将其中的媒体IP和端口替换为rtpengine的公网接口IP和端口 (PUBLIC_RTPENGINE_IP:port_public)。这个修改后的SDP将发往公网用户。
  1. 转发响应给公网用户
    • Kamailio将带有rtpengine修改后SDP的200 OK转发给公网用户。
  1. 媒体流建立
    • 公网用户向PUBLIC_RTPENGINE_IP:port_public发送RTP/RTCP流。
    • rtpengine接收到后,根据内部映射,将媒体流从其公网接口转发到其私网接口,并发送给私网网关的媒体地址 PRIVATE_GW_IP:port_gw_private (此地址由rtpengine从私网网关的SDP中获知)。
    • 反向媒体流:私网网关向PRIVATE_RTPENGINE_IP:port_private发送RTP/RTCP流。
    • rtpengine接收到后,转发给公网用户的媒体地址 PUBLIC_USER_IP:port_user_public (此地址由rtpengine从公网用户的初始SDP中获知)。
    • 核心路径:公网用户 <-> rtpengine公网IP <-> rtpengine私网IP <-> 私网网关。

3. 呼叫流程:私网用户/网关呼叫公网用户

此流程与上述类似,但方向相反。

  1. INVITE请求到达Kamailio私网接口
    • 来自私网用户/网关,目标是Kamailio的私网IP地址(例如 PRIVATE_IP:5060)。
    • Kamailio通过if ($Ri == "PRIVATE_IP")判断请求来自私网接口,进入route[FROM_PRIVATE]逻辑。
  1. 选择公网目标网关 (Dispatcher)
    • 调用ds_select_dst("1", DS_ALGORITHM_PUBLIC)选择公网网关组(Set ID 1)。
  1. rtpengine处理媒体协商 (Offer)
    • 调用rtpengine_manage(RTPENGINE_COMMON_FLAGS + " direction=private direction=public")
      • direction=private direction=public指示rtpengine,对于呼叫的“对端”(即公网侧),应使用rtpengine的“公网”接口。对于“本端”(私网用户),使用其“私网”接口。
    • rtpengine在公网接口分配媒体端口,在私网接口分配媒体端口。
    • 修改INVITE中的SDP:将媒体IP和端口替换为rtpengine的私网接口IP和端口,准备发往公网网关(宣告rtpengine的公网地址)。
      • 更正与澄清:当rtpengine_manageroute[FROM_PRIVATE]中为发往公网的INVITE处理SDP时,它修改的SDP内容是准备给公网对端的。因此,SDP中的c=行和媒体端口应该是rtpengine的公网接口IP和端口
  1. 转发INVITE到公网网关
  2. 公网网关响应 (例如200 OK)
  3. rtpengine处理媒体协商 (Answer)
    • 调用rtpengine_manage(RTPENGINE_ANSWER_FLAGS + " direction=public direction=private")
    • rtpengine修改200 OK中的SDP,将其中的媒体IP和端口替换为rtpengine的私网接口IP和端口,准备发往私网用户/网关。
  1. 转发响应给私网用户/网关
  2. 媒体流建立
    • 私网用户/网关 <-> rtpengine私网IP <-> rtpengine公网IP <-> 公网网关/用户。

4. rtpengine在媒体处理中的角色

  • 音视频流 (Audio/Video):rtpengine通过解析SDP中的m=audiom=video行来识别不同的媒体流。它会为每个媒体流(及其对应的RTCP流)分配端口并进行转发。RTP/AVP flag确保了对标准音视频profile的支持。
  • RTCP流:rtpengine自动处理与RTP流配对的RTCP流。用户要求RTCP转发以处理视频丢包,这是rtpengine的默认行为。rtcp-mux-offerrtcp-mux-answer flags用于协商是否将RTP和RTCP复用在同一端口上,这是推荐的做法,可以节省端口资源并简化NAT穿透(尽管本场景无NAT)。
  • 接口选择direction=publicdirection=private flag是核心,它告诉rtpengine应该将哪个逻辑网络接口(公网或私网)视为呼叫的“远端”进行SDP宣告,并使用哪个接口与该远端通信。rtpengine的另一个接口则用于与呼叫的“近端”通信。
  • SDP操作trust-address (信任SDP中的c=行IP作为媒体来源的初始判断,但最终会被rtpengine的IP替换掉), replace-origin (替换o=行), replace-session-connection (替换会话级c=行) 确保了SDP被正确修改以通过rtpengine路由媒体。

5. Dispatcher模块的角色

  • 负载均衡:根据配置文件中定义的网关列表(例如/etc/kamailio/dispatcher_public.list/etc/kamailio/dispatcher_private.list)和选择的算法(例如轮询),将出局呼叫(无论是到公网还是私网的网关)分发到多个目标网关之一。
  • 网关健康检查:Dispatcher模块可以配置为定期ping目标网关(通过SIP OPTIONS请求),以检查其可用性,并自动将流量从不可用的网关移开。
  • 分组管理:通过Set ID(例如公网组为1,私网组为2)对不同的网关进行分组管理,使得路由逻辑可以清晰地选择合适的目标组。

6. Kamailio配置关键点回顾

  • 监听接口:Kamailio通过listen参数同时监听公网和私网IP地址,以便接收来自两个网络的SIP请求。
  • 接口识别:在request_route中,通过$Ri (Received Interface IP) 变量判断请求到达的接口,从而决定呼叫的初始方向(公网到私网,或私网到公网)。
  • rtpengine模块参数rtpengine_sock定义了与rtpengine守护进程的通信方式。
  • rtpengine_manage()调用:在INVITE请求和对应的2xx响应中(如果包含SDP)调用,以使rtpengine参与媒体会话。关键是根据呼叫方向正确设置direction flag。
  • Record-Routingrecord_route()函数用于确保后续的请求(如ACK, BYE)和响应都通过Kamailio,从而使Kamailio能够保持对话状态并正确处理媒体会话的生命周期(例如调用rtpengine_delete())。
  • rtpengine_delete():在对话结束时(例如收到BYE或CANCEL后,或对话超时),调用rtpengine_delete()来释放rtpengine中占用的资源。
  • onreply_route中的逻辑:正确处理响应中的SDP至关重要。确定响应对应的原始请求方向,以便为rtpengine_manage设置正确的direction flag,是onreply_route中较为复杂的部分,通常需要借助事务标志或对话AVPs来传递上下文。

7. 关于音视频和RTCP的进一步说明

rtpengine本身设计为透明处理RTP和RTCP。只要SDP中正确描述了媒体类型(例如m=audio ... RTP/AVP ...m=video ... RTP/AVP ...),rtpengine就会为它们分配端口并转发。RTCP通常使用RTP端口号+1(除非使用RTCP-Mux)。

用户要求RTCP转发以处理视频丢包,这是标准行为。RTCP报告(如Sender Reports, Receiver Reports)包含了丢包统计、抖动等信息,视频编解码器和播放器可以利用这些信息来调整码率、请求重传(如果协议支持)或进行错误隐藏,从而改善视频质量。

通过确保rtpengine正确桥接了双向的RTCP流,接收端可以向发送端报告网络状况,发送端也可以据此调整发送策略,这对于视频流的质量至关重要。

这份说明应该能帮助理解所提供Kamailio配置方案的工作原理。在实际部署前,务必替换所有占位符IP地址,并根据具体网络环境进行测试和调整。

空空如常

求真得真

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/pingmian/86383.shtml
繁体地址,请注明出处:http://hk.pswp.cn/pingmian/86383.shtml
英文地址,请注明出处:http://en.pswp.cn/pingmian/86383.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

青少年编程与数学 01-012 通用应用软件简介 15 人工智能助手

青少年编程与数学 01-012 通用应用软件简介 15 人工智能助手 一、什么是人工智能助手二、人工智能助手的产生和发展&#xff08;一&#xff09;早期探索阶段&#xff08;二&#xff09;技术突破阶段&#xff08;三&#xff09;广泛应用阶段 三、人工智能助手的主要功能&#xf…

JavaWeb学习——day9(图书管理系统初级)

文章目录 1. 项目功能模块设计1. 登录与权限控制&#xff1a;2. 图书管理功能&#xff08;仅管理员&#xff09;3. 用户功能&#xff08;普通用户&#xff09;&#xff1a; 2. 数据库设计3. 具体功能实现步骤步骤 1&#xff1a;扩展 UserService 来管理角色步骤 2&#xff1a;修…

【设计模式】策略模式 在java中的应用

文章目录 概述策略模式的定义与应用场景定义应用场景 策略模式的核心设计思想 策略模式的纯Java实现1. 定义策略接口&#xff08;抽象基类&#xff09;2. 设计具体策略类3. 通过示例代码理解策略模式的基本用法 策略模式的优缺点与扩展性分析1. 策略模式在设计中的优势2. 如何让…

Container

目录 一、Containerd 概述 1. 什么是 Containerd 主要特点和功能&#xff1a; 2. Containerd 的起源与背景 二、Containerd 架构 1. 架构概述 2. 核心组件解析 &#xff08;1&#xff09;Storage&#xff08;存储&#xff09; &#xff08;2&#xff09;Metadata&…

C#设计模式-Builder-生成器-对象创建型模式

using System; using System.Collections.Generic;namespace A4_Builder_生成器_对象创建型模式 {// 产品类&#xff1a;最终要构建的复杂对象public class Computer{public string CPU { get; set; }public string GPU { get; set; }public int RAM { get; set; } // GBpublic…

C语言堆内存管理详解:malloc和free的使用指南

在C语言程序设计中&#xff0c;内存管理是一个重要的话题。本文将详细介绍堆内存的分配和释放&#xff0c;重点讲解malloc和free函数的使用方法&#xff0c;并通过实例说明相关注意事项。 一、堆内存与栈内存的区别 在C语言中&#xff0c;内存主要分为堆内存和栈内存&#xf…

探索 Oracle Database 23ai 中的 SQL 功能

探索 Oracle Database 23ai 中的 SQL 功能 介绍目标前提条件 功能 1&#xff1a;使用 FROM 子句功能 2&#xff1a;使用 BOOLEAN 数据类型功能 3&#xff1a;使用 IF NOT EXISTS DDL 子句功能 4&#xff1a;使用 INSERT 插入多行功能 5&#xff1a;使用新的 VALUE 构造函数功能…

SQL(6)

! 会排除null数据 select name from Customer where referee_id ! 2 or referee_id is null; 交叉联结 交叉连接&#xff08;CROSS JOIN&#xff09;-CSDN博客 197. 上升的温度 select a.id from weather as a cross join weather as b on datediff(a.recordDate ,b.recordD…

【Java面试题】cookie、session、jwt/token的异同

以下是对Cookie、Session、Token与JWT的异同的完善分析&#xff0c;结合技术原理、安全性和应用场景进行系统性对比&#xff1a; &#x1f50d; 一、核心概念与工作流程 机制定义工作流程核心特点Cookie客户端存储的小型文本数据1. 服务器通过Set-Cookie响应头下发数据2. 浏览…

数字经济时代科技创业的巨大潜力

2025年3月&#xff0c;42岁的字节跳动创始人张一鸣以655亿美元身家成为中国新首富。这位"80后"企业家白手起家的故事&#xff0c;展现了数字经济时代科技创业的巨大潜力。本文将带您了解张一鸣的成功秘诀&#xff0c;分析网络安全行业的最新趋势&#xff0c;并为计算…

深入剖析Nginx架构及其不同使用场景下的配置

一、Nginx 整体架构概览 1. Nginx简介 Nginx 是采用 C 语言 编写的高性能 Web 服务器、反向代理服务器及邮件代理服务器&#xff0c;特点是&#xff1a;高并发、高可用、低内存占用、模块化设计。 架构核心理念&#xff1a; Master-Worker 多进程模型 事件驱动&#xff08;…

单元测试详解

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 对于软件测试&#xff0c;我们先按照开发阶段来进行划分&#xff0c;将软件测试分为单元测试、集成测试、系统测试、验收测试&#xff0c;下面我们来聊聊单元测试。…

四款好用的Windows虚拟打印机,文档转PDF

1&#xff0c;Microsoft Print To PDF 2&#xff0c;Foxit Reader PDF Printer 3&#xff0c;Adobe PDF 4&#xff0c;clawPDF 参考文档&#xff1a; https://mp.weixin.qq.com/s/_mt4J2RwhqQE36DRAvc-Rg

《map和set的使用介绍》

引言&#xff1a; 上次我们学习了第一个高阶数据结构—二叉搜索树&#xff0c;趁热打铁&#xff0c;今天我们就再来学习两个数据结构—map和set。 一&#xff1a;序列式容器和关联式容器 前面我们已经接触过STL中的部分容器如&#xff1a;string、vector、list、deque、arra…

PostgreSQL(二十六)分区表管理

目录 一、分区表特点 1、概念&#xff1a; 2、好处&#xff1a; 3、特点&#xff1a; 二、范围分区介绍 1、简介 2、范围分区实验&#xff1a; 三、list分区介绍 1、简介 2、list分区表实验 四、hash分区介绍 1、简介 2、hash分区表实验 五、混合分区介绍 1、简…

概率论中的生日问题,违背直觉?如何计算? 以及从人性金融的角度分析如何违背直觉的?

一、生日问题的概率计算&#xff1a;为何23人就有50%概率撞生日&#xff1f; 1. 问题背景与直觉矛盾 生日问题指&#xff1a;在n个人中&#xff0c;至少有两人生日相同的概率超过50%时&#xff0c;n的最小值是多少&#xff1f; 直觉判断&#xff1a;因一年有365天&#xff0c…

Qt for WebAssembly官方说明文档

链接 Qt for WebAssembly | Qt 5.15

前端自主实现将vue页面转为pdf文件下载

1.vue 转 PDF 在 Vue 项目中将 HTML 页面转换为 PDF 文件是一个常见需求&#xff0c;特别是在需要生成报告或打印页面时。本文将介绍如何使用 html2canvas 和 jspdf 库实现这一功能。 2.安装依赖 首先&#xff0c;我们需要安装两个库&#xff1a;html2canvas 和 jspdf 。可以…

TCP 坚持定时器详解:原理、配置与最佳实践​

一、TCP 坚持定时器基础原理 1.1 坚持定时器的设计目的 TCP 坚持定时器 (TCP Persist Timer) 是 TCP 协议中用于处理接收窗口为零情况的重要机制&#xff0c;其核心设计目的是防止 TCP 连接在窗口更新 ACK 丢失时陷入死锁状态。当 TCP 连接的接收方通告一个窗口大小为 0 的 A…

大厂测开实习和小厂开发实习怎么选

先说选择&#xff0c;这个可以百分百确定选大厂&#xff0c;title很重要。 要想弄清楚那个选择对自己最有利&#xff0c;可以思考下实习的意义是什么&#xff1f; 实习无非就是给简历加分&#xff0c;拿到好offer&#xff0c;高薪offer。 那这就需要思考&#xff0c;简历怎么让…