Network Working Group                                       J. Rosenberg
Request for Comments: 5627                                 Cisco Systems
Category: Standards Track                                   October 2009

SIP协议里,全局可路由的 UA URI(GRUU)的获取及使用

摘要

许多SIP协议的应用要求UA构造并分发一个URI给Internet的任意实体,以便其他人可把呼叫路由给这个特定的UA实例。我们把描述路由到特定UA实例的URI称为全局可路由UA URI(GRUU)。本文档描述SIP协议的一种扩展,定义了从注册服务供应商获取GRUU用于dialog内通信的方法。

备忘录状态

本文档为Internet社区定义了一种标准跟踪协议,请求对其讨论和收集建议。如需了解本协议的标准化进展,请参考最新版本的《Internet   Official Protocol Standards" (STD 1)》。本文档的分发不受任何限制。

版权声明

版权所有(c) 2009:IETF及标识为文档作者的个人。保留所有权利。

本文档自发布之日起,受BCP 78和IETF法律文书(http://trustee.ietf.org/license-info)的保护。请仔细阅读这些文档,因为他们描述了您使用这些文档所享有的权利和受到的限制。从本文档提取代码,必须按法律条款中第四章的规定,遵循BSD授权规则,包含BSD授权声明条款。

本文档可能包含IETF在2008年11月10日之前公布的文件或材料。某些材料的版权所有人可能没有授予IETF信托基金在IETF标准流程之外修改这些材料的权利。在没有获取版权所有人授权的前提下,不允许在IETF标准过程之外对本文档所涉及的材料进行修改;也不允许在IETF标准过程之外创建其衍生作品。格式化RFC出版物或将其翻译为英语之外的其他语言是允许的。

目录

摘要

备忘录状态

版权声明

1.  引言

2.  术语

3.  操作概述

3.1.1.   暴露潜在AOR的GRUU

3.1.2.  隐藏潜在AOR的GRUU

3.2.  获取GRUU

3.3.  使用GRUU

4.  UA行为

4.1.  生成REGISTER 请求

4.2.  从REGISTER 应答消息中学习GRUU

4.3.  构建‘自制’GRUU

4.4.  使用自己的GRUU

4.4.1.  针对多个AOR实例的考虑

4.5.  Dereferencing a GRUU(GRUU的解除引用?)

4.6.  在UI上呈现GRUU

5.  注册服务器行为

5.1.  处理REGISTER 请求

5.2.  生成REGISTER 应答

5.3.  注册超时

5.4.  创建 GRUU

5.5.  Registration 事件支持

6.  Proxy 行为

6.1.  请求的目标

6.2.  Record-Routing

7.  语法

8.  需求

9.  流程实例

10.  安全考虑

10.1.  外部攻击

10.2.  内部攻击

10.3.  隐私考虑

11.  IANA 考虑事项

11.1. 头域参数

11.2.  URI 参数

11.3.  SIP 选项标签

12.  鸣谢

13.  参考文献

13.1.  参考规范

13.2.  参考信息


1.  引言

在会话初始化协议(SIP)RFC3261的定义里,引用实体的基本单位是地址记录(AOR)。然而,在一个SIP系统中,单个用户可以拥有多个UA(手持设备、软电话、语音信箱账号,等等),所有这些都通过同一个UA引用。在很多上下文中,我们需要一个指向具体UA的标识符,而不是指向一组UA的逻辑标识符AOR。

举个例子:考虑一个盲转(请参考RFC5889 [19])的场景:用户A正与用户B通话,这时用户A希望把电话转给用户C。因此,用户A向用户C发出一条REFER消息。下面是REFER消息的片段:

     REFER sip:C@example.com SIP/2.0From: sip:A@example.com;tag=99asdTo: sip:C@example.comRefer-To: (URI that identifies B's UA)

在Refer-To报头里,需要包含一个URI,让用户C可以取代用户A与用户B通话。这时,用户C所发起的通话,需要路由给用户B正在使用的UA,否则,转移可能会失败。比如说,如果A向C提供的是B的AOR,这时B正用他的手持设备通话,那么C发起的呼叫很可能被路由到语音信箱。

为了方便通信,用户B在SIP交换中向用户A提供了一个实例相关的URI(Contact 报头里的设备URI)。这个URI指向了用户B当前所使用的UA,它可以由用户C间接引用。用户B并不知道用户A会把电话转移给谁,因此,这个URI事实上是可以被任何人引用的。

当前,许多client端试图通过Contact报头所携带的IP地址来寻找它们所需要的实例关联的标识信息。但是,由于NAT、防火墙的存在,外部连接的clietn很可能是用不上这些信息的。使用hostname标识也会面临类似的问题。更何况,许多SIP client自己没有获取hostname的能力。

本规范描述了一种机制,它提供了一种全局唯一的UA标识符,可用于全局路由。我们把这种标识符称为全局可路由的UA URI(GRUU)。

2.  术语

本规范中,关键字"MUST必须", "MUST NOT不许", "REQUIRED要求", "SHALL应当", "SHALL NOT不当",   "SHOULD应该", "SHOULD NOT不该", "RECOMMENDED建议", "MAY可能", 和"OPTIONAL可选"的定义遵循RFC2119。

此外,本规范定义了以下专用术语:

contact:  术语 "contact",全小写时,指的是通过注册绑定到AORt和GRUU的URI。通常,contact是一个SIP URI,它通过REGISTER请求的Contact头域携带,绑定到AOR和GRUU上。

remote target:  术语 "remote target" 是一个URI,UA用它标识自己,用于接收dialog内和dialog外的请求。"remote target" 是在建立dialog的交互过程中建立的,通常是在请求和应答消息里的Contact头域中携带,它可以在后续的刷新请求和应答中更新。

Contact 头域:  术语"Contact头域",指的是在REGISTER请求及应答消息、重定向消息,或创建dialog的请求及应答中消息携带的消息报头。根据不同语义,"Contact头域"有时承载的是"contact";有时承载的是remote target。

3.  操作概述

GRUU背后的基本思想很简单。GRUU由某个SIP域颁发,通常可以路由到这个域内的一台proxy。反过来,SIP域负责维护GRUU和特定UA实例之间的绑定。当发出SIP请求解除GRUU绑定时,这个请求会被路由给这台proxy。它负责特定UA实例的contact和GRUU之间的映射,因此把消息路由给它。

3.1.  GRUU的结构

GRUU是一个SIP URI,它拥有两个属性:

o  它路由到一个特定的UA实例。

o  它可以由Internet上的任意UA解绑,不局限于GRUU指向的UA实例所在的域。

原则上,只要满足上述两条,就可以选择任意方式来构造GRUU。但是,为了让GRUU的接收方可以知道这两个属性,要求所有GRUU包含"gr" URI参数(带不带值都可以)。

在实践中存在两种不同的GRUU:

1.  暴露潜在AOR的GRUU

2.  隐藏潜在AOR的GRUU

3.1.1.   暴露潜在AOR的GRUU

在很多场景中,构建GRUU时,会显式映射AOR。比如说,很多UA保留呼叫日志,记录呼叫的尝试。如果UA呼叫一个GRUU(也许是呼叫转移请求触发的结果),那么呼叫日志中将会包含GRUU信息。因为日志最终是要呈现给用户的,那么如果日志内容里用AOR描述将是会很有帮助的,因为AOR对用户来说是有意义的标识符。

这种GRUU称为公共的GRUU。构造时,取AOR的值,加上"gr" URI参数,其值是由域内注册服务器生成的。"gr" URI参数的值 表示具体的UA实例。假设有这么一个AOR:"sip:alice@example.com",那么对应的GRUU可能是:

sip:alice@example.com;gr=kjh29x97us97d

如果接收终端删除"gr" URI参数,那么结果就是取AOR的值。很多系统会忽略它们不能处理的参数,这时公共GRUU就等价于AOR。

3.1.2.  隐藏潜在AOR的GRUU

在其他一些场景中,我们希望构造GRUU时隐藏AOR的信息,不让接收方提取。这样的GRUU称为临时GRUU。最明显的用途是保护用户的隐私。这时,只要GRUU满足3.1 和5.4要求就行,它可以携带任何内容,只要不让别人猜出AOR就行。这时GRUU携带的"gr" URI参数可以不带参数值。为了避免在注册服务器建立过多的状态,通常通过算法构造“无状态的”GRUU,具体请参考附录A。

下面是一个无状态GRUU的具体实例:

sip:asd887f9dfkk76690@example.com;gr

3.2.  获取GRUU

UA有多种获取GRUU的途径:

o  作为REGISTER 事务的组件

o  UA本地构造,使用自己的IP地址或主机名作为URI的domain组件,描述UA实例。这称为自制GRUU。只有在UA的IP或主机名是全局可见的前提下,这个GRUU才是真正意义上的GRUU。

o  通过一些指定的本地管理机制。

如果UA希望通过REGISTER请求获取GRUU,那么它要在Contact头域中携带一个"+sip.instance"参数,传递instance ID(RFC5626),比如:

 Contact: <sip:callee@192.0.2.2>;+sip.instance="<urn:uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6>"

注册服务器发现这个参数,在REGISTER 的应答消息中提供两个GRUU,其中一个是临时GRUU,一个是公共GRUU。消息中,这两个GRUU分别用"temp-gruu" 和"pub-gruu"参数描述(Contact 头域)。比如:

<allOneLine>Contact: <sip:callee@192.0.2.2>;pub-gruu="sip:callee@example.com;gr=urn:uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6";temp-gruu="sip:tgruu.7hs==jd7vnzga5w7fajsc7-ajd6fabz0f8g5@example.com;gr";+sip.instance="<urn:uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6>";expires=3600</allOneLine>

注意:the <allOneLine> 这个tag的用法如附录[17]所述。

UA刷新注册时,注册服务器将返回同一个公共GRUU,但会建立一个新的临时GRUU。尽管每次刷新都会创建一个新的临GRUU,但是之前REGISTER应答中学习到的所有临时GRUU的contact在期生命周期中依然有效,只要满足下列条件:(1)这个instance ID指向的contact依然在注册;(2)与之前的reg-id (附录14RFC5626)实例比较,UA没有变更REGISTER请求中的Call-ID。当实例的最后一个contact超时后,无论是因为注销还是因为定时器触发,所有临时GRUU都将失效。同样,如果注册方刷新contact时(或者使用RFC5626,reg-id)变更了Call-ID,那么之前的所有临时GRUU都将失效。如果UA后来用同一实例ID发起注册,那么得到的公共GRUU是同一个,但临时GRUU会是全新的(因为已经刷新过了),此外,直到下次刷新之前,这个临时GRUU将是唯一的有效ID,因为前面的ID因为实例ID变更已经抢失效了。因此,临时GRUU在注册生命周期内是可以“积累的”。

3.3.  使用GRUU

一旦UA从注册服务器取得GRUU,就拥有了多少使用它的方式。首先,可以把它作为非REGISTER请求及应答(比如INVITE消息和对应的200 OK)的Contact头域的内容。根据RFC3261的定义,Contact头域携带了可以直接路由到这个UA的URI。在本规范之前,还没有真正满足这一需求的方式出现。UA可以在匿名呼叫中使用临时GRUU,其他场景使用公共GRUU。

此外,UA可以在其他需要解析指向自己的地方使用GRUU,比如WEB页面上。

3.4.  GRUU解析引用

因为GRUU就是一个简单的URI,所以,引用的方式和其它URI没什么不同。但是,当请求路由到对应的proxy时,它的处理行为却稍微有点不同。proxy需要把GRUU映射为AOR,并从注册实例中确实GRUU指向的具体实例。然后,把消息路由给指定的实例。

4.  UA行为

本章定义UA的行为规范。

4.1.  生成REGISTER 请求

当遵循本规范的UA生成REGISTER请求时,它必须在请求中包含Supported头域。Supported头域中必须包含"gruu"选项标签。这告诉注册服务器UA支持GRUU机制。这类Contact头域字段不应(SHOULD NOT)包含"pub-gruu"或"temp-gruu"。

此外,如果UA希望获取GRUU,那么它的每个contact必须携带一个"sip.instance"媒体特性标签(参考RFC5626[14])作为UA特征(参见[7]),其值必须是标识当前注册的UA实例的ID。基于RFC 3261 [1]的等价规则比较,contact URI不允许(MUST NOT)等价于To头域里的AOR。如果contact URI是一个GRUU,那么它不允许(MUST NOT)为To头域里的AOR的GRUU。

根据RFC 3261 [1],REGISTER刷新请求中的Call-ID应当(SHOULD )完全等同于先前注册contact的Call-ID。带GRUU时,有一个额外的考虑。如果在注册刷新时Call-ID有变化,那么服务端将废弃之前所有与这个UA实例关联的临时GRUU,唯一有效值将是REGISTER应答中新生成的那个。遵循RFC 5626时,这一规则适用于reg-id:如果特定reg-id注册刷新时变更了Call-ID,那么服务端将废弃之前关联到这个UA实例的所有GRUU。因此,如果UA希望让之前获取的GRUU保持效力,那么它在刷新注册时必须(MUST )用相同的Call-ID;反之,如果它想弃用之前的GRUU,可以(MAY)改变Call-ID。

请注意:如果有dialog正在进行中,并且它使用GRUU作为remote target,恰好这时UA变更Call-ID进行刷新操作,那么dialog所使用的GRUU可能会失效,导致后续的消息处理失败。

如果UA实例注册多个contact用于HA冗余备份,那么它必须遵循RFC5626[14]的定义。

使用GRUU的UA依然可以执行第三方注册,可以携带省力"+sip.instance" Contact头域字段的contact内容。

如果UA期望在对方不支持本规范时中止注册,那么它应当(MAY)在请求中携带Require头域,并在头域值上添加"gruu"选项标签。这是Supported头域之外的消息内容。至于Proxy-Require头域的使用则是没必要的,本规范也不建议。

4.2.  从REGISTER 应答消息中学习GRUU

如果REGISTER应答是2XX,每条包含"+sip.instance" 参数的Contact头域也可以包含"pub-gruu" 和"temp-gruu"参数。这两个参数分别承载UA实例的公共GRUU和临时GRUU信息。UA必须(MUST)支持以下场景的兼容:只有 "pub-gruu"参数;只有"temp- gruu"参数;两者都有。临时GRUU的有效周期限定为注册的生命周期内;公共GRUU则是跨注册的持续存在。UA每收到一个成功的REGISTER消息,都会收到一个新的临时GRUU,但公共GRUU保持不变。但是,UA必须准备好处理公共GRUU变更,因为持久性也有不确定性。如果UA在REGISTER刷新过程中针对同一contact或 reg-id变更了Call-ID,那么,它必须(MUST)丢弃之前学习到的临时GRUU。UA可以(MAY)保留零个、一个、部分或全部临时GRUU。如果UA存储了临时GRUU,那么,它必须保证GRUU不会因为UA与注册服务器之间的时钟偏差导致意外失效。因此,UA必须刷新其注册,以保证REGISTER的持续生效。对于默认的事务定时器,假设注册周期大于64秒,至少提前32秒刷新;如果注册周期小于64秒,UA应当(SHOULD )折半提前刷新。

请注意:使用RFC5626 [14],并且UA注册多流实现冗余时,只要有一个流还保持注册,那么临时GRUU就有效。因此,即使其中的一个流超时了,之前学习的其它临时GRUU依然有效。

在注册服务端强制缩短注册周期的场景下,UA通过注册事件包还了解这些变化,详见RFC3680[24]。同时实现RFC 3680和GRUU的UA,必须实现RFC 3680 [24]的扩展,以承载GRUU的信息,如RFC5628[28]所定义,因为这些是保持UA和注册服务端之间的临时GRUU集同步所需要的。更一般地说,临时GRUU的效用取决于UA和注册服务器之间的有效的临时GRUU集合的同步。没有RFC3680[24]及它的GRUU扩展支持的话,client端只有在注册周期超时之前刷新注册才能保持同步。除子强制注销之外 ,其他事件(比如说网络中断,连接失败,短暂的刷新间隔)可能导致GRUU集合的不一致。因此,本规范建议实现临时GRUU的UA同时实现RFC 3680 [24] 和RFC 5628 [28]的扩展。

REGISTER请求收到非2XX应答对之前提供给这个UA的GRUU没有影响。具体地说,如果先前成功处理过REGISTER请求,并向UA提供了一个GRUU,那么后续的注册请求失败不会删除GRUU或令其失败。

UA从REGISTER应答消息中学习到的GRUU的user和host部分必须不透明处理。也就是说,不允许(MUST NOT)UA以任何形式修改。不允许UA修改或删除它不识别的URI参数。进一步说,不允许UA添加、删除或修改proxy接收或处理请求相关的URI参数,包括:transport, lr, maddr, ttl,  user, 和comp (RFC 3486 [25])。另一个在RFC3261 [1]里定义的URI参数,method,通常不会出现在GRUU里,UA在向其它实体递交GRUU时,可以(MAY )加上method参数。类似的,RFC 4240 [26]和RFC 4458 [27]定义的URI参数是供UA使用的。这些内容不应出现在注册服务器返回的GRUU里,但是UA可以加上这些参数,以表达UA期望得到参数所描述的相关服务。

但是请注意:如果另一个UA解除GRUU引用,proxy在把Request-UR转换为注册的contact时,这些参数会丢失,除非提供了其它手段用于传递这些属性给UA。这类交付机制是目前标准化进程中的活跃主题(详见"Delivery of Request-URI Targets to User Agents" [29])。

4.3.  构建‘自制’GRUU

许多UA(比如说连接PSTN的网关、会议服务器、媒体服务器)本身不执行注册,因此不能通过注册机制获取GRUU。这类UA通常可以公开访问。这意味着该域的安全策略允许从公网上接入,并递交给UA而无需域内的proxy干预。此外,防火墙和NAT策略会允许这类请求进入网络。当UA确认满足这些条件时,可以(MAY )构建一个‘自制’GRUU。当然,如果UA执行注册时满足这些条件,也可以构建一个‘自制’GRUU。但是,本规范推荐使用注册的机制来获取。

‘自制’GRUU的域名部分等价于UA的IP地址或主机名。SIP URI的user部分则由UA任意选择。和其它GRUU一样,URI必须包含"gr"参数以标识它是一个GRUU,参数有没有值都可以。

如果UA没有执行注册,并且不能在公网上访问,那么它需要通过其它方式获取GRUU。典型的方式是配置一个GRUU,这个GRUU可以指向proxy,并由proxy配置GRUU到IP或主机的映射关系。

4.4.  使用自己的GRUU

UA在dialog内处理请求和应答填充Contact头域时,应当使用GRUU。换句话说,遵循本规范的UA应当以自己的GRUU作为 remote target。包括:

o  INVITE 请求

o   INVITE 的2xx 或 18x 应答,带 To tag的

o  SUBSCRIBE 请求(参考[5])

o   SUBSCRIBE 的2xx 或 18x 应答,带 To tag的

o  NOTIFY 请求

o  REFER 请求([6])

o  NOTIFY 的 2xx 应答

o  请求

o  UPDATE 的 2xx 应答

不使用GRUU的唯一原因是考虑隐私因素,详见10.3一节。

使用注册机制获取GRUU时,UA必须先有一个活跃的注册,进而,必须通过这个注册学习GRUU。绝不允许使用已经失效的GRUU(换句话说,不能使用已超时的GRUU)。UA既可以使用公共GRUU,也可以选择一个临时GRUU。GRUU与Call-ID关联,对于同一个UA的AOR或实例,如果GRUU的Call-ID与最近REGISTER的Call-ID不同,那么就不允许继续使用,如果使用RFC 5626 [14],那么reg-id也是一样 。如果UA按RFC3323 [15]的描述构造匿名请求,那么它应该(SHOULD )选用临时GRUU。10.3一节提供了临时GRUU与隐私保护的更完整论述。

如RFC3261 [1]所述,UA应该在自己生成的请求或应答消息中携带Supported 头域标签"gruu" 以声明自己支持gruu扩展。

4.4.1.  针对多个AOR实例的考虑

在一些SIP网络里,一个UA可以有多个AOR,不论它是隶属一个域或多个域。这时,需要考虑更全面一些。

在UA发出请求消息时,将会‘使用’其中的一条AOR。通常这个AOR会出现在请求的From头域中,并且用这个AOR关联的唯一权证信息进行鉴权。植入Contact头域的GRUU应当是和这个AOR关联的。当UA使用tel URI(如 [11]所定义)作为From 的AOR时,通常会有一个对应的SIP AOR作为tel URI的别名。那么可以把这个SIP URI所关联的GRUU作为Contact头域内容。

在UA接收请求时,2XX应答消息中,Contact头域植入的GRUU应当是与请求目标最近的实体所关联的AOR或GRUU。有很多种方式可以决定使用AOR或GRUU来发请求。比如说,UA为每个UA独立注册一个contact(URI的user部分可以区分),Request-URI(携带contact内容)里将指示具体的AOR。

4.5.  Dereferencing a GRUU(GRUU的解除引用?)

GRUU由URI参数"gr"标识,这个参数有没有值都可以。UA希望把请求发给包含GRUU的URI时,只需要知道它是要递交给指定UA实例的就行,不需要采取其他更多的措施。

有些UA实现了非标的URI处理机制来弥补很多URI不是全局可路由的不足。由于携带"gr" 参数的URI已经定义为全局可路由的了,那么UA在处理这包含"gr" 参数的URI时,就不应当再用这类(前面所说的非标)机制来处理。

因为这个实例ID是一种被叫方能力参数,那么UA可以尝试把请求发给用户的AOR,同时包含一个Accept-Contact头域 ( 由[12]定义),由它标识路由给特定实例ID的偏好。尽管这看起来与向GRUU发送请求具有相同的效果,但实际上并不是。 Accept-Contact头域描述的仅仅是主叫方的选项偏好。它们的有效性取决于UA如何构造Accept-Contact头域字段,该字段与AOR的域处理逻辑交互,从而导致请求路由到特定的实例。考虑到域内路由逻辑的可变性(例如,基于时间路由给特定contact),这对许多域路由策略都不起作用。然而,本规范并不禁止客户端尝试这样的请求,因为在某些情况下,所希望的操作确实是由偏好路由决定的。

4.6.  在UI上呈现GRUU

在UI上呈现GRUU时,建议(RECOMMENDED )删除"gr"参数。对于公共URI来说,这能如你所愿生成AOR。对于临时GRUU,看起来显示的URI是随机的。未来的工作可能会提供优化机制,让我们识别匿名的URI,和不适合呈现给用户的内容。

5.  注册服务器行为

5.1.  处理REGISTER 请求

REGISTER 请求可能带有Require头域,头域值包含 "gruu"选项标签,这说明要求注册服务器必须理解本规范才能处理这个请求。但是,它并不要求注册服务器必须建立GRUU。

当注册服务器根据RFC3261的10.3一节所描述的第七步流程处理REGISTER请求中的contact时,检查每个Contact头域是否包含"+sip.instance"参数。如果注册周期不为0,那么按本节的后续步骤继续处理contact。否则,这个contact基于RFC3261的正常规则处理。

注意:对于Contact头域值为"*",并且注册周期为0的请求,仍然按RFC 3261[1]中的定义处理——删除所有contact,而不仅仅是具有特定实例ID的contact。如本规范5.4所述,这将删除每个contact与AOR的绑定,还有每个contact与GRUU的绑定。

如果contact URI等价于AOR(根据RFC   3261 定义的规则比较),那么注册服务器必须(MUST)回403拒绝,因为这会导致环回。如果 contact URI是 To头域的AOR的GRUU,那么,基于相同原因,必须回403拒绝。如果 contact URI不是SIP URI,那么注册服务器必须回403拒绝。

接下来,注册服务器检查是否有AOR对应的有效公共GRUU存在(REGISTER 请求里的To头域内容),和实例ID(Contact 头域的"+sip.instance"参数)。如果没有有效的公共GRUU,这时应当(SHOULD )根据5.4所述构建一个。这个公共GRUU必须带"gr"参数,其值为AOR。如果contact包含"pub-gruu" Contact头域参数,注册服务器必须忽略它。UA不能以任何方式向注册服务器提供或建议公共GRUU。

接下来,注册服务器检查现有的已注册contact,是否有相同的AOR、实例ID,还有REGISTER请求是否带有流[14]标识,也就是reg-id。如果其中一条匹配,那么查找最近的注册记录,检查关联的Call-ID。如果Call-ID有变化,那么注册服务器必须废弃之前为这个实例ID(AOR)所生成的所有临时GRUU。结果是,从今往后,所有发向这些GRUU的请求都将被拒绝,状态码是404。

接下来,注册服务器应当(SHOULD )为AOR(实例ID)创建一个新的临时GRUU。创建规则将在5.4一节中描述。临时GRUU的算法必须拥有以下两项属性:

1.  必须保证生成两个相同临时GRUU的可能性非常小。

2.  给定一对GRUU,必须保证很难算出它们是否为同一AOR所发出的。

如果contact带有"temp-gruu"参数,必须忽略它。UA不能以任何方式向注册服务器提供或建议临时GRUU。

5.2.  生成REGISTER 应答

对REGISTER请求生成200 (OK)应答时,遵循RFC3261 10.3第8步所定义的流程。此外,对应答消息中的每个Contact头域,如果服务端存储了与contact相关联的实例ID,那么这个实例ID以参数的形式返回。如果REGISTER请求中有携带"gruu"选项标签的Supported头域,并且注册服务器上至少存在一个与AOR或实例ID关联的临时GRUU,那么注册服务器必须增加一个"temp-gruu" Contactu头域参数。"temp-gruu"参数值是一个引号字符串,其值是为这个实例ID最近生成的关联GRUU。此外,如果注册服务器上有这个APR(实例ID)所关联的公共GRUU,并且client端支持GRUU,那么必须增加一个 "pub-gruu" Contact头域参数。pub-gruu" Contact头域参数的值就是公共GRUU的值。

在应答消息中,不应在Require或Supported头域里携带"gruu"选项标签。

5.3.  注册超时

当已注册的contact超时时,不论是因为定时器超时还是显式的注销,它所绑定的AOR按正常删除。此外,绑定的GRUU同时删除,这是5.4所描述的关系的结果。

如果由于contact过期,某个特定的GRUU不再有任何已注册的contact绑定到它,并且该GRUU是临时GRUU,那么该GRUU必须失效。这意味着,一旦给定实例ID的最后一个contact过期,所有累积的临时gruu都会失效。

但是,如果GRUU是公共GRUU,那么注册服务器应当把它视为有效的。因此,后续指向这个GRUU的请求,在向这个GRUU重新注册contact之前,应当返回80 (Temporarily Unavailable)应答。此外,由于GRUU仍然有效,根据5.1的规则,当带有这个实例ID(AOR)的contact继续注册时,其值将继续使用。

这些规则赋予公共GRUU永久的属性。其目的是,只要AOR本身在域内是已知的,注册服务器就会尽一切努力保持GRUU的有效性。这一条约的要求级别是应当(SHOULD ),而不是必须(MUST ),因为很难达到必须的级别。注册服务器的故障可能会导致有效GRUU丢失,而本规范要求UA对这种场景保持健壮。也就是说,可以构建一个公共 GRUU,这样注册服务器就不需要为它保留任何额外的状态,但 GRUU 仍然满足本规范的要求。

5.4.  创建 GRUU

本节定义注册服务器构建和维护GRUU的附加行为。这些规则不适用于自制GRUU和不通过注册机制获取GRUU的场景。

一旦注册服务器创建一个GRUU,就要求它维护与这个GRUU相关联的信息,不论它是公共的还是临时的。每个GRUU都与一个独立的AOR及实例ID关联。当以GRUU的形式呈现时,注册服务器必须拥有判定实例ID及AOR的能力。此外,GRUU和AOR一样,可以解析为零个或多个contact。AOR解析为已注册的所有contact,但GRUU只解析为与GRUU关联的实例ID的contact。因此,一个带有实例ID的contact通常同时绑定能GRUU和AOR上,永远不会只绑定给AOR,或者只绑定给GRUU。这个关系如图1所示。图中有三个contact注册到一个AOR。其中一个contact带有实例ID 1,另外两个带有实例ID 2。在这个AOR有两个GRUU。其中一个关联实例ID 1;另一个关联实例ID 2。第一个GRUU只能解析为带有实例ID 1的contact。第二个GRUU只能解析为带有实例ID 2的contact。如果UA崩溃、重启,并以同一实例ID重新注册,或者按RFC5626 的定义进行冗余注册,那么对于同一实例ID,就会出现多个contact。如果实例ID 1的contact超期,那么AOR将会解析为两个contact;但是关联实例ID 1的GRUU,解析得到的就是零个contact。

图 1

同一个实例ID及AOR可以有多个GRUU。事实上,本规范要求注册服务器维护多全GRUU,其中公共GRUU只有一个,临时GRUU可以有多个。然而,如果两个GRUU关联到两个不同的AOR或实例ID上,那么,按照URI比较规则比较,这两个GRUU它必须是不同的。按照URI比较规则,域内的GRUU不允许与任何AOR等价,除非它是这个AOR关联的GRUU。

公共GRUU通常等价于AOR。根据RFC 3261 [1]的URI比较规则,如果某个参数只在其中一个URI里出现,那么比较时忽略这个参数。公共GRUU与AOR的区别仅在于有没有"gr" URI参数,因此它们是等价的URI。

一旦临时GRUU创建,那么在按之前描述的规则判定失效之前,注册服务器必须把它视为有效的。一旦公共GRUU创建,那么在对应AOR有效的期间内,它必须视为有效的。一旦AOR在域内判定为失效,那么它所关联的所有GRUU必须同时视为失效。

本规范没有强制指定生成GURR的机制。附录A给出了一个运行良好的算法,可以用它生成GRUU。然而,除了3.1所描述的属性之外,注册服务器所构建的GRUU还必须拥有以下属性:

o  URI的domain部分是公网的IP地址,如果给的是主机名,按RFC3263的解析流程处理,可以得到对应的公网地址。

o  如果请求是发给GRUU的,把它路由给可以访问注册数据的代理。这样的代理称为权威代理,其定义在RFC5626[14]。

5.5.  Registration 事件支持

RFC 3680 [24]定义了一种event,让client端可以了解注册服务器发生的事件。它还允许注册服务器强制修改注册内容(比如说,缩短周期强制刷新)。如果注册服务器支持RFC3860 [24]和GRUU,那么它必须同时支持RFC5628 [28]。

6.  Proxy 行为

RFC3261 16章完整定义了代理的行为规范。GRUU的处理对它有两处影响:请求权威代理定位目标和record-routing。

6.1.  请求的目标

代理收到请求时,说明它是Request-URI所指定的域的属主,并假定它可以访问定位服务器以确定请求的目标(RFC3261 16.5一节的定义),代理需要检查Request-URI。如果它包含"gr"参数,那么按URI比较规则与现有域内有效GRUU进行比较,如果找不到等价的记录,它应当返回404 (Not Found)应答。这一行为与代理处理无效URI的定义是一致的。

如果Request-URI包含"gr"参数,按URI比较规则与现有域内有效GRUU进行比较,找到匹配记录,那么 处理流程和其它URI的定位服务一样(基于RFC3261 16.5的定义),不同之处是"gr"参数不像标准规范定义那样删除。对于dialog外请求和dialog内请求的处理是一样的(dialog内请求可能带有Route头域,携带代理record-routing填充的内容)。

注意:保留"gr"参数的目的只是为了方便定位服务器查找GRUU。如果找到匹配,Request-URI将用注册的contact重写,替换GRUU及"gr"参数。"gr"参数不会被带入重写的 Request-URI中。

如果没有注册的contact与GRUU绑定,那么服务端必须返回480 (Temporarily Unavailable)应答。如果找到不止一个contact,那么有两种场景:

1.  Client端使用RFC5626[14],注册了多个contact冗余备份。这时,这些contact包含"reg-id" Contact头域参数,那么,就按RFC5626 第7章定义的规则选择contact。

2.   Client端没有使用RFC5626[14],那么这时只有在client出现崩溃,重启,并以相同ID重新注册的场景下会出现一个实例ID对应多个contact。这种情况下,这些contact没有reg-id"特征参数。这时代理必须选择最近刷新的contact。与RFC5626定义一样,如果请求指向这个目标因 408 (Request Timeout) 或430 (Flow Failed)处理失败,代理应当(SHOULD )继续尝试下一个contact(按最近刷新时间排序)。此外,如果请求收到其它失败应答,那么不允许代理重试这个实例的其它contact。

请求中的任何主叫方首选项(如RFC3841定义),都应当紧着GRUU绑定的contact处理。

从本质上讲,选择已注册的contact时,GRUU的处理和AOR一样,差别是只选择AOR所绑定的contact的子集。

需要特殊考虑注册中有Path 头域的处理(RFC3327 [3])。如果接收到的请求有Route头域,其值超出权威代理自身的范围(这在dialog 请求可能会出现),这时必须丢弃 Path URI。这是RFC3327 [3]允许的本地处理策略。GRUU的用法要求使用这类策略,以避免出现螺旋呼叫,导致失败。

代理可以对请求执行其它处理,比如执行被叫方业务,就像它处理AOR的请求目标那样。对于dialog外请求,建议采用筛选类型的功能,包括自动(比如黑白名名单)和交互式(比如通过IVR与用户协商是否接听电话)。在很多场景中,新的请求与现有dialog有关,它们可能是要尝试加入(使用RFC3911定义的Join 头域);或者可能是要替代(使用RFC3981定义的Replaces 头域)。当新请求与现有dialog相关时,UA通常会有自己的授权决定,绕过权威代理上的筛选服务可能是有意义的。但是,网络设计人员需要仔细斟酌,因为这样的能力取决于筛选服务的特定类型。

但是,前转服务,比如说呼叫前转,对于发给GRUU的请求,不应提供服务。GRUU的目的是把呼叫目标限定为指定的UA实例,这与前转操作是不兼容的。

如果请求是dialog内的。通常来说,代理应当只处理对dialog内请求有意义的服务。这也就排除筛选服务和前转服务了。

此外,指向GRUU的请求不应被重定向。在很多实例中,UA使用GRUU的目的是解决NAT和防火墙穿透,但是重定向经常会阻止为类情况的工作。

6.2.  Record-Routing

对于record-routing有两个截然不同的需求:在源端域和宿端域的需求。这些需求避免了不必要的、可能有问题的、螺旋式的请求。

如果:

o  源端权威代理收到一个创建dialog的请求,
   o  并且Contact 头域包含代理的域的GRUU,

o  并且这个GRUU是代理域内的有效GRUU,

o  并且这个GRUU与请求AOR关联,这个AOR已经通过身份认证(假设已经执行完认证机制)

o  并且请求中带有 Record-Route头域,

那么权威代理必须做record-route。如果所有条件都满足,除了与 GRUU 关联的 AOR 与请求者的身份验证不匹配之外,建议代理使用 403(Forbidden)响应拒绝请求。

如果:

o  宿端权威代理收到一个创建dialog的请求,

o  并且Request-URI包含定位服务器的资源记录(可以是GRUU或AOR),

o  并且选中的contact有一个实例ID绑定到GRUU,

o  并且注册时带有 Path URI,

那么,宿端权威代理必须做record-route。

如果代理是在源端或宿端域内,但不是权威代理,那么这个代理可以选择record-route。

如果宿端域内的代理基于某种原因(防火墙穿透、计费)要求dialog内请求经过它处理,那么它必须做record-route,此外,绝对不允许假定UA会用到应答消息里的Contact头域的GRUU(这将会导致dialog请求绕过没做record-routing的代理)。

实现者应当注意:如果UA在它的contact里使用GRUU,并且代理在注册时把自己放入Path头域里,那么无论呼叫过程中有没有record-route,这个代理都会收到dialog内请求。唯一区别是代理在dialog内请求中的topmost Route里看到的URI是什么。如果代理用record-route,看到的就是它;否则,看到的是Path URI。

7.  语法

本规范定义了两个新的Contact 头域参数:"temp-gruu" 和"pub-gruu",它扩展了RFC3261对"contact-params"的定义。此外,还定义了一个新的SIP URI参数"gr",它扩展了RFC3261对"uri-parameter"的定义。具体ABNF定义如下:

contact-params  =/ temp-gruu / pub-gruu
   temp-gruu       =  "temp-gruu" EQUAL quoted-string
   pub-gruu        =  "pub-gruu" EQUAL quoted-string

uri-parameter   =/ gr-param
   gr-param        = "gr" ["=" pvalue]   ; defined in RFC 3261

描述temp-gruu 和pub-gruu的quoted-string必须是一个SIP URI。但它们的编码与所有其他带引号的字符串一样,因此如果内容包含引号需要转义。

8.  需求

本规范的建立是为了满足以下需求的:

REQ 1:  当UA引用GRUU时,必须把请求路由给GRUU关联的特定UA实例。

REQ 2:  必须保证GRUU可以在Internet的任何地方上引用,并且保证请求可以被正确地路由。也就是说,不能限定GRUU的使用域。

REQ 3:  必须保证不需要在网络中存储附加状态就能构建GRUU的可行性。

REQ 4:  必须保证UA能获取UA实例上每条路由的多条GRUU。例如,如果UA实例主持多个会议时,每个会议都需要一个标识的URI,这就需要多个GRUU。注意:本规范并未满足这个需求,它将在另一份规范中独立处理(目前可以参考:"Delivery of  Request-URI Targets to User Agents" [29])。

REQ 5:  UA收到指向GRUU的请求时,必须能够知道GRUU调用的资源是什么,作为REQ 4的结果,这个要求是必然的。注意:本规范并未满足这个需求,它将在另一份规范中独立处理(目前可以参考:"Delivery of  Request-URI Targets to User Agents" [29])。

REQ 6:  必须保证UA向GRUU增加不透明内容的可能性。这些内容不由网络中的其他实体解释或修改,只由GRUU指向的UA实例使用。这提供了类似cookie的功能,允许UA在GRUU里嵌入状态信息。注意:本规范并未满足这个需求,它将在另一份规范中独立处理(目前可以参考:"Delivery of  Request-URI Targets to User Agents" [29])。

REQ 7: 必须保证代理通过GRUU执行服务与特性的能力。比如说,如果用户有呼叫阻止的功能,那么无论是用AOR还是用GRUU,代理都能正确地执行。

REQ 8: 必须保证dialog内的UA有能力通知对端它的GRUU,并且让对端知道这个URI表示的是一个GRUU。这对于会议和dialog复用的应用来说是必要的,因为这类应用中会在dialog传输URI。

REQ 9: 基于之前 REQ 8需求传送GRUU时,必须保证接收方UA有能力识别完整性和真实性。

REQ 10: 对于一个域来说,具有权威性的服务器必须能够构造GRUU,该GRUU可以路由到绑定到该域中AOR的UA实例。换句话说,代理也可以构造GRUU。这是在线状态应用所需要的。

9.  流程实例

图2中所描绘的流程,包含了基本的注册与呼叫建立的流程,演示了GRUU的使用方法。还有一个订阅GRUU的过程。接着是一个被叫方失败和重注册。使用RFC4475的约定来描述长消息行。

图 2

被叫方支持GRUU扩展,因此,它的注册消息REGISTER (1)是这样的:

REGISTER sip:example.com SIP/2.0
Via: SIP/2.0/UDP 192.0.2.1;branch=z9hG4bKnashds7
Max-Forwards: 70
From: Callee <sip:callee@example.com>;tag=a73kszlfl
Supported: gruu
To: Callee <sip:callee@example.com>
Call-ID: 1j9FpLxk3uxtm8tn@192.0.2.1
CSeq: 1 REGISTER
Contact: <sip:callee@192.0.2.1>;+sip.instance="<urn:uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6>"
Content-Length: 0

注册服务器分配一个临时的和一个公共的GRUU,REGISTER的应答消息 (message 2)是这样的:

SIP/2.0 200 OK
Via: SIP/2.0/UDP 192.0.2.1;branch=z9hG4bKnashds7
From: Callee <sip:callee@example.com>;tag=a73kszlfl
To: Callee <sip:callee@example.com> ;tag=b88sn
Call-ID: 1j9FpLxk3uxtm8tn@192.0.2.1
CSeq: 1 REGISTER
<allOneLine>
Contact: <sip:callee@192.0.2.1>
;pub-gruu="sip:callee@example.com
;gr=urn:uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6"
;temp-gruu="sip:tgruu.7hs==
jd7vnzga5w7fajsc7-ajd6fabz0f8g5@example.com;gr"
;+sip.instance="<urn:uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6>"
;expires=3600
</allOneLine>
Content-Length: 0

REGISTER的应答消息的Contact头域里,带有"pub-gruu"参数,其值是公共GRUU:ip:callee@example.com;gr=urn:uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6。还有一个 "temp-gruu"参数,其值为临时GRUU: sip:tgruu.7hs==jd7vnzga5w7fajsc7-ajd6fabz0f8g5@example.com;gr。这两个GRUU对AOR和实例ID都是有效的,最终都解析为contact sip:callee@192.0.2.1。

主叫发出的INVITE消息(message 3)是一个正常的SIP INVITE。但是,被叫生成的200 OK里,携带了自己的GRUU作为 remote target。这时UA选择的是公共GRUU。

SIP/2.0 200 OK
Via: SIP/2.0/UDP proxy.example.com;branch=z9hG4bKnaa8
Via: SIP/2.0/UDP host.example.com;branch=z9hG4bK99a
From: Caller <sip:caller@example.com>;tag=n88ah
To: Callee <sip:callee@example.com> ;tag=a0z8
Call-ID: 1j9FpLxk3uxtma7@host.example.com
CSeq: 1 INVITE
Supported: gruu
Allow: INVITE, OPTIONS, CANCEL, BYE, ACK, SUBSCRIBE
<allOneLine>
Contact:
<sip:callee@example.com
;gr=urn:uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6>
</allOneLine>
Content-Length: --
Content-Type: application/sdp
[SDP Not shown]

过段时间,主叫方决定订阅这个特定UA的 dialog事件(16]中定义)。因此,它生成一条SUBSCRIBE 请求(message 9),指向之前记录下来的remote target,即GRUU。

<allOneLine>
SUBSCRIBE sip:callee@example.com;gr=urn:uuid:f8
1d4fae-7dec-11d0-a765-00a0c91e6bf6
SIP/2.0
</allOneLine>
Via: SIP/2.0/UDP host.example.com;branch=z9hG4bK9zz8
From: Caller <sip:caller@example.com>;tag=kkaz-
<allOneLine>
To: <sip:callee@example.com;gr=urn:uuid:f8
1d4fae-7dec-11d0-a765-00a0c91e6bf6>
</allOneLine>
Call-ID: faif9a@host.example.com
CSeq: 2 SUBSCRIBE
Supported: gruu
Event: dialog
Allow: INVITE, OPTIONS, CANCEL, BYE, ACK, NOTIFY
Contact: <sip:caller@example.com;gr=hdg7777ad7aflzig8sf7>
Content-Length: 0

在本例中,主叫自身支持GRUU,因此它用自己的GRUU来填充remote target。

订阅请求路由到代理,它基于 Request-URI执行定位服务。最终转换为实例指向的contact,并把消息转发出去。

SUBSCRIBE sip:callee@192.0.2.1 SIP/2.0
Via: SIP/2.0/UDP proxy.example.com;branch=z9hG4bK9555
Via: SIP/2.0/UDP host.example.com;branch=z9hG4bK9zz8
From: Caller <sip:caller@example.com>;tag=kkaz-
<allOneLine>
To: <sip:callee@example.com;gr=urn:uuid:f8
1d4fae-7dec-11d0-a765-00a0c91e6bf6>
</allOneLine>
Call-ID: faif9a@host.example.com
CSeq: 2 SUBSCRIBE
Supported: gruu
Event: dialog
Allow: INVITE, OPTIONS, CANCEL, BYE, ACK, NOTIFY
Contact: <sip:caller@example.com;gr=hdg7777ad7aflzig8sf7>
Content-Length: 0

SUBSCRIBE 请求生成一条200应答(message 11),其后跟着NOTIFY(message 13 and 14)和对应的应答(message 15和 16)。接收message 16一段时间之后,被叫方的机器崩溃并重启了,它获取到一个新的IP:192.0.2.2。它不知道之前的注册,所以重新注册(message 17 以后)。但是注册时保持之前的实例ID,因为它有持久化处理。

REGISTER sip:example.com SIP/2.0
Via: SIP/2.0/UDP 192.0.2.2;branch=z9hG4bKnasbba
Max-Forwards: 70
From: Callee <sip:callee@example.com>;tag=ha8d777f0
Supported: gruu
To: Callee <sip:callee@example.com>
Call-ID: hf8asxzff8s7f@192.0.2.2
CSeq: 1 REGISTER
<allOneLine>
Contact: <sip:callee@192.0.2.2>
;+sip.instance="<urn:uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6>"
</allOneLine>
Content-Length: 0

Both contacts are

注册服务器注意到同一实例ID已经关联了另一个contact:sip:callee@192.0.2.1。它注册新的记录,并在REGISTER应答中一同返回新老记录。两个记录的公共GRUU是一样的,但重新生成临时GRUU。两条contact内容都在REGISTER应答中,但是临时GRUU的值是一样的,用最近生成的值填充。注册服务器最终发出的应答消息:

SIP/2.0 200 OK
Via: SIP/2.0/UDP 192.0.2.2;branch=z9hG4bKnasbba
From: Callee <sip:callee@example.com>;tag=ha8d777f0
To: Callee <sip:callee@example.com>;tag=99f8f7
Call-ID: hf8asxzff8s7f@192.0.2.2
CSeq: 1 REGISTER
<allOneLine>
Contact: <sip:callee@192.0.2.2>
;pub-gruu="sip:callee@example.com;gr=urn:
uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6"
;temp-gruu="sip:tgruu.7hatz6cn-098shfyq193=
ajfux8fyg7ajqqe7@example.com;gr"
;+sip.instance="<urn:uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6>"
;expires=3600
</allOneLine>
<allOneLine>
Contact: <sip:callee@192.0.2.1>
;pub-gruu="sip:callee@example.com;gr=urn:
uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6"
;temp-gruu="sip:tgruu.7hatz6cn-098shfyq193=
ajfux8fyg7ajqqe7@example.com;gr"
;+sip.instance="<urn:uuid:f81d4fae-7dec-11d0-a765-00a0c91e6bf6>"
;expires=400
</allOneLine>
Content-Length: 0

UA不需要刻意去删除残余的contact。请求目标定位时,按6.1一节的描述,会自动递交给最近刷新的地址。

10.  安全考虑

SIP网络中使用GRUU时,攻击可以分为外部(第三方攻击系统)和内部(攻击者是内部的恶意元素)。此外,使用GRUU时还需要考虑隐私保护。

10.1.  外部攻击

对于 UA 来说,确保 REGISTER 响应中给出的 GRUU 的完整性很重要。 如果 GRUU 被攻击者篡改,结果可能导致对 UA 的拒绝服务 (DoS)攻击。 因此,建议 UA 在注册时在 Request-URI 中使用 SIPS URI 方案。 代理和注册服务器必须支持 SIPS URI 并且必须支持 TLS。 这并没有变更RFC 3261 [1] 中的要求。。

附录A.1所给的构建GRUU算法,并没有尝试隐藏GRUU所关联的AOR和实例ID。通常,AOR与GRUU明确关联是和个很好的属性,因为它可以轻松跟踪特定的呼叫目标。了解实例ID对攻击者来说几乎没什么好处。注册攻击需要截获用户的鉴权凭据,只知道实例ID是不够的。

附录A.1所给的构建GRUU算法,并没有尝试防止用户根据AOR和实例ID知识猜测GRUU。能够执行这个操作的用户,同样能够在别的实例上直接发起新的请求。但是,本规范建议,对发给GRUU的请求,要进行特别的处理(比如说筛选)。这种处理能确定GRUU不会为攻击者留下后门,阻止外部攻击用户的试图。

10.2.  内部攻击

使用本规范的结果,UA将从dialog的创建和刷新过程中开始使用GRUU。这些GRUU又会传递给其它UA(称为通讯员),然后其它UA会在请求中直接使用。

如果某个恶意通信都删除 "gr" URI参数,那么请求将会被路由给权威代理。如果是临时GRUU,删除gr" URI参数会导致GRUU不与任何AOR匹配,请求被拒绝。如果是公共GRUU,删除gr" URI参数会被处理为AOR,因此,和直接呼叫AOR是一样的。由于协议允许从GRUU里提取AOR,所以这不算攻击,呼叫会被正常处理。

系统中的恶意用户可能会尝试使用 GRUU 对另一个 SIP UA 发起 DoS 攻击。为此,它将等待来自该 UA 的呼叫,并从中观察他们的 GRUU。一旦获得 GRUU,UA 将向实体(例如在线服务器)发起 SIP 请求,该实体将生成许多返回给 UA 的请求。但是,攻击者将在该 SUBSCRIBE 请求的 Contact 头域中使用攻击目标的 GRUU。这将导致流量被定向到目标。由于 GRUU 是全局可路由的,与发送到其IP 地址的流量相比,这类流量更有可能被发给攻击目标。本规范要求代理验证请求的Contact 中的 GRUU 与请求发送者的身份匹配来帮助减轻这种攻击。这类检查需要使用outbound proxy。 SIP 不强制使用outbound proxy,这确实会留下潜在的漏洞。然而,在实践中,几乎所有 SIP 部署都使用outbound proxy,因此这种漏洞不太可能成为问题。

10.3.  隐私考虑

RFC 3323 [15]定义了隐私机制。它区分了网络提供的隐私和用户提供的隐私。在前者中,用户在请求中包含Privacy 头域以从网络请求隐私服务。在后者中,UA遵循一套基本的准则来构造其请求,因此提供了一定程度的隐私。

RFC 3323[15]的4.1节中为用户提供的隐私请求定义了指导方针:UA使用一个省略user 部分的URI构造其Contact头域,并利用UA的IP地址或主机名。这样的建议与本规范中定义的规则相冲突,本规范要求在Contact头域中使用GRUU。

但是,注册服务器提供的临时GRUU可以用来代替RFC 3323[15]中描述的Contact URI格式。UA从每个REGISTER响应中收集临时GRUU,并缓存其中的一小部分。当它发出或接收一个呼叫时,可以使用一个临时GRUU来填充Contact头域。

UA可以选择在所有呼叫中使用同一个临时GRUU,也可以选择每个通呼叫换一个临时GRUU。选择取决于隐私考虑的程度。

o  如果UA在所有的呼叫中使用同一GRUU,那么将允许通讯员基于Contact头域组织调查,将来自同一UA的呼叫关联起来。RFC 3323[15]提供的的隐私过程也是如此,因为Contact URI中的IP或主机名提供了一种类似的关联性。

o  UA.如果UA的每通电话使用不同的GRUU,那么通讯员将不能基于Contact头域组织调查,因为其内容不能提供关联性。

o  在上述两种场景中,如果没有提供网络级的隐私保护,那么SDP协议里的IP地址和端口可以为通讯员提供呼叫来自同一UA的线索。

o  在两种场景中,如果用户发起呼叫,通讯员都能够通过Contact 头域里的GRUU发起回呼。类似呼叫转移和通过网络应用服务收集数据(RFC4730)的特性实现是有可能的,它们依赖于Contact里的GRUU。在注册失效之前,这些入局请求都是可行的。UA如果希望限制之前生成的临时GRUU的可见性,可以改变Call-ID刷新注册。UA不应用先注销再注册的方式来使之前的临时GRUU失效,因为这会导致短时间内的完全不可达,也会增加网络负载。用新的Call-ID刷新会更高效,它是控制临时GRUU有效性的一种粗粒度的控制。UA不希望被特定的回呼打扰,需要实现手动或自动的呼叫控制流程来拒绝它。本规范没有为UA提供让单个临时GRUU失效的能力。如果UA坚持不接收任何这类入局请求(包括诸如数字收集服务生成的请求),那么UA可以选择在Contact头域中使用非GRUU。但这是不推荐的。使用带有自动呼叫拒绝的GRUU会优越得多。

o  只要使用临GRUU填充Contact头域,通讯员将无法通过检查Contact头域确定AOR或UA实例ID的任何信息。但是,在没有网络提供隐私服务的情况下,可以通过SDP中的IP地址来确定UA的信息,如其地理位置和ISP等。

o  在所有场景中,无论UA在Contact 中使用的是临时GRUU还是公共GRUU,无论它使用GRUU与否,无论它是否使用网络提供的隐私服务,通讯员都能够确定UA的SIP服务商。

11.  IANA 考虑事项

本规范定义了两个新的Contact头域参数,和一个SIP URI参数,还有一个SIP选项标签。

11.1. 头域参数

本规范根据RFC3968[8]的定义,注册了两个新的头域参数。它们的需求信息描述如下:

参数可以出现的头域:  Contact
   参数名:  pub-gruu
   预定义值:  无
   参考RFC:  RFC 5627

参数可以出现的头域:  Contact
   参数名:  temp-gruu
   预定义值:  无
   参考RFC:  RFC 5627

11.2.  URI 参数

本规范根据RFC 3969 [9],定义注册了一个新的SIP URI参数,具体信息如下:

参数名:  gr
   预定义值:  无
   参考RFC:  RFC 5627

11.3.  SIP 选项标签

本规范根据RFC3261 27.1的准则,定义注册了一个新的SIP选项标签,其信息如下:

名称:  gruu

描述:  这个标签用于标识全局可路由的 UA URI(GRUU)扩展。当它出现在Supported头域中时,说明UA理解本扩展。当它出现在REGISTER请求的Require头域中时,要求注册服务器只有在理解本扩展的前提下才能处理注册请求。

12.  鸣谢

The author would like to thank Eric Rescorla, Robert Sparks, Rohan
   Mahy, Paul Kyzivat, Alan Johnston, Ya-Ching Tan, Dale Worley, Jeroen
   van Bemmel, Vijay Gurbani, Andrew Allen, Alan Hawrylyshen, Francois
   Audet, Fredrik Thulin, Dean Willis, David Hancock, Keith Drage, and
   Cullen Jennings for their comments and contributions to this work.
   Eric Rescorla provided the text for the introduction and the GRUU
   construction algorithm in the appendix.

13.  参考文献

13.1.  参考规范

[1]   Rosenberg, J., Schulzrinne, H., Camarillo, G., Johnston, A.,
         Peterson, J., Sparks, R., Handley, M., and E. Schooler, "SIP:
         Session Initiation Protocol", RFC 3261, June 2002.

[2]   Rosenberg, J. and H. Schulzrinne, "Session Initiation Protocol
         (SIP): Locating SIP Servers", RFC 3263, June 2002.

[3]   Willis, D. and B. Hoeneisen, "Session Initiation Protocol (SIP)
         Extension Header Field for Registering Non-Adjacent Contacts",
         RFC 3327, December 2002.

[4]   Bradner, S., "Key words for use in RFCs to Indicate Requirement
         Levels", BCP 14, RFC 2119, March 1997.

[5]   Roach, A., "Session Initiation Protocol (SIP)-Specific Event
         Notification", RFC 3265, June 2002.

[6]   Sparks, R., "The Session Initiation Protocol (SIP) Refer
         Method", RFC 3515, April 2003.

[7]   Rosenberg, J., Schulzrinne, H., and P. Kyzivat, "Indicating
         User Agent Capabilities in the Session Initiation Protocol
         (SIP)", RFC 3840, August 2004.

[8]   Camarillo, G., "The Internet Assigned Number Authority (IANA)
         Header Field Parameter Registry for the Session Initiation
         Protocol (SIP)", BCP 98, RFC 3968, December 2004.

[9]   Camarillo, G., "The Internet Assigned Number Authority (IANA)
         Uniform Resource Identifier (URI) Parameter Registry for the
         Session Initiation Protocol (SIP)", BCP 99, RFC 3969,
         December 2004.
   [10]  Handley, M., Jacobson, V., and C. Perkins, "SDP: Session
         Description Protocol", RFC 4566, July 2006.

[11]  Schulzrinne, H., "The tel URI for Telephone Numbers", RFC 3966,
         December 2004.

[12]  Rosenberg, J., Schulzrinne, H., and P. Kyzivat, "Caller
         Preferences for the Session Initiation Protocol (SIP)",
         RFC 3841, August 2004.

[13]  Crocker, D. and P. Overell, "Augmented BNF for Syntax
         Specifications: ABNF", STD 68, RFC 5234, January 2008.

[14]  Jennings, C., Ed. and R. Mahy, Ed., "Managing Client-Initiated
         Connections in the Session Initiation Protocol (SIP)",
         RFC 5626, October 2009.

13.2.  参考信息

[15]  Peterson, J., "A Privacy Mechanism for the Session Initiation
         Protocol (SIP)", RFC 3323, November 2002.

[16]  Rosenberg, J., Schulzrinne, H., and R. Mahy, "An INVITE-
         Initiated Dialog Event Package for the Session Initiation
         Protocol (SIP)", RFC 4235, November 2005.

[17]  Sparks, R., Hawrylyshen, A., Johnston, A., Rosenberg, J., and
         H. Schulzrinne, "Session Initiation Protocol (SIP) Torture Test
         Messages", RFC 4475, May 2006.

[18]  Schulzrinne, H., "Dynamic Host Configuration Protocol (DHCP-
         for-IPv4) Option for Session Initiation Protocol (SIP)
         Servers", RFC 3361, August 2002.

