close

SIP穿越NAT&FireWall解決方案

What's going in the picture is the fact that Yate uses the RTP stream IP+port insted of the RTP ip+port declared in SDP in 200 OK. This small hack allows most of the sip clients when Yate is the server to pass the voice over NAT.



A better explanation can be found at: http://freshmeat.net/articles/view/2079/

NAT traversal for the SIP protocol
 by Diana Cionoiu, in Tutorials - Sun, Feb 19th 2006 00:00 PDT

NAT stands for Network Address Translation. It's the technology which allows most people to have more than one computer in their home and still use a single IP address. Most of the time, a router with NAT support gets data packets from the internal network (with internal IP addresses) and sends them to Internet, changing the internal IP address of each packet to the external one.


Copyright notice: All reader-contributed material on freshmeat.net is the property and responsibility of its author; for reprint rights, please contact the author directly.



What's RTP?

RTP stands for Real-Time Transport Protocol. Its purpose is to pass voice data between a caller and the called. The problem is that when you call someone using the RTP protocol, you need to know his IP address and port. This makes RTP quite inconvenient when used alone, since the parts have no way to find one another. This is why people invented SIP.

What's SIP?

SIP (Session Initiation Protocol) looks in syntax like HTTP, human readable text. Its purpose is to help the caller find the IP address and port of the called. It also helps the negotiation of the media types and formats. For example, when you have a PC at home and you want to call your friend from Romania using Free World Dialup (which uses the SIP protocol):

SIP sends an INVITE packet with the caller IP address and port for RTP to the FWD server, and from there, FWD forwards the call to the intended destination. The called accepts the call and sends his own IP address and port for RTP back.

SIP + NAT, an unsolvable problem?

The problem with SIP and NAT is not actually a SIP problem, but the RTP problem. SIP announces the RTP address and port, but if the client is behind NAT, it announces the client's RTP port, which can be different from the port the NAT allocates externally.

Even if a lot of SIP implementations and carriers are based on the fact that NAT will always try to allocate the same port, that assumption is false. In a production environment, you can't tell grandma that she can't talk with her grandson because some router has allocated another number.

If you are a carrier, the solution is simple because you proxy all the data, anyway. The solution is to use a SIP Session Border Controller. The SIP SBC normally stays in front of the internal SIP network of the carrier, solving the NAT traversal problem and protecting the SIP network.

The solution for NAT traversal in this case is to use some tricks.

The first trick is to keep open the hole in the NAT from the SIP client to the server. This is normally done by making all SIP clients use a two byte packet which is sent more often than 30 seconds. Some routers remove apparently unused NAT mappings after 30 seconds; GNU/Linux typically does this after three minutes.

The second trick is one we've used for our project YATE, to figure out the RTP IP and port from the first packet that arrives on the local RTP IP and port of the server, and to use it instead of using the RTP IP and address declared in SDP. This trick solves the NAT traversal problem, no matter how many NATs the client is traversing. However, the main disadvantage is that, in some cases, the client will not receive early media (since at that point, it sends out no voice packets) and it will not hear the ringing.

If you are not a carrier and you are trying to make a peer-to-peer call and both sides are behind the NAT, you must use an external SIP proxy or gateway to pass the SIP between the two points, hoping that the NATs will open the proper ports, one to another, for the RTP connection. However, there is no ultimate solution for that. Two proposed solutions are STUN and ICE, but every solution that currently exists can get in your way sometimes. Skype has found a very simple and nice solution for this problem: They use the Skype clients that are not behind NAT to proxy all the data for clients that are behind NAT.

This solution, technically speaking, is very good. However, there are some moral and political reasons not to use Skype. One of them is that if you are a Skype client outside the NAT, you don't know whose data is passing through your computer. Another is that it is using your bandwidth; after all, someone has to pay one way or another for Internet bandwidth necessary to proxy the voice stream.

My personal hope is that in the near future, most SIP implementations will use the two tricks used by YATE. Skype will probably be around for a long time for home users, but enterprise seems to move slowly to VoIP providers. With a lot of work and a little bit of luck, they will become at least as reliable as PSTN providers, since the technology is better.



