1. 程式人生 > >[轉]SIP穿越NAT&FireWall解決方案

[轉]SIP穿越NAT&FireWall解決方案

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

1. 包的地址轉換。
2. SIP訊息裡面的SIP地址轉換。
3. SIP訊息裡面的SDP中的RTP地址轉換。

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

NAT和Firewall的基本原理

首先,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}通訊。
Partial和Restricted Cone的區別是Partial只繫結incoming packet 的IP地址,而Restricted Cone會繫結incoming packet的IP地址和埠。也就是上面描述的那種情況。

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的基本策略:
Firewall會判斷所有的包是來自內部(Inside)還是外部(Outside)。

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

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

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

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

所有NAT和Firewall都是對於TCP/IP層以下進行處理和過濾的,而SIP應用的地址是在應用層。所以必須採用其他的途徑來解決這一問題。
針對不同的NAT型別,可以有不同的解決方案。
1. UPnP
2. External Query
3. STUN
4. ALG
其中前3種都是由SIP Client(包括UA和Proxy)通過某種手段或協議在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要進行通訊,Ada和Bob,他們分別位於自己的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 Server,NAT將其私有地址轉換成公網地址,並繫結,由於是採用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 Proxy的3002埠收到包,它可以從包地址獲得Ada的RTP公網IP。
當RTP Proxy的3000埠收到包,它可以從包地址獲得Bob的RTP公網IP。
從而,RTP Proxy會將3002埠收到的包轉發到Bob的RTP公網IP。
同樣,RTP Proxy會將3000埠收到的包轉發到Ada的RTP公網IP。

這樣,一個通話的連線就成功建立。
SIP ALG的部署因為無論如何,都需要所有RTP包經過RTP Proxy,所以所有的MS都要有修改SDP的能力,而只有SIP ALG需要有修改SIP訊息的能力。讓使用者配置自己的Proxy是什麼,避免公網的SIP Client也經過SIP ALG,造成沒必要的消耗。
補充如果SIP ALG發現INVITE包的地址和SIP地址是一致的話,它將不對這個包進行修改,它認為這個包是來自公網,或者SIP Client具備了穿越NAT的能力。但它會修改其SDP的IP地址。
ISSUE:

1.       如果SDP描述的是單工工作的話,RTP連線無法建立,因為RTP proxy始終無法知道沉默方的RTP公網IP。
2.       每次建立RTP連線,某一方的RTP包可能會丟掉若干個,直到RTP proxy獲知另一方的RTP公網IP。
3.       是否應該強制任何RTP包都要經過RTP Proxy,無論它們都是來自公網,可以直接連線。我想是的,因為主叫方是不知道被叫方的網路環境的。
4.       如果多個RTP Proxy進行均衡,如何保證為主叫方分配IP的Proxy和為被叫方分配IP的Proxy是一致的呢?(它們必須是同一臺Proxy)
可以增加一個header,比如RTP proxy,這個header只有SIP ALG認識。
5.       如果SIP訊息加密,就無法修改其SIP的IP地址。