Contact和Record-Route 解释

Contact and Record-Route headers explained – The Smartvox Knowledgebase

诊断VoIP中的一些问题需要仔细检查正在交换的SIP消息,但在许多情况下,对松散路由的良好理解将是非常有用的。支撑松散路由的标头是Contact、Record Route和Route。在这篇文章中,我解释了它们是如何工作的,并对它们的交互方式提供了一些见解。

一些首字母缩略词和术语

UAC  用户代理客户端(例如,VoIP手持设备)

UAS  用户代理服务器(例如,IP-PBX,如Asterisk)

SIP Proxy 作为UAC和UAS之间的中间节点运行的服务器

URI * 统一资源标识符。典型格式“sip:<username>@<domain>”

Sequential Request  作为已建立对话一部分的SIP请求。它将有一个“to-tag”。顺序请求在建立对话的初始请求(initial request)之后。

*<domain>元素通常显示为<host>,可能表明它可以是域或IP地址。它还可以附加端口号(在冒号分隔符之后)。e、 g.sip:12345@192.168.20.123:5144

如果您想深入研究用于标识URI子组件的术语,并了解它如何与SIP头上下文中的参数相匹配,那么您可能会发现本文很有趣。

Contact头的功能是什么?

Contact头包含一个URI,当其他节点和与它通信的设备(在同一对话中)希望向它发送SIP请求时,应使用该URI。通常在所有SIP请求中都可以找到Contact头,在SIP响应中也可以找到联系人头。它的作用可以通过例子得到最好的说明。

从最简单的情况开始:两个端点;一方通过向另一方发送SIP请求(例如INVITE)来启动对话。Contact头由发起对话的设备(UAC)插入到SIP请求中。它由下游端点(UAS)接收,UAS必须存储联系人地址URI,以备稍后在对话中使用。

 请记住,SIP响应的路由(例如“180振铃”或“200 OK”)由Via标头决定。当下游(downstream)端点需要向上游发送SIP请求时,会使用Contact标头。然而,上游端点一旦接收到URI,就可以在连续请求中使用来自下游设备的Contact标头的URI。

我们什么时候可以看到端点向上游发送请求,如上图所示?一个明显的例子是BYE请求。如果被叫方先挂断,则会向被叫方的设备上游发送BYE请求,告知呼叫已结束。在呼叫设置阶段提供的Contact报头告诉被叫设备在这种情况下如何寻址呼叫设备。 

需要注意的是,Contact 头定义了一个URI,而不仅仅是IP地址和端口。呼叫设备通常希望上游请求中的Request-URI(R-URI)使用它在原始Contact头URI中写入的相同<username>元素。然而,许多设备可以容忍并接受URI域已更改的请求。这一点很重要,因为当UAC设备位于NAT之后时,它允许中间代理修复联系地址(此处详细讨论)。Contact 头还可能包括参数,您希望在上游请求时将这些参数复制到R-URI。下面是NAT后面的设备的联系人标头示例,其中还包括两个参数:

Contact: "John Quick" <sip:1005@192.168.0.81:2048;line=n01ly175;transport=tcp>

 注:这里的John Quick是username

Introducing the Record-Route header

上面的图表和示例使用高度简化的案例说明了核心原则,但不幸的是,它与现实世界没有太多相似之处,因为除了基于局域网的PBX扩展之外,两个端点直接相互通信是非常罕见的。为了使其更现实,我们需要在调用和被调用设备之间的通信路径中至少包括一个代理服务器或SBC。

SIP代理服务器使用的标准解决方案涉及添加另一个标头,即Record-Route标头,以将自身标识为中间节点

 

当向上游发送请求时,Record-Route头会重新生成为Route头。稍后将对此进行详细介绍,但在继续之前,首先我必须指出一个相关的次要问题。SIP标准描述了两种不同的技术,用于记录路由标头(及其反向部分路由标头):

  1. 严格路由
  2. 松散路由

在我的博客帖子/维基文章中,包括这篇文章,我只讨论了松散路由。如果您想了解严格路由,请从其他在线资源中查找信息。我相信谷歌搜索会找到很多关于这个话题的材料。所以请接受我所有的wiki文章都假设了松散路由。现在,让我们回到这篇文章的主题。 

How Record-Route headers are used

此时,我将故意增加情况的复杂性,因为这有助于说明记录路由头在实践中是如何操作的。当有多个代理服务器时会发生什么?

链中的每个代理都会添加一个新的Record-Route头,其中包含自己的地址。它总是将其添加到任何现有RR标头之上–顺序很重要。在上面的示例中,当SIP请求到达UAS时,它包含三个RR头。整个RR标头集描述了通过所有中间节点的路径。结合联系人报头,这提供了通向呼叫设备的上游路径的完整描述。 