[19]  Sparks, R., Johnston, A., and D. Petrie, "Session Initiation
         Protocol (SIP) Call Control - Transfer", BCP 149, RFC 5589,
         June 2009.

[20]  Burger, E. and M. Dolly, "A Session Initiation Protocol (SIP)
         Event Package for Key Press Stimulus (KPML)", RFC 4730,
         November 2006.

[21]  Mahy, R. and D. Petrie, "The Session Initiation Protocol (SIP)
         "Join" Header", RFC 3911, October 2004.

[22]  Mahy, R., Biggs, B., and R. Dean, "The Session Initiation
         Protocol (SIP) "Replaces" Header", RFC 3891, September 2004.

[23]  Willis, D. and B. Hoeneisen, "Session Initiation Protocol (SIP)
         Extension Header Field for Service Route Discovery During
         Registration", RFC 3608, October 2003.

[24]  Rosenberg, J., "A Session Initiation Protocol (SIP) Event
         Package for Registrations", RFC 3680, March 2004.

[25]  Camarillo, G., "Compressing the Session Initiation Protocol
         (SIP)", RFC 3486, February 2003.

[26]  Burger, E., Van Dyke, J., and A. Spitzer, "Basic Network Media
         Services with SIP", RFC 4240, December 2005.

[27]  Jennings, C., Audet, F., and J. Elwell, "Session Initiation
         Protocol (SIP) URIs for Applications such as Voicemail and
         Interactive Voice Response (IVR)", RFC 4458, April 2006.

