06
2019
03

asterisk的NAT配置

HQY

asterisk的NAT配置

   http://www.asteriskguru.com/tutorials/sip_nat_oneway_or_no_audio_asterisk.html

这篇文章已经把该说的都说了,能理解多少是多少!

 

1. sip.conf:

Externip:在[general] context配置的属性,配置你的公网地址,这样发送sip消息时就会用该地址替换消息头的主机地址,对端解析消息后就会往这个地址发送应答消息。

Nat:该属性决定asterisk如何处理用户的连接。个人理解就是配置astersik处理收到消息的方式。

a) nat=route

asterisk 从收到的rtp包得到目地地址,把rtp包发往该地址而不是SDP中协商的每媒体地址。

b) nat=no

默认配置,根据rfc3581,asterisk会把rport和received字段添加到via域,作为应答接受地址。

http://hi.baidu.com/caoyaping/blog/item/18f15c6e724e6fd781cb4ad8.html

c) nat=never

asterisk不把rport加入via域,也不会按照route的方式处理。?

d) nat=yes


======================================转一篇关于nat的文章,原地址打不开了==============

STUN是RFC3489规定的一种NAT穿透方式,它采用辅助的方法探测NAT的IP和端口。毫无疑问的,它对穿越早期的NAT起了巨大的作用,并且还 将继续在ANT穿透中占有一席之地

STUN的探测过程需要有一个公网IP的STUN server,在NAT后面的UAC必须和此server配合,互相之间发送若干个UDP数据包。UDP包中包含有UAC需要了解的信息,比如NAT外网 IP,PORT等等。UAC通过是否得到这个UDP包和包中的数据判断自己的NAT类型。

假设有如下UAC(B),NAT(A),SERVER(C),UAC的IP为IPB,NAT的IP为 IPA ,SERVER的 IP为IPC1 、IPC2。请注意,服务器C有两个IP,后面你会理解为什么需要两个IP。 

(1)NAT的探测过程:

STEP1:B向C的IP1的pot1端口发送一个UDP 包。C收到这个包后,会把它收到包的源IP和port写到UDP包中,然后把此包通过IP1和port1发还给B。这个IP和port也就是NAT的外网 IP和port(如果你不理解,那么请你去看我的BLOG里面的NAT的原理和分类),也就是说你在STEP1中就得到了NAT的外网IP。

 熟悉NAT工作原理的朋友可以知道,C返回给B的这个UDP包B一定收到(如果你不知道,去读下我的其它文章)。如果在你的应用中,向一个STUN服务器 发送数据包后,你没有收到STUN的任何回应包,那只有两种可能:1、STUN服务器不存在,或者你弄错了port。2、你的NAT拒绝一切UDP包从外 部向内部通过(我们公司的NAT就是)。

 当B收到此UDP后,把此UDP中的IP和自己的IP做比较,如果是一样的,就说明自己是在公网,下步NAT将去探测防火墙类型,我不想多说。如果不一 样,说明有NAT的存在,系统进行STEP2的操作。

STEP2:B向C的IP1发送一个UDP包,请求C通过另外一个 IP2和PORT(不同与SETP1的IP1)向B返回一个UDP数据包(现在知道为什么C要有两个IP了吧,虽然还不理解为什么,呵呵)。

我们来分析一下,如果B收到了这个数据包,那说明什么?说明NAT来着不拒,不对数据包进行任何过滤,这也就是STUN标准中的full coneNAT。遗憾的是,full cone nat太少了,这也意味着你能收到这个数据包的可能性不大。如果没收到,那么系统进行STEP3的操作。

STEP3:B向C的IP2的port2发送一个数据包,C收到数据包 后,把它收到包的源IP和port写到UDP包中,然后通过自己的IP2和port2把此包发还给B。

和step1一样,B肯定能收到这个回应UDP包。此包中的port是我们最关心的数据,下面我们来分析:

如果这个port和step1中的port一样,那么可以肯定这个NAT是个CONE NAT,否则是对称NAT。道理很简单:根据对称NAT的规则,当目的地址的IP和port有任何一个改变,那么NAT都会重新分配一个port使用,而 在step3中,和step1对应,我们改变了IP和port。因此,如果是对称NAT,那这两个port肯定是不同的。

