【转】RFC3581——SIP中的rport机制
1. 介绍
RFC3581的下载地址:http://www.ietf.org/rfc/rfc3581.txt
该协议比较简短,主要用于描述rport(response-port)机制。
1.1 NAT分类
NAT:网络地址转换(NAT,Network Address Translation)属接入广域网(WAN)技术,是一种将私有(保留)地址转化为合法IP地址的转换技术,它被广泛应用于各种类型Internet接入方式和各种类型的网络中。原因很简单,NAT不仅完美地解决了lP地址不足的问题,而且还能够有效地避免来自网络外部的攻击,隐藏并保护网络内部的计算机。
NAT常用的分类如下:
l Full Cone NAT(完全圆锥型)
l Address Restricted Cone NAT(地址限制圆锥型 )
l Port Restricted Cone NAT(端口限制圆锥型)
l Symmetric NAT(对称型)
1.1.1 完全圆锥型NAT
在完全圆锥型NAT(Full Cone NAT)中,NAT会将客户机地址{X:y}转换成公网地址{A:b}并绑定。任何包都可以通过地址{A:b}送到客户主机的{X:y}地址上。如图所示:
1.1.2 地址限制圆锥型NAT
地址限制圆锥型NAT(Address Restricted Cone NAT)会将客户机地址{X:y}转换成公网地址{A:b}并绑定,只有来自主机{P}的包才能和主机{X:y}通信。如下图所示:
1.1.3 端口限制圆锥型NAT
端口限制圆锥型NAT(Port Restricted Cone NAT)会将客户机地址{X:y}转换成公网地址{A:b}并绑定,只有来自主机{P,q}的包才能和主机{X:y}通信。如下图所示:
1.1.4 对称型NAT
对称型NAT(Symmetric NAT)会将客户机地址{X:y}转换成公网地址{A:b}并绑定为{X:y}|{A:b}<->{P:q}。对称型NAT只接受来自{P:q}的incoming packet,将它转给{X:y} ,每次客户机请求一个不同的公网地址和端口,NAT会新分配一个端口号{C,d} 。如下图所示:
1.2问题描述
1.2.1 SIP Proxy无法穿过NAT回送SIP信令
因为SIP信令中的From和Contact头域记录的是私网地址和端口,NAT无法识别和转换。如图所示:
1.2.2 使用UDP Hole Punching的问题
这个内网的NAT上打了一个方向为211.136.91.58的“洞”,(这就是称为UDP Hole Punching的技术)以后211.136.91.58就可以通过这个洞与内网的192.168.1.223联系了,但是其他的IP不能利用这个洞。
在没有活动的时候,这个Hole会过期:
NAT对于地址转换关系是有一定生命期的,某个地址转换后在一段时间内没有被使用将会被清除,当这个业务流再次出现时,将会建立一个新的地址转换关系。
SIP代理无法穿越
SIP在UDP和TCP上操作。当在UDP中使用的时候,对请求的响应被发送给请求所来自的地址,端口字段带在请求的Via头字段中。一半以上的信息(例如:IP地址)带在 IP包头中,还有一半的信息(例如:端口信息)带在SIP消息头中。SIP这样做的原因是为了监听所有的信息,包括请求消息和响应消息。
但是这种方式在客户端在 NAT中的情况不适用,在NAT的环境中,回应可能发送不过去,因为与在请求中找到的地址不一样,而且此前也没有方法让客户端来得到源端口信息。
2. NAT的常用解决方案
解决NAT穿越有很多中解决方案,常用的有:
2.1 ALG(Application Level Gateway)
可以识别SIP信令,能够适当地修改数据包。ALG可以是单独的连接于外网和内网之间的设备,也可以是内置于防火墙内的插件。
当FW/NAT发现外网呼叫信令为SIP时,将其转发到ALG(应用层网关),通过ALG建立起内网伪地址终端与外网终端的通信连接。
使用ALG需要对现有设备升级改造。例如思科的路由器都支持配置ALG。
2.2 MidCom(IETF MIDCOM(Middlebox Communications)
允许第三方(MIDCOM Agent )成为受FW/NAT信任的实体,然后代表FW/NAT做出决定,强迫其开放端口传送媒体流或数据流。这些受信任的实体通过“MidCom”定义的新协议与FW/NAT进行通信。
协议的识别不由Middlebox完成,而是由外部的MIDCOM Agent完成。
使用MidCom需要对现有设备升级改造。
2.3 STUN(Simple Traversalof UDP Through Network)
IETF RFC 3489定义了如何确定由NAT分配的公网地址和端口,不需要改造现有NAT。
主要特色:
l 能够让客户端发现NAT的存在以及类型;
l 能够让客户端发现NAT的绑定生命周期;
l 可以工作在多NAT串联环境下;
l 非常简单的协议,易于实现,负载低;
l STUN服务器可以位于公网任何地方。
适用范围:
l 不适用于Symmetric NAT;
l 对于Non- Symmetric NAT都适用;
l 如果双方都位于同一个NAT之后,就不适用。
2.4 SBC(Session Border Controller)
l Signaling Solution
? SBC可以帮助SIP信令穿越已经存在的FW/NAT,而不需要对现有的FW/NAT设备做任何改变;
? 对于SIP终端,SIP终端设备会周期性发送注册消息到SBC。
l Media Traversal Solution
SBC可以把相应的媒体流发送到防火墙上的相关IP地址和端口,然后正确地使媒体流到达防火墙后的用户侧。
3 rport机制讲解
3.1 方案描述
获得IP地址是在Via头中带上received参数。为了得到端口信息,也参考了这种方式,即在Via头中带上rport属性来指明端口信息。
当在客户端和服务器之间是NAT的时候,请求可能会在NAT中创建(或刷新)一个绑定,为了让客户端收到响应信息,在事务处理的过程中这个绑定必须保持存在。大多数的NAT绑定有超过1分钟的超时时间,这超过了non-INVITE事务的持续时间,因而对non-INVITE事务的请求的响应只能在绑定存在的时候存在。INVITE事务倒是不存在这个问题。
为了保持这个绑定,客户端应该在每隔20s左右重发INVITE请求,这种重发机制需要发生在收到一个临时的响应后。
当然刚才所说的大概1分钟的超时时间也不是确定的,有时候会比这长,此时重发机制可以发慢一点,否则,可以发快一点。这些问题可参考RFC3489。
如果是支持rport机制的服务器,它需要在接收到的请求中检查Via头是否包含一个没有值的rport参数。如果有,它需要在回应中带上rport的值,这与received的处理类似。
为了穿越对称性的对称性的NAT,响应需要发送到相同的IP地址和端口。当服务器在多端口或接口的请求上监听请求时,它必须记住请求是从何处发的。对一个稳定的Proxy,在一个传输的持续时间中,记住这些东西是没有问题的。但是对于不稳定的Proxy,它不存储请求和响应中的状态信息,为了达到本规范的要求,它需要将地址和端口信息加密到Via头字段中,在响应信息到达的时候,它能提取加密的信息并将它放到响应中。
rport机制需要终端支持该种机制,因此应用情况比较受限。但是在笔者的应用场景(呼叫中心)中,主要要解决的问题是坐席能在NAT环境中穿越,给服务器发送信息。因为坐席所使用的SIP软电话是本公司开发的,所以可以保证是支持rport和received的。
3.2 实例
下面举一个发送REGISTER信息的实例,在请求信息的Via头中包含了没有值的rport参数,如下所示:
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
发送到的服务器支持rport机制,它看到请求中的rport后,将通过分析UDP包信息得到的的NAT的公网地址(124.42.4.203)和端口信息(15500)分别作为received和rport属性带给客户端:
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
客户端在得到响应信息后,知道了所使用的公网地址和端口,在而后定期重发的REGISTER信息中,Contact变换成124.42.4.203: 15500,例如新发的REGISTER信息变为:
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
![](http://www.blogjava.net/Images/OutliningIndicators/None.gif)
Content - Length:
rport方式主要是对sip信令中Via字头的扩展,不过同时也要求SIP Proxy支持该功能。
NAT之后的sip client在发送请求的时候在via字头中添加rport字段,该消息经发出后路由到SIPProxy,SIP Proxy通过检查消息的源地址和Via字段中的地址,得知该client处于NAT之后,并且基于已有的rport,将消息的真实地址即公网上的地址通过received和rport字段返回给client端,这样client就知道自己真实的公网地址,可以解决信令穿越的问题。
4. 参考文档
神州泰岳应用开发事业部郑昀《SIP穿越NAT》
RFC3581:http://www.ietf.org/rfc/rfc3581.txt