[28]  Kyzivat, P., "Registration Event Package Extension for Session
         Initiation Protocol (SIP) Globally Routable User Agent URIs
         (GRUUs)", RFC 5628, October 2009.

[29]  Rosenberg, J., van Elburg, J., Holmberg, C., Audet, F., and S.
         Schubert, Ed., "Delivery of Request-URI Targets to User
         Agents", Work in Progress, June 2009.

Appendix A.  Example GRUU Construction Algorithms

The mechanism for constructing a GRUU is not subject to
   specification.  This appendix provides an example that can be used by
   a registrar to construct a public and a temporary GRUU.  Of course,
   others are permitted, as long as they meet the constraints defined
   for a GRUU.

A.1.  Public GRUU

The most basic approach for constructing a public GRUU is to take the
   AOR and place the actual value of the instance ID into the contents
   of the "gr" URI parameter.

A.2.  Temporary GRUU

This specification requires a registrar to create a new temporary
   GRUU on each registration refresh.  If a registration is very long
   lived, this can quickly result in hundreds or even thousands of
   temporary GRUUs being created and allocated to a UA.  Consequently,
   it is important to have an algorithm for constructing temporary GRUUs
   that does not require additional storage that grows in size with the
   number of temporary GRUUs.  The following algorithm meets this goal.