如果在你的应用中,到此步的时候PORT是不同的,恭喜你,你的STUN已经死了。如果不同,那么只剩下了restrict cone 和port restrict cone。系统用step4探测是是那一种。

STEP4:B向C的IP2的一个端口PD发送一个数据请求包,要求C 用IP2和不同于PD的port返回一个数据包给B。

我们来分析结果:如果B收到了,那也就意味着只要IP相同,即使port不同,NAT也允许UDP包通过。显然这是restrict coneNAT。如果没收到,没别的好说,port restrict  NAT.

(2)SIP怎么使用STUN

个人认为这是个很不值得提的问题,不过有许多人问我,还是简要提一下。其实这是个很简单的问题,SIP通过STUN得到NAT的外网IP和SIP的信令监 听端口的外网port,替换SIP注册包中的contact头中的IP和port,然后注册。这样就可以确保当有人呼叫你的的时候注册服务器能找到你。需 要提醒你的是,NAT发现一个连接超过一段时间后没有活动,它就会关闭这个影射,因此你必须间隔一端时间发送一个数据包出去以keep alive。

另外,当你要和别人建立RTP通讯的时候,不要忘记把你的SDP中的IP和PORT改成公网IP和PORT。

 

================================================================================================

 

下面对SIP协议产生NAT穿透问题,作一些解释;及提出解决的办法。 
1、大致有4种类型的NAT
a) Full Cone 完全圆锥体
b) restricted cone 受限制的圆锥体
c) port restricted 端口受限制的圆锥体
d) symmetric 对称的
其中a,b,c 也称作非对称的NAT

2、SIP终端在NAT后面,其工作有可能出现问题。原因是SIP信令走的路径,和媒体流走的路径不一样。

3、Full Cone 完全圆锥体NAT
因特网上的任何PC,可以发送数据包到IP:port对;而NAT将这个IP:port对(公网 上的)映射到内网的IP:port对(私有网络的)。

4、restricted cone 受限制的圆锥体NAT
NAT
外面的PC,只有那些内网中已有PC与之联系过的PC,才能通过这个映射 进来。例如,我通过内网的一台机器,IP 地址是10.1.1.1:123,与PC(a)联系,则PC(a)也可以通过这个NAT的映射,联系到我。而PC(b)则不行。
10.1.1.1:123 —NAT —> 202.70.65.78:10000 ——pc(a)
如果pc(b)也发送数据到 202.70.65.78:10000,则不会有数据送到10.1.1.1:123。

补充说明:
如果我也联系过pc(b),则pc(b)也可以进来了。
10.1.1.1:123 —NAT —> 202.70.65.78:10000 ——pc(b)
如果pc(b)也发送数据到202.70.65.78:10000,则数据送到 10.1.1.1:123。

5、port restricted 端口受限制的圆锥体NAT
除了4的条件外,即不但要检测pc(a)的源IP地址,还要检测其端口是否 与前面也一样。
10.1.1.1:123 —>NAT—->202.70.65.78:10000 —–> pc(a)[213.123.324.34:8000]

这个NAT只会接收从IP地址 213.123.324.34 且端口为 8000来的数据,让进入到10.1.1.1:123。

6、对称的NAT 这是关系描述最简单的一个
10.1.1.1:1000 —-NAT —–> 200.123.123.34:1234 —-pc(a)
10.1.1.1:1000 —-NAT —–> 200.123.123.34:2222—-pc(b)
这种NAT的IP:port对,对每个外部的程序,都是不同的。因而每一个外部的程 序,都有自己的映射(NAT分配的IP:port对)。而前面的三种,多个外部程序,可能共用一个NAT的IP:port对。

7、RTP的问题
在RTP的消息正文内,有UA能够成功通信所需要的一些信息。这种消息正文,就叫做SDP消息。

问题在于,SIP终端(UA)可能对NAT一无所知。因而在SDP中包含的IP地址,通常使用内部的IP地址,也就是SIP终端知道的IP。这样, 当通信的对方想与SIP终端通信时,就查看SDP消息中的IP地址,但是什么也没有得到,因为这里使用的是内部IP地址。

下面举个例子说明:

INVITE sip:040600@192.168.20.2:5060 SIP/2.0.
Record-Route: <sip:143.248.130.35;ftag=3a7ceb24a6ac50c4;lr=on>.
Via: SIP/2.0/UDP 143.248.130.35;branch=z9hG4bK758e.976609c7.0.
Via: SIP/2.0/UDP
192.168.20.3;rport=1024;received=223.178.140.109;branch=z9hG4bK34efcab2403aa20d.
From: "Iqbal" <sip:040618@sip.dom.com>;tag=3a7ceb24a6ac50c4.
To: <sip:040600@sip.dom.com>.
Contact: <sip:040618@223.178.140.109:1024>.
Supported: replaces.
Call-ID: 7f2c327896a5b0e1@192.168.20.3.
CSeq: 8717 INVITE.
User-Agent: Grandstream HT487 1.0.5.18.
Max-Forwards: 16.
Allow: IN
VITE,ACK,CANCEL,BYE,NOTIFY,REFER,OPTIONS,INFO,SUBSCRIBE.
Content-Type: application/sdp.
Content-Length: 343.
.
v=0.
o=040618 8000 1 IN IP4 192.168.20.3.
s=SIP Call.
c=IN IP4 192.168.20.3.
t=0 0.
m=audio 38660 RTP/AVP 0 8 4 18 2 15 99.
a=sendrecv.
a=rtpmap:0 PCMU/8000/3.
a=rtpmap:8 PCMA/8000/3.

SIP消息的标题头,类似于邮件的标题头。从后往前看,从From行开始,看到第一个Via行,这是SIP终端自己认为的IP地址,例如 192.168.20.3。但是SIP代理服务器是聪明的,它知道这个消息是从哪里发过来的,它添加了rport和接收到的标志:
Via: SIP/2.0/UDP
192.168.20.3;rport=1024;received=223.178.140.109;branch=z9hG4bK34efcab2403aa20d.

也就是说,SIP代理服务器,知道发消息的SIP终端的公网地址是223.178.140.109:1024。
这样,SIP代理服务器是可 以与SIP终端通信的,因为它知道SIP终端的公网地址。

但是,可怜的老式的RTP被阻塞了,因为它的标题头如下:
v=0.
o=040618 8000 1 IN IP4 192.168.20.3.
s=SIP Call.
c=IN IP4 192.168.20.3.
t=0 0.
m=audio 38660 RTP/AVP 0 8 4 18 2 15 99.
a=sendrecv.
a=rtpmap:0 PCMU/8000/3.
a=rtpmap:8 PCMA/8000/3.

SIP终端期望从端口 port m=38660 且IP地址IP c= 192.168.20.3来接收RTP数据,而这个192.168.20.3:38660,就是通信的对方试图发RTP数据的目的地址。

这就是SIP电话振铃总是能够听到,而接起来却没有声音的原因。

8 解决办法 告诉SIP终端,不要如此傻地工作,而要想办法知道NAT分配给自己的端口映射。

并将公网的IP地址:端口放到SDP消息中。这样,SIP终端就问NAT….。或者是问公网的某个服务器,NAT分配给自己的映射是什么。

9 问NAT。 这种办法就是使用UPnP协议,另外去参见UPnP的资料。

10 问公网上的某个服务器。 如STUN服务器。
SIP终端发送一个探测数据包,到公网上的服务器。公网上的服务器会发回数据包,会包含 有关NAT的详细信息。有了这些信息,SIP终端就会知道它是否在NAT后面。这种探测方法,可以用于上面4种NAT,都有效。例如SIP终端从 10.1.1.1:1000发送一个数据包,则SDP消息中包含的是m=1000 and c=10.1.1.1。但是,如果SIP终端先进行NAT探测,则会知道NAT会分配公网的IP:端口是212.134.123.23:12345。则 SIP终端直接在SDP消息写m=12345,c=212.134.123.23。

产生的问题 因为NAT的端口分配是动态的,因而有可能会改变。这样,在发送了NAT探测消息后,要很快地发送出SIP消息。而且,SIP终端发送数据的端口和接收数 据的端口要是一样的。

注意受限制的圆锥体(包括端口受限制的圆锥体)NAT,它不让回来的消息进来,除非SIP终端先发了一个数据包给它。因而,SIP终端需要先发一个 数据包给对方。这样以后对方来的数据,就可以进入NAT内部了(不过,不需要为这个操作担心,有办法的)。

上面的办法在对称的NAT后面,不能够工作。因为,对称的NAT,它在分配给SIP终端外部的IP:port时,每次都变化(不同的对方不一样)。 也就是SIP终端在探测NAT时,得到的IP:port,与它后来发SIP消息时,分配的IP:port不一样。这样,对方来的语音数据就进不来,因为对 方得不到正确的IP:port。

11、上面描述的过程,其实就是采用STUN协议时,解决问题的过程。就是SIP终端向STUN服务器发探测NAT的数据包。

12、对称的NAT 解决办法 就是在公网上放一个中转语音流的服务器。这个中转语音流的服务器有时就是一个Out Bound proxy。注意,这个中转语音流的服务器,可能会成为瓶颈。由于语音要经过中转语音流的服务器,所以路径增长了,音质会变差。所以,对称的NAT,要 SIP能够工作,总之是个麻烦。

不过,目前大多数的NAT,都可以做“虚拟服务器的端口转发”,即将SIP工作需要的端口转发到SIP终端上去。如果在NAT设备上,做了“虚拟服 务器的端口转发”,则NAT会保留SIP工作需要的端口,专用于SIP终端,这样SIP终端就相当于是在一个Full Cone完全圆锥体的NAT后面,SIP用STUN工作没有问题。SIP终端需要的端口数是这样确定的,一个端口用于SIP信令,比如5060。RTP端 口的数量,取决于通话的路数。一路通话需要2个RTP端口。每增加一路通话,则需要多2个端口。
只支持一路通话的SIP话机,需要NAT映射3个 端口。
前面三种的NAT,可统称为非对称的NAT。非对称的NAT,都可以用STUN协议穿过NAT

将对称的NAT,通过端口转发的方式,变为完全圆锥体的NAT,是解决NAT问题的最好办法。首先应当用这种办法来解决。没有办法映射端口,再想其 它的办法。当然,建议大家不要买那种不能够映射端口的宽带路由器,那样的路由器太差了。

===================================================================================

2. 案例

2.1. asterisk作为服务器,在nat之外,voip电话在nat之内。

      2.1.1. 呼叫来自nat后面的电话终端,asterisk把媒体发到私网ip

  

如果voip电话没有使用stun或其他机制来获取它的公网地址(并把公网地址写入invite消息),asterisk就把媒体发到私网地址,被路由器丢弃导致单通。

这种情况发生在sip.conf中主叫用户配置了nat=never,或nat=no,或nat=rfc3581。与nat的类型无关。

那就只有nat=route可以了,即主叫发送媒体到asterisk后,asterisk再按原路返回rtp.(asterisk如何获得rtp的路由?)

    2.1.2. 呼叫来自nat后面的电话,asterisk发送媒体到错误端口


voip电话能检测到自己的公网ip并写入invite头,asterisk知道rtp的ip地址。

如果nat类型是Cone(full cone,restricted cone),nat转发rtp到asterisk的端口不是原来voip电话的媒体端口,asterisk按照原端口发送rtp。这时nat就不知道把从asterisk收到的rtp包转给谁(cone是内网ip:port对应外网ip:port,一一对应)。

 nat=route或nat=yes可以解决这个问题。

 如果只有一个电话在nat后面,可以做端口映射,把该电话使用的rtp端口都做内外网映射。

如果有多个电话在nat后面,则可以把rtp端口范围不重叠的分派给每个电话,然后分别做端口映射。(?)

 

使用symmetric nat或stun服务器也可以解决这个问题


HQY
« 上一篇 下一篇 »

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。