SIP穿越NAT&FireWall解決方案

SIP從私網到公網會遇到什麼樣的問題呢?

包的地址轉換。

SIP消息裡面的SIP地址轉換。

SIP消息裡面的SDP中的RTP地址轉換。

 

網絡現存結構複雜, SIP服務提供商並不一定是NETWORK提供商,很難要求客戶只能使用某種方式的NAT&FireWall 。如何找出一種可以滿足各種網絡的SIP應用解決方案呢?

 

NATFirewall的基本原理

首先,NAT的幾種方式:

Full Cone當一台私網內的主機向公網發一個包,其本地地址和端口是{A:B}NAT會將其私有地址{A:B}轉換成公網地址{X:Y}並綁定。任何包都可以通過地址 {X:Y}送到該主機的{A:B}地址上,NAT會將任何發送到 {X:Y}incoming包的地址{X:Y}轉換成 {A:B}

 

Partial/Restricted Cone當一台私網內的主機向公網發一個包,其本地地址和斷口是{A:B}NAT會將其私有地址{A:B}轉換成公網地址{X:Y}並綁定。任何包都可以通過地址 {X:Y}送到該主機的{A:B}地址上,但是,NAT只為第一個發往 {X:Y}的包綁定成{A:B}|{X:Y}<->{C:D},其中{C:D} 是那個包的源地址和端口。也就是說,只有來自{C:D}的包才能於主機{A:B}通信。

PartialRestricted Cone的區別是Partial 只綁定incoming packet IP地址,而Restricted Cone 會綁定incoming packetIP地址和端口。也就是上面描述的那種情況。

 

Symmetric Cone當一台私網內的主機向公網某台主機發送一個包,{A:B} à{C:D} NAT會將其地址{A:B} 轉換成{X:Y},並為其綁定成 {A:B}|{X:Y}<->{C:D}NAT 只接受來自{C:D} incoming packet,將它轉給{A:B} 。也就是說,如果私網內的主機要向外面發送一個包,它必須要知道對方的公網IP和端口。但如果對方也是處於一個私網內,它就很難獲知對方的公網 IP和端口。 

 

由此可見, Symmetric Cone條件最嚴格,Partial/Restricted Cone次之,Full Cone 條件最不嚴格。

 

下面再看看Firewall的基本策略:

l  Firewall會判斷所有的包是來自內部(Inside)還是外部(Outside)

l 一般,允許所有來自inside的包發出去。

l 一般,允許來自Outside的包發進來,但這個連接必須是由Inside發起的。

l 一般,禁止所有連接由Outside發起的包發進來。

l 一般,firewall會允許幾個信任的outside主機,他們可以發起建立連接,併發包進來。

 

所有 NATFirewall都是對於TCP/IP層以下進行處理和過濾的,而 SIP應用的地址是在應用層。所以必須採用其他的途徑來解決這一問題。

針對不同的 NAT類型,可以有不同的解決方案。

l UPnP

l External Query

l STUN

l ALG

其中前3 種都是由SIP Client(包括UAProxy)通過某種手段或協議在 INVITE之前獲取自己的公網地址和端口。需要SIP Client提供額外支持,並且也不適應所有的NAT 方式。

ALG(Application Layer Gateway)適應所有NAT 方式,並不需要SIP Client做任何額外的支持。它對Application層的SIP 信令進行處理和修改,從而做到透明轉換地址。

下面針對一個案例詳細描述ALG的解決方案。

 

SIP ALG 解決方案


ALG 修改SIP消息裡面的SIP地址和端口和SDP消息裡面的RTP地址和端口,其中RTP地址和端口要向RTP Proxy請求獲得,RTP Proxy分配自己的一個空閒的地址和端口,並和這個Call保持映射關係。並為分配給呼叫雙方的地址和端口進行綁定,這樣,呼叫雙方的RTP連接地址都 是RTP Proxy,由RTP Proxy經過中轉,發至真正的目的地。

假設,有兩個SIP Client 要進行通信,AdaBob,他們分別位於自己的Nat Server 後面:

 

其中兩台 NAT Server都是Symmetric Cone方式。

其信令流程如下:

1. Ada發起信令,Invite Bob

IP Packet IP Address:

From: 192.168.1.10:5060

To: 128.97.41.56:5060 (SIP ALG)

SIP Msg IP Address:

From: 192.168.1.10:5060

To: 128.97.41.56:5060

SDP Body IP Address for RTP:

192.168.1.10:10024

 

2. 經過NAT ServerNAT將其私有地址轉換成公網地址,並綁定,由於是採用 Symmetric Cone方式,所以還綁定目的的IP地址。

{192.168.1.10:5060}|{128.96.41.1:5678}<->{128.97.41.56:5060}

IP Packet IP Address:

From: 128.96.41.1:5678

To: 128.97.41.56:5060 (SIP ALG)

SIP Msg IP Address:

From: 192.168.1.10:5060

To: 128.97.41.56:5060

SDP Body IP Address for RTP:

192.168.1.10:10024

 

3. SIP ALG接受到該INVITE,發現其包的IP 地址和SIP IP地址不同,就判斷其是經過NAT,於是就將其相關的SIP IP 地址修改。

並檢查它的Body中是否是包含 SDP信息,如果是,且有RTP地址,SIP ALG就會去向 RTP Proxy請求一個公網RTP地址來代替原有的RTP地址。

IP Packet IP Address:

From: 128.97.41.56:5060

To: 128.96.63.25:5566

SIP Msg IP Address:

From: 128.96.41.1:5678

To: 128.96.63.25:5566(下一跳的地址) 

SDP Body IP Address for RTP:

128.97.44.5:3000

 

4. 因為Bob不斷的向SIP ALG發送註冊包,所以,它的 NAT Server始終為它保留著這麼個綁定,{10.0.0.12:5060}|{128.96.63.25:5566}<->{ 128.97.41.56:5060}。所以,由SIP ALG發出的INVITE Bob能收到。

Bob返回 200 OK,包含SDP信息。

IP Packet IP Address:

From: 10.0.0.12:5060

To: 128.97.41.56:5060

SIP Msg IP Address:

From: 10.0.0.12:5060

To: 128.97.41.56:5060(下一跳的地址)

SDP Body IP Address for RTP:

10.0.0.12:10002

 

5. NAT Server將其包的IP地址修改。發往SIP ALG

 

6.  SIP ALG接受到該200 OK,發現其包的IP地址和 SIP IP地址不同,就判斷其是經過NAT,於是就將其相關的SIP IP地址修改。

並檢查它的Body中是否是包含SDP 信息,如果是,且有RTP地址,SIP ALG就會去向RTP Proxy 請求一個公網RTP地址來代替原有的RTP地址。

IP Packet IP Address:

From: 128.96.63.25:5566

To: 128.96.41.1:5678

SIP Msg IP Address:

From: 128.96.63.25:5566

To: 128.96.41.1:5678(下一跳的地址)

SDP Body IP Address for RTP:

128.97.44.5:3002

 

7. 此時,RTP Proxy為這個Session保持著這麼個連接綁定

{128.97.44.5:3000|128.97.44.5:3002}

 

8. Ada收到200 OK,它認為對方的RTP 地址是128.97.44.5:3002。將與其建立連接。

Bob認為對方的RTP地址是128.97.44.5:3000 。將與其建立連接。

 

9. RTP Proxy3002端口收到包,它可以從包地址獲得 AdaRTP公網IP

RTP Proxy3000端口收到包,它可以從包地址獲得 BobRTP公網IP

從而,RTP Proxy會將3002端口收到的包轉發到 BobRTP公網IP

同樣,RTP Proxy會將3000端口收到的包轉發到 AdaRTP公網IP

 

這樣,一個通話的連接就成功建立。

SIP ALG的部署

因為無論如何,都需要所有RTP包經過RTP Proxy ,所以所有的MS都要有修改SDP 的能力,而只有SIP ALG需要有修改SIP 消息的能力。讓用戶配置自己的Proxy是什麼,避免公網的 SIP Client也經過SIP ALG,造成沒必要的消耗。

補充

如果 SIP ALG發現INVITE包的地址和SIP 地址是一致的話,它將不對這個包進行修改,它認為這個包是來自公網,或者SIP Client具備了穿越 NAT的能力。但它會修改其SDPIP 地址。

ISSUE:

1. 如果SDP描述的是單工工作的話, RTP連接無法建立,因為RTP proxy始終無法知道沉默方的 RTP公網IP

2. 每次建立RTP連接,某一方的 RTP包可能會丟掉若干個,直到RTP proxy獲知另一方的 RTP公網IP

3. 是否應該強制任何RTP包都要經過 RTP Proxy,無論它們都是來自公網,可以直接連接。我想是的,因為主叫方是不知道被叫方的網絡環境的。

4. 如果多個RTP Proxy進行均衡,如何保證為主叫方分配 IPProxy和為被叫方分配IP Proxy是一致的呢?(它們必須是同一台Proxy

可以增加一個header ,比如RTP proxy,這個header 只有SIP ALG認識。

5. 如果SIP消息加密,就無法修改其 SIPIP地址。

 

 

參考

「SIP, NAT, and Firewalls」, Fredrik Thernelius, May 2000

「Cisco - VoIP Traversal of NAT and Firewall」,  Cisco Systems, Inc.


上篇文章著重講了穿越NAT的技術原理。現在主要講下如何部署。

 

我們知道STUN可以穿越除Symmetric 之外的其他三種類型的NATSymmetric 類型的NAT需要借助一個ALG 來解決。


雖然ALG 能夠解決所有類型的NAT問題,但是如果所有呼叫的媒體通信都需要通過 ALG來代理中轉的話,勢必給ALG帶來十分重的負擔,甚至影響語音通信的質量,照成延時或其他 QoS的問題。


所以提出一個問題,如何將 ALG的負擔減至最小。


可以將 NAT的類型分成SymmetricAsymmetric 兩大類。所以網絡通信會有以下幾種結構:


 caller               callee

Asymmetric  ßà  Asymmetric

Symmetric    ßà  Asymmetric

Asymmetric  ßà  Symmetric

Symmetric    ßà  Symmetric

 

第一種情況,通過STUN可以很容易解決。

 

第二三種情況,雖然 STUN解決不了,但是也可以通過非ALG的手段來解決。 Symmetric類型的NAT只能接收來自它請求的 IP地址和端口。比如ASymmetric 類型,B是非Symmetric 類型。B能在自己的SDP 裡面填寫正確的IP地址和端口(這裡說的正確是指能真正聯繫到BIP地址和端口),但是A不能,因為端口是當 A發第一個包至B時由 NAT Server動態分配一個端口。所以B必然不能通過 ASDP信息發包至 A,但當B收到來自A 發過來的RTP包時,它就可以從RTP 包的IP包頭中獲知A NAT ServerIP地址和端口。因此, B再重新修改它的Socket,將目標地址和端口該為來自 ARTP包的 IP包頭中的地址和端口。通過這樣,也能解決這一類型的通話問題。

 

也就是說,只有第四種情況是非得通過ALG 來解決的。

 

所以要根據通話雙方的NAT類型來選擇是否要經過ALG

但是如何獲知呼叫雙方的NAT 類型呢?

假設所有UA 都支持STUN,可以檢測出自己的NAT 類型。

發起方可以在INVITE 消息裡面加上個NAT-Type的頭域,指明自己是什麼類型的 NAT

然後,要求每個 SIP UA向自己的註冊服務器註冊時提供自己的NAT類型。

這樣,當INVITE抵達目標UA proxy時,就可以獲知雙方的NAT 類型,得出是屬於四種情況中的哪一種。

因此,由目標 UAproxy來決定是否需要經過 ALG來中轉。當目標 UAproxy收到個Incoming INVITE Message時,它判斷呼叫雙方的 NAT類型。當雙方NAT 類型都是屬於Symmetric時,則請求 ALG進行RTP中轉。屬於其他類型則忽略。

http://blog.csdn.net/images/blog_csdn_net/noiile/41845/r_SIPandALG.jpg

 

arrow
arrow
    全站熱搜

    Bluelove1968 發表在 痞客邦 留言(0) 人氣()