The registrar maintains a counter, I. This counter is 48 bits and is
   initialized to zero.  The counter is persistently stored, using a
   backend database or other similar technique.  When the registrar
   creates the first temporary GRUU for a particular AOR and instance
   ID, the registrar notes the current value of the counter, I_i, and
   increments the counter in the database.  The registrar then maps I_i
   to the AOR and instance ID using the database, a persistent hashmap
   or similar technology.  If the registration expires such that there
   are no longer any contacts with that particular instance ID bound to
   the GRUU, the registrar removes the mapping.  Similarly, if the
   temporary GRUUs are invalidated due to a change in Call-ID, the
   registrar removes the current mapping from I_i to the AOR and
   instance ID, notes the current value of the counter I_j, and stores a
   mapping from I_j to the AOR and instance ID.  Based on these rules,
   the hashmap will contain a single mapping for each AOR and instance
   ID for which there is a currently valid registration.

The usage of a counter in a 48-bit space with sequential assignment
   allows for a compact representation of the hashmap key, which is
   important for generating GRUUs of reasonable size.  The counter
   starts at zero when the system is initialized.  Persistent and
   reliable storage of the counter is required to avoid misrouting of a
   GRUU to the wrong AOR and instance ID.  Similarly, persistent storage
   of the hashmap is required, even through proxy and registrar
   restarts.  If the hashmap is reset, all previous temporary GRUUs
   become invalidated.  This might cause dialogs in progress to fail, or
   future requests towards a temporary GRUU to fail when they normally
   would not.  The same hashmap needs to be accessible by all proxies
   and registrars that can field requests for a particular AOR and
   instance ID.

The registrar maintains a pair of local symmetric keys K_e and K_a.
   These are regenerated every time the counter is reset.  When the
   counter rolls over or is reset, the registrar remembers the old
   values of K_e and K_a for a time.  Like the hashmap itself, these
   keys need to be shared across all proxy and registrars that can
   service requests for a particular AOR and instance ID.

To generate a new temporary GRUU, the registrar generates a random
   80-bit distinguisher value D. It then computes:

M = D || I_i
   E = AES-ECB-Encrypt(K_e, M)
   A = HMAC-SHA256-80(K_a, E)

Temp-Gruu-userpart = "tgruu." || base64(E) || base64(A)

where || denotes concatenation, and AES-ECB-Encrypt represents AES
   encryption in electronic codebook mode.  M will be 128 bits long,
   producing a value of E that is 128 bits and A that is 80 bits.  This
   produces a user part which has 42 characters.

When a proxy receives a request whose user part begins with "tgruu.",
   it extracts the remaining portion, and splits it into 22 characters
   (E') and the remaining 14 characters (A').  It then computes A and E
   by performing a base64 decode of A' and E' respectively.  Next, it
   computes:

Ac = HMAC-SHA256-80(K_a, E)

If the counter has rolled over or reset, this computation is
   performed with the current and previous K_a.  If the Ac value(s) that
   are computed do not match the value of A extracted from the GRUU, the
   GRUU is rejected as invalid.  Next, the proxy computes:

M = AES-ECB-Decrypt(K_e, E)

If the counter has rolled over, this computation is done using the
   value of K_e that goes with the value of K_a, which produced a valid
   Ac in the previous HMAC validation.  The leading 80 bits (the
   distinguisher D) are discarded, leaving an index I_i in the hashmap.
   This index is looked up.  If it exists, the proxy now has the AOR and
   instance ID corresponding to this temporary GRUU.  If there is
   nothing in the hashmap for the key I_i, the GRUU is no longer valid
   and the request is rejected.

The usage of a 48-bit counter allows for the registrar to have as
   many as a billion AORs, with 10 instances per AOR, and cycle through
   10,000 Call-ID changes for each instance through the duration of a
   single registration.  These numbers reflect the average; the system
   works fine if a particular AOR has more than 10 instances or a
   particular instance cycles through more than 10,000 Call-IDs in its
   registration, as long as the average meets these constraints.

Appendix B.  Network Design Considerations

The GRUU specification works properly based on logic implemented at
   the user agents and in the authoritative proxies on both sides of a
   call.  Consequently, it is possible to construct network deployments
   in which GRUUs will not work properly.

One important assumption made by the GRUU mechanism is that, if a
   request passes through any proxies in the originating domain prior to
   visiting the terminating domain, one of those proxies will be the
   authoritative proxy for the User Agent Client (UAC).  Administrators
   of SIP networks will need to make sure that this property is
   retained.  There are several ways it can be accomplished:

1.  If the user agents support the service-route mechanism [23], the
       registrar can implement it and return a service route that points
       to the authoritative proxy.  This will cause requests originated
       by the user agent to pass through the authoritative proxy.

2.  The user agents can be configured to never use an outbound proxy,
       and send requests directly to the domain of the terminating
       party.  This configuration is not practical in many use cases,
       but it is a solution to this requirement.

3.  The user agents can be configured with an outbound proxy in the
       same domain as the authoritative proxy, and this outbound proxy
       forwards requests to the authoritative proxy by default.  This
       works very well in cases where the clients are not roaming; in
       such cases, the outbound proxy in a visited network may be
       discovered dynamically through DHCP [18].

4.  In cases where the client discovers a local outbound proxy via a
       mechanism such as DHCP, and is not implementing the service route
       mechanism, the UA can be configured to automatically add an
       additional Route header field after the outbound proxy, which
       points to a proxy in the home network.  This has the same net
       effect of the service route mechanism, but is accomplished
       through static configuration.

作者联系方式:

Jonathan Rosenberg
   Cisco Systems
   Edison, NJ
   US

EMail: jdrosen@cisco.com
   URI:   http://www.jdrosen.net

RFC 5627 SIP中文翻译相关推荐

  1. RFC文档(中文翻译版本)

    RFC文档官方在线阅读地址:https://tools.ietf.org/rfc/index 以下是部分中文翻译的文档连接 RFC文档目录 RFC1 主机软件 RFC2 主机软件 RFC3 文档规范 ...

  2. Internet X.509 公钥基础设施(RFC2459中文翻译)

    Internet X.509 公钥基础设施(RFC2459中文翻译) 组织:中国互动出版网(http://www.china-pub.com/) RFC文档中文翻译计划(http://www.chin ...

  3. 【转】关于HTTP中文翻译的讨论

    http://www.ituring.com.cn/article/1817 讨论参与者共16位: 图灵谢工 杨博 陈睿杰 贾洪峰 李锟 丁雪丰 郭义 梁涛 吴玺喆 邓聪 胡金埔 臧秀涛 张伸 图钉派 ...

  4. pinia中文文档 指导文档中文翻译版 pinia指导中文翻译

    Pinia 指导文档 中 文 翻 译 版 翻译者:jcLee95 Pinia 指导手册中文翻译地址(本文): https://blog.csdn.net/qq_28550263/article/det ...

  5. rfc-3227中文翻译

    本人翻译的RFC-3227,<电子证据收集.保管指南>. 译者:孙达(ntbbc@hotmail.com) 发布:networkmanager.blogchina.com 译文发布时间:2 ...

  6. 翻译是一份严谨的工作——关于HTTP中文翻译的讨论

    讨论参与者共16位: 图灵谢工 杨博 陈睿杰 贾洪峰 李锟 丁雪丰 郭义 梁涛 吴玺喆 邓聪 胡金埔 臧秀涛 张伸 图钉派007LL 图钉派111DP 图钉派-34徐浩然 辩论主题:HTTP中的&qu ...

  7. 论文中文翻译——kAFL Hardware-Assisted Feedback Fuzzing for OS Kernels

    本论文相关内容 论文下载地址--26th USENIX Security Symposium 论文中文翻译--kAFL Hardware-Assisted Feedback Fuzzing for O ...

  8. YOLOv4全文阅读(全文中文翻译)

    YOLOv4全文阅读(全文中文翻译) YOLOv4: Optimal Speed and Accuracy of Object Detection 论文链接: https://arxiv.org/pd ...

  9. ctypealpha php_php ctype函数中文翻译和示例

    PHP Ctype扩展是PHP4.2开始就内建的扩展,注意,Ctype系列函数都只有一个字符串类型参数,它们返回布尔值. $str = "0.1123"; //检查字符串所有字符是 ...

  10. sound.js # pixi辅助插件 — 中文翻译教程

    本篇博客为中文翻译博客,转载请注明出处 sound.js-pixi的交互性插件[版本3.0.11] 安装配置 加载声音文件 初始化加载的声音 播放和控制加载的声音 更改回放速率 添加回声 添加混响 产 ...

最新文章

  1. Azure Logic Apps正式发布
  2. 【转】supervisord使用
  3. iptables 工具的使用
  4. 骚操作!昨晚停网,我写了一段Python代码破解了隔壁小姐姐的wifi密码...
  5. JAVA基础知识之字节和字符
  6. 一维数组和二维数组创建,输出,Arrays.fill()替换
  7. ZAB 协议和Paxos 算法
  8. (转)15个强大的jQuery开发提示和技巧
  9. 两个表里数组字段的映射关联(stuff ,charindex,for xml path)
  10. 调用虚拟内存编译时的error处理
  11. 珍大户《认知世界的经济学》学习笔记,更新时间 2021年01月30日22:34:35
  12. 语义分割-ICCV2017 Unpaired Image-to-Image Translation using Cycle-Consistent Adversarial Networks循环一致对抗网
  13. 托马斯微积分10版积分简表101 公式修正
  14. word 图 按居中,居中不了的问题
  15. 电脑广告弹窗如何操作过滤屏蔽,经验技巧!怎样设置弹窗自动拦截?
  16. 大学生选课抢课如何提高选中概率
  17. makex机器人程序_MakeX总决赛现场参赛选手在进行机器人编程
  18. 如何设置 Mac 键盘的打字音效?
  19. 转“打工皇帝”唐骏的经验之谈
  20. 功率单位(power control)

热门文章

  1. 2021-05-09 matlab归一化和反归一化函数——mapminmax
  2. html中引入字体包
  3. ip地址自动获取背后的机制(udhcpc)
  4. miui8 android.policy,小米MIUI8系统调教记:轻快好省 畅爽静稳
  5. studio和solo哪个好_beats studio3 和solo3的区别再哪里?
  6. Python爬取豆瓣网图书评论
  7. 植被指数-RVI、NDVI、DVIEVI、GVI、PVI、EVI
  8. intouch与PLC之间通讯状态监测和设置
  9. Pytorch中文视频教程,Pytorch实战视频教程
  10. Ruby on rails 实战圣经:Ruby程序语言入门