UAS对返回UAC的路径有完整的描述,但此时UAC对路径、中间节点甚至UAS的地址一无所知。它也需要知道路径,例如,当它想在当前对话中向UAS发送更多请求时。那么,如何交换这些信息呢?答案相当简单——UAS在其响应中包含所有记录路由头的完整副本。它还在响应中包含自己的Contact头。响应遵循的路径由Via标头定义,RR标头存在于响应中,但不影响其传输路径。

 所以现在,UAC和UAS都有一个完整的记录路由头集的副本。这对于松散的工作路线至关重要,并且发生在对话开始时。以下是包含两个记录路由头的真实SIP INVITE请求的编辑示例:

INVITE sip:1009@92.153.251.246:5060 SIP/2.0
Record-Route: <sip:82.0.128.19:5060;lr>
Record-Route: <sip:89.200.14.123:5060;lr;MPXON=Y>
Via: SIP/2.0/UDP 82.0.128.19:5060;branch=z9hG4bKf01e.56789d1.0
Via: SIP/2.0/UDP 89.200.14.123:5060;branch=z9hG4bKf01e.f9f91e21.0
Via: SIP/2.0/UDP 192.168.24.12:5144;received=86.4.139.77;branch=z9hG4bK161987113;rport=4454
From: “John Quick” <sip:1001@svr2.smartvox.co.uk:5061>;tag=2014274981
To: <sip:1009@svr2.smartvox.co.uk:5060>
Call-ID: 115377082-5144-3@BJC.BGI.A.BC
CSeq: 21 INVITE
Contact: “John Quick” <sip:1001@86.4.139.77:4454>

请注意,Record-Route头都是包含参数“lr”的。这一点非常重要,它表明使用的是松散路由形式。其中一个RR标头还有一个自定义参数“MPXON=Y”,用于显示媒体代理处于活动状态。当呼叫被应答时,您会在“200 OK”响应中,看到完全相同的这两个Record-Route头。 

一旦建立了“Route Set”,两个端点都会记住它。一旦建立了对话,代理们就不应该在该初始事务之后再插入任何Record-Route头。并且,所有接下来的的SIP请求都应该包含Route headers。

引入Route标头(Route headers)

在顺序请求中,Route Set用于创建一组路由头。这些标头的顺序很重要–上游服务器将颠倒顺序,但下游服务器不会。下一个图是使用松散路由的下游顺序SIP请求的表示:

 …这是上游请求的等效图:

松散路由机制的快速解释

请求的路径由嵌入的Route头决定。当它们收到松散路由请求时,中间节点(代理)应在最顶端的Route头中找到自己的地址。然后,他们有责任去掉这个最顶端的路由头,并检查是否还有其他路由头。如果有更多路由头,则使用下一个路由头来确定路径中下一个节点的地址。重复此过程,直到到达最后一个节点。此时,所有路由头都已使用,最后一个跃点使用Request-URI进行路由

您可能会遇到一些变化

双RR标头

当代理在一个网络接口上接收到请求并使用不同的接口(例如WAN到LAN)向前发送时,通常需要添加额外的记录路由标头。例如,代理必须添加两个RR头,通常您可能希望它添加一个RR头。当代理从一个传输协议转码到另一个传输协议时,也会发生同样的情况——例如,如果代理接收到WebRTC请求并将其作为TCP转发。在添加两个记录路由头的情况下,还应添加参数“r2=on”。下面是一个示例:

Record-Route: sip:192.168.10.11:5060;transport=tcp;lr;r2=on;did2=09c.7ab64763>
Record-Route: sip:86.4.139.77:5060;transport=tcp;lr;r2=on>

RFC 5658是在这些特殊情况下使用双RR头的官方规范文件。

拓扑隐藏

OpenSIPS的TOPOLOGY_HIDING模块在使用时,不会以此处所述的方式使用Record-Route和Record头。相反,它将有关上游和下游路径的信息存储在内存中,并将唯一的键值插入到联系人标头中,稍后使用该标头从内存中恢复所需的信息。

“received”参数

在某些情况下,您可能会在路由标头中看到“received”参数。它用于指定与标头中定义的主地址不同的地址。如果正在使用松散路由来访问NAT后面的设备,其中设备的Contact URI提供了一个IP地址,但网络连接需要使用不同的地址,例如,Contact URI使用LAN地址,并且访问该地址的唯一方法是通过NAT路由器外部端口上的公共IP地址,则有时可以使用此格式。

“alias”参数、连接重用和RFC 5923

当使用TCP或TLS连接到SIP代理时,可能会忽略路由标头中显示的端口,因为代理更喜欢重新使用预先存在的连接。这种行为有点难以详细解释,如果你想理解的话,我建议你参考RFC 5923。严格来说,只有在先前请求中接收到的Via中存在“alias”参数时,才会发生这种情况,但OpenSIPS还有一个核心函数 force_tcp_alias(),即使“alias”参数不存在,也会触发相同的行为。

 

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值