码农的菜园子 2010-09-16
对于SIP协议来说,可能有些朋友比较熟悉。在这方面,最突出的就是VoIP业务了。在VoIP业务中,常会涉及到SIP协议和SIP服务器等相关内容。下面我们就来具体看看SIP服务器当中的穿越问题吧。
1. SIP服务器问题描述
大多数传统的voip协议(SIP、h323…)在设计之初都没有充分考虑NAT穿越问题,它们只关注怎样传输呼叫信号(连线、拆线…)和应用RTP(实时传输协议)传输声音信息。
呼叫信号通常应用固定的或标准的端口,而RTP 却应用任意端口收发声音信息。
大多数防火墙/NATs没有能力将呼叫信号协议包和声音信息包捆绑在一起,同时它们也不能识别声音将向哪里发送。
这样,在呼叫者发起呼叫时,虽然呼叫可以顺利获得通过,响起振铃,被叫者也可以选择拾起或者挂断这个电话,但是,线路上会出现一方或双方都没有声音的现象。
2. NATs 和防火墙
在下面几种情况下,UDP 可能会受到NAT 或者防火墙影响:
2.1 全锥型NAT:
全锥型NAT是指所有来自同一个内部IP地址和端口的请求都被指向同一个外部IP地址和端口,而且,任何外部主机都可以通过发送信息包到这个被指向的外部地址,向内部主机发送信息包。
2.2 限制锥型NAT:
限制锥型NAT是指所有来自同一个内部IP地址和端口的请求都被指向同一个外部IP地址和端口,与全锥型NAT不同的是,只有在一个内部主机先向IP地址XXXX发送信息包后,IP地址是XXXX的外部主机才可以向这个内部主机发送信息。
2.3 端口限制锥型NAT:
端口限制锥型NAT与限制锥型NAT相像,只是限制范围包括端口号码。
具体说,只有在一个内部主机先向IP地址XXXX和端口PPPP发送信息包后,外部主机才可以通过IP地址是XXXX和端口PPPP发送信息包。
2.4 对称型NAT:
对称型NAT是指所有来自同一个内部IP地址和端口的请求,发送到特定目标IP地址和端口时,被指向同一个外部IP地址和端口。如果相同的主机通过相同的IP地址和端口向不同的目标发送信息包,指向也有所不同,而且,只有接收到信息包的外部主机才可以回复UDP信息包给内部主机。
您属于以上哪种呢?您可以通过应用一个stun客户端软件来查看:
例如:http://sourceforge.net/projects/stun/
3. SIP服务器问题详解
3.1 MVB2000作为一个NAT外部的SIP服务器,客户端在NAT内部。
(1) 呼叫来自NAT后面,MVB2000发送声音到一个私网IP
如果这个VOIP电话没有应用STUN或其它方式检测它的公网IP(=NAT防火墙上的公网IP),而是直接嵌入私网IP地址到邀请消息,那么MVB2000将不断向这个私网IP发送RTP信息包,而这些信息包会被路由器截获并删除,导致单方向说话。
(呼叫者听不到声音)
这通常是在用户不去关心NAT设备怎样应用,将nat=never、nat=no或者nat=rfc3581写入sip.conf时所发生的情况。
(2) 呼叫来自NAT后面,MVB2000发送声音到错误端口
如果电话可以检测到它的公网IP, 并且正确地置入SIP服务器的邀请字头,MVB2000就会知道向哪个IP地址发送RTP了。
但是,假设应用的是一个锥型防火墙,NAT设备发送RTP到MVB2000的端口不一定与最初的RTP端口相同,这样,MVB2000将发送信息包到最初的端口,NAT设备不会知道信息包去哪里而将其截获删除。
用户可以将nat=route或者nat=yes 写入sip.conf解决这个问题。
如果NAT后面仅仅有一部电话,您也可以查看一下这部电话使用RTP端口的范围,然后在防火墙上应用端口转移,将公网IP指向内网。
如果NAT后面有多部电话,您可以为每一部电话设定一个非重叠的RTP端口范围,这样,应用端口转移指向每一部与RTP端口范围相符的电话。
和应用一个STUN服务器(如果电话有STUN支持)一样,应用对称型NAT也将解决这个问题。
(3) 呼叫来自NAT外部的MVB2000服务器,应用全锥型NAT设备
没有SIP服务器的电话注册到MVB2000或sip.conf 里面的NAT设备IP,这样,MVB2000不会知道到哪里去查找这部电话,呼叫将被拒绝通过。
(对于所有的NAT设备都是一样的)
如果sip.conf 里面host=123.123.123.123 或者电话注册到MVB2000了,MVB2000将能够发送呼叫信号和RTP声音包到NAT设备,然后转移到这部电话。
如果电话有STUN支持,它可以打开NAT设备上的封装信息,应用IP和SDP域中SIP服务器的消息里面的端口(1个对应呼叫信号的端口、1个对应RTP的端口和1个对应RTCP的端口)
STUN也同时维护这个封装信息使之处于存活状态(检测NAT超时和发送保持存活的封装信息)。
如果电话没有STUN支持,您需要注册这部电话到服务器上,让MVB2000发送保持存活的信息(the qualify= line),确认MVB2000发送的信息比您的NAT设备超时更快。
没有STUN支持,您也需要设置NAT=yes或者NAT=route,在MVB2000服务器接收那部NAT电话声音之前,您将不能听到呼入的声音。
(4) 呼叫来自NAT外部的MVB2000服务器,应用限制锥型NAT设备
与上面所讲相同,只有被叫电话首先发出信息到NAT设备,NAT设备才可以将MVB2000来电呼叫的声音包发送到那个电话上。
您可以通过让电话发送一个注册信息,或者空SIP服务器的消息(如果您的电话支持STUN)到MVB2000服务器,打开封装信息来实现。
如果应用STUN,那么这部电话将会知道它被指向的端口和SDP信息(STUN将不必为了做封装信息而发送RTP到您的MVB2000服务器上,只在STUN服务器上操作即可)。
如果没有STUN支持,您将需要设置NAT=yes或者NAT=route,并且在MVB2000服务器没有收到来自电话的声音包之前,您将听不到声音。
注意:如果没有STUN支持,那么注册地址和代理服务器地址必须是同一个IP地址,(如果您仅仅应用MVB2000服务器没有其余的组件如SER 就不存在这个问题)。
(5) 呼叫来自NAT外部的MVB2000服务器,应用端口限制锥型NAT设备
即使我们注册这部电话到MVB2000服务器,MVB2000服务器也不能发送任何声音包到这部电话上,除非这部电话首先发送声音包到MVB2000上,而且必须采用NAT设备上的5060端口。
如果您的电话支持STUN,这部电话将发送一个空SIP服务器的消息到您的MVB2000服务器上,以便打开封装信息,像任何发送到MVB2000服务器上的RTP信息包可以打开RTP封装信息一样。
如果应用STUN,那么这部电话将会知道它被指向的端口和SDP信息(STUN将不必为了做封装信息而发送RTP到您的MVB2000服务器上,只在STUN服务器上操作即可)。
如果没有STUN支持,您将需要设置NAT=yes或者NAT=route,并且在MVB2000服务器没有收到来自电话的声音包之前,您将听不到声音。
3.2 MVB2000作为SIP服务器在NAT外部,与NAT外部的SIP代理服务器或客户端相联。
不用地址转换,不存在问题
3.3 MVB2000作为SIP客户端在NAT外部,与NAT外部的SIP代理服务器或电话相联。
不用地址转换,不存在问题
3.4 MVB2000作为SIP客户端在NAT外部,与NAT内部的SIP代理服务器相联。
您需要将端口转移到NAT上的信号端口,同时转移RTP端口(如果代理服务器也负责RTP端口)
这个问题与第一个问题相识。
3.5 MVB2000作为SIP服务器在NAT内部,与NAT内部的SIP代理服务器或客户端相联。
不用地址转换,不存在问题
3.6 MVB2000作为SIP服务器在NAT内部,与NAT外部的客户端相联。
您需要将MVB2000应用到的所有RTP端口(在RTP.conf中定义)转移到NAT上,同样,也要做SIP信号端口(sip.conf中有端口选项)转移
您也可以在sip.conf 上配置externip和localnet 选项。
3.7 MVB2000作为SIP客户端在NAT内部,与NAT外部的SIP代理服务器/电话/网关相联。
能不能工作依赖于对方的电话/网关(您必须使用externip和localnet 选项)
3.8 MVB2000作为SIP客户端在NAT内部,与NAT内部的SIP代理服务器/电话/网关相联。
不用地址转换,不存在问题
3.9 MVB2000在NAT内部,电话/网关在另一个NAT内部
针对这种情况,我们需要一个中间人来相互辨认对方,它应该是一个局外的SIP代理服务器,由它来负责SIP服务器的传输,而且所有的终端都能与它建立联接。如果希望点对点传输多媒体信息流,那么,我们需要另外一个多媒体服务器。
可以采用的解决多媒体服务器办法有:
◆Portaone's RTPProxy(适合对称型NAT,需要SER组件支持)
◆AG Projects MediaProxy(适合对称型NAT,需要SER组件支持)