http://www.cnblogs.com/whyandinside/archive/2010/12/08/1900492.html
http://www.gzsec.com/oldversion/filesys/news_view.asp?newsid=84
在現實Internet網絡環境中,大多數計算機主機都位於防火牆或NAT之后,只有少部分主機能夠直接接入Internet。很多時候,我們希望網絡中的兩台主機能夠直接進行通信,即所謂的P2P通信,而不需要其他公共服務器的中轉。由於主機可能位於防火牆或NAT之后,在進行P2P通信之前,我們需要進行檢測以確認它們之間能否進行P2P通信以及如何通信。這種技術通常稱為NAT穿透(NAT Traversal)。最常見的NAT穿透是基於UDP的技術,如RFC3489中定義的STUN協議。
STUN,首先在RFC3489中定義,作為一個完整的NAT穿透解決方案,英文全稱是Simple Traversal of UDP Through NATs,即簡單的用UDP穿透NAT。
在新的RFC5389修訂中把STUN協議定位於為穿透NAT提供工具,而不是一個完整的解決方案,英文全稱是Session Traversal Utilities for NAT,即NAT會話穿透效用。RFC5389與RFC3489除了名稱變化外,最大的區別是支持TCP穿透。
TURN,首先在RFC5766中定義,英文全稱是Traversal Using Relays around NAT:Relay Extensions to Session Traversal Utilities for NAT,即使用中繼穿透NAT:STUN的擴展。簡單的說,TURN與STUN的共同點都是通過修改應用層中的私網地址達到NAT穿透的效果,異同點是TURN是通過兩方通訊的“中間人”方式實現穿透。
NAT(Network Address Translation,網絡地址轉換)的原理
NAT網絡包含一個 NAT管理設備及該管理設備后面的網絡節點。
NAT網絡怎么能夠節約公網IP地址呢?這是因為它能夠讓由私有IP構成的局域網內所有的計算機通過一台具有公網IP和NAT功能的計算機進入公網(Internet),比如上網沖浪,這樣一個局域網就只需要一個或很少幾個公網IP就行了,從而達到了節約公網IP地址的目的。也許你要問了,為什么需要NAT呢?局域網的私有IP計算機不是能夠通過網關直接進入公網嗎?非也,內網IP的數據包根本就不可能在公網上傳播,因為公網上的路由器都是屏蔽掉了這些私網IP的,這是因為私有IP本來就是人為保留出來專供私有網絡通信用的(RFC 1597中描述)。從另一個角度說,即使私有數據包能夠到達公網目標地址,目標地址的響應包也不可能返回真正的源地址,因為源地址是私有IP,目標發送的響應包一種可能是被目標地址所在的擁有相同網絡號的內網接收,一種可能就是這種子網不存在,數據包被拋棄。所以內網數據包在進入公網之前,必須被翻譯成公網IP,這就是NAT網絡的功能,而且NAT技術發展到現在,已不僅局限於翻譯IP地址,現在實際翻譯時,它不光翻譯IP地址,還會翻譯TCP/UDP端口。由於這個功能,NAT通常都位於網關計算機上,起着一種路由器的作用,為了講述方便,以后我們就稱這台網關計算機為NAT管理設備。下面就來看看NAT翻譯的基本過程(假如局域網192.168.0.0的NAT設備公網IP是218.70.201.185,私有IP是192.168.0.1,現在客戶機192.168.0.88要通過NAT管理設備訪問cn.yahoo.com的網頁,cn.yahoo.com的IP是202.43.216.55)。
當客戶機192.168.0.88通過IE向 http://cn.yahoo.com發出請求時,它發出的數據包含有下面的信息:
源地址和源端口:192.168.0.88:1234
目標地址和目標端口:202.43.216.55:80
當這個數據包到達NAT管理設備時,它會檢測到這個數據包是要發向公網的,所以它會對源IP地址和端口進行修改(翻譯),並在映射表中新建IP和端口的映射條目,然后再把修改的數據包轉發出去,下面就是修改后數據包的相關信息。
源:218.70.201.185:8999
目標:202.43.216.55:80 (無需變)
當cn..yahoo.com響應時,它會把數據包發給NAT管理設備,它的數據包含有下面的信息,
源:202.43.216.55:80
目:218.70.201.185:8999
當NAT管理設備收到響應時,它會檢查它的IP地址/端口映射表,並且會找到218.70.201.185:8999與192.168.0.88:1234的映射條目,於是它又修改數據包,然后把數據包轉發給192.168.0.88。相關數據包信息如下:
源:202.43.216.55:80
目:192.168.0.88:1234
具體的翻譯步驟就如圖1所示,其中圖1黑線左側是內網發向公網的翻譯過程,右側則是公網發向內網的翻譯過程,從中可以看出,翻譯過程也是從上層向下層進行的。
從上面可以看出,最開始發起連接的內網計算機(這里是192.168.0.88)對網關進行NAT翻譯是一無所知的,它根本就不知道網關對它的數據包“做了手腳”,上面所講的可以說是最理想的翻譯,這種翻譯對IP地址和端口信息只存在於IP首部和TCP/UDP首部的數據包是非常適合的,但恰恰這個世界是復雜的,網絡世界也不例外,每種技術都會有它的缺陷,下面就來看看NAT所面臨的網絡連接問題。
NAT有4種不同的類型
1) Full Cone
這種NAT網絡內部的機器A連接過外網機器C后,NAT會打開一個端口.然后外網的任何發到這個打開的端口的UDP數據報都可以到達A.不管是不是C發過來的.
例如 A:192.168.8.100 NAT:202.100.100.100 C:292.88.88.88
A(192.168.8.100:5000) -> NAT(202.100.100.100:8000) -> C(292.88.88.88:2000)
任何發送到 NAT管理設備(202.100.100.100:8000)的數據都可以到達A(192.168.8.100:5000)
2) Address Restricted Cone
這種NAT網絡內部的機器A連接過外網的機器C后,NAT打開一個端口.然后C可以用任何端口和A通信.其他的外網機器不行.
例如 A:192.168.8.100 NAT:202.100.100.100 C:292.88.88.88
A(192.168.8.100:5000) -> NAT(202.100.100.100 : 8000) -> C(292.88.88.88:2000)
任何從C發送到 NAT管理設備(202.100.100.100:8000)的數據都可以到達A(192.168.8.100:5000)
3) Port Restricted Cone
這種NAT網絡內部的機器A連接過外網的機器C后,NAT打開一個端口.然后C可以用原來的端口和A通信.其他的外網機器不行.
例如 A:192.168.8.100 NAT:202.100.100.100 C:292.88.88.88
A(192.168.8.100:5000) -> NAT(202.100.100.100 : 8000) -> C(292.88.88.88:2000)
C(202.88.88.88:2000)發送到 NAT管理設備(202.100.100.100:8000)的數據都可以到達A(192.168.8.100:5000)
以上三種NAT通稱Cone NAT(圓錐形NAT).我們只能用這種NAT進行UDP打洞.
4) Symmetric(對稱形)
對於這種NAT。連接不同的外部Server,NAT管理設備打開的端口會變化。也就是內部機器A連接外網機器B時,NAT管理設備會打開一個端口,連接外網機器C時又會打開另外一個端口。
對於雙方都是Port Restricted Cone NAT的時候,則需要利用UDP打洞原理進行“先打洞,然后才能直接通信”。
對 於Cone NAT.要采用UDP打洞.需要一個公網機器server C來充當”介紹人”.處於NAT之后的內網的A,B先分別和C通信,打開各自的NAT端口.C這個時候知道A,B的公網IP: Port. 現在A和B想直接連接.比如A給B直接發包,除非B是Full Cone,否則不能通信.反之亦然.
為什么啊?因為對於處於NAT管理設備之后的A,B。 如果想A要與外界的D通信,則首先必須要A發包到D,然后A經過NAT管理設備NA,NA把A的內網地址和端口轉換為NA的外網地址和端口。和D通信之后,D 才能經過NA和A通信。也就是說,只能A和外界主動通信,外界不能主動和處於NA之后的A通信。這種包會被NA直接丟棄的。這也就是上面所說的Port Restricted Cone 的情形啊! A(192.168.8.100:5000) -> NA(202.100.100.100:8000) -> D(292.88.88.88:2000)但是我們可以這樣.
A --- NA --- Server C --- NB --- B
- A,B 為主機;
- NA, NB 為NAT設備;
- Server C為外網的機器;
- 如果A想與B通信;
- A首先連接 C, C得到A的外網NA的地址和端口;
- B也要連接C,C得到B的外網NB的地址和端口;
- A告訴C說我要和B通訊;
- C通過NB發信息給B,告訴B A的外網NA的地址和端口;
- B向NA發數據包(肯定會被NA丟棄,因為NA上並沒有 A->NB 的合法session),但是NB上就建立了有B->NA的合法session了;
- B發數據包給C,讓 C 通知 A,我已經把洞打好了;
- A接受到通知后向 B 的外網發NB數據包,這樣就不會被丟棄掉了。因為對於NB來說,它看到的是A的外網NA的地址,而通過第6步,B已經讓NA成為NB的合法通信對象了。所以當NA發數據包給NB時,NB就會接收並轉發給B;
- B給A發數據反過來走一遍就可以了。
注意: 路由器和防火牆的UDP打洞的端口有個時間限制的,在一定時間內如果沒有數據通訊會自動關閉
STUN
STUN 的全稱是Simple Traversal of UDP Through NAT,即UDP對NAT的簡單穿越方式。應用程序(即STUN CLIENT)向NAT外的STUN SERVER通過UDP發送請求STUN 消息詢問自身的轉換后地址,STUN SERVER收到請求消息,產生響應消息,響應消息中攜帶請求消息的源端口,即STUN CLIENT在NAT上對應的外部端口。然后響應消息通過NAT發送給STUN CLIENT,STUN CLIENT通過響應消息體中的內容得知其在NAT上對應的外部地址,並且將其填入以后呼叫協議的UDP負載中,告知對端,同時還可以在終端注冊時直接注 冊這個轉換后的公有IP地址,這樣就解決了H.323/MGCP/SIP穿越NAT的通信建立問題以及作為被叫時的問題。本端的接收地址和端口號為NAT 外的地址和端口號。由於通過STUN協議已在NAT上預先建立媒體流的NAT映射表項,故媒體流可順利穿越NAT。
需要注意的是,NAT/PAT 對於地址轉換關系是有一定生命期的,某個地址轉換后在一段時間內沒有被使用將會被清除,當這個業務流再次出現時,將會建立一個新的地址轉換關系,這就意味 着STUN的詢問過程以及終端的注冊過程都需要再執行一遍才能保證通信的正確。解決這個問題一個比較通行的方案是采用某種方式保持NAT/PAT的轉換關 系,例如在NAT/PAT生命期內重復注冊一次,比如NAT/PAT的生命期是3分鍾,那么就將注冊重復周期設置為2分鍾。
另外STUN server並非指一個專用的服務器,而是指一種功能、一個協議,我們可以在softswitch或者任何一個需要此功能的服務器上內置此協議, 后面代碼也包含一個簡單的Server實現。
但 是在NAT采用對稱模式(symmetric NAT)工作時,STUN的方案就會出現問題。假如我們在softswitch上提供STUN server功能,終端A通過STUN可以獲得NAT為終端A與softswitch之間通信分配的地址A',並將這個地址注冊在softswitch 上,當一個公網上的終端B呼叫終端A時,A'和B通過softswitch完成呼叫建立過程。當B試圖向A'發送媒體流時,問題就出現了。因為對稱NAT 只允許從softswitch發送數據給地址A',從B發送的媒體流將被丟棄。所以STUN無法應用於工作在對稱模式的NAT.
STUN協議最大的優點是無需現有NAT/FW設備做任何改動,同時STUN方式可在多個NAT串聯的網絡環境中使用. STUN的局限性在於STUN並不適合支持TCP連接的穿越,同時STUN方式不支持對對稱NAT(Symmetric NAT).
TURN
這 種方式又稱SPAN(Simple Protocol for Augmenting NATs)方式. TURN方式解決NAT問題的思路與STUN相似,也是基於私網接入用戶通過某種機制預先得到其私有地址對應在公網的地址(STUN方式得到的地址為出口 NAT上的地址,TURN方式得到地址為TURNServer上的地址),然后在報文負載中所描述的地址信息直接填寫該公網地址的方式,實際應用原理也是 一樣的。
TURN的全稱為Traversal Using RelayNAT,即通過Relay方式穿越NAT,TURN應用模型通過分配TURNServer的地址和端口作為客戶端對外的接受地址和端口,即私網 用戶發出的報文都要經過TURNServer進行Relay轉發,這種方式除了具有STUN方式的優點外,還解決了STUN應用無法穿透對稱 NAT(Symmetric NAT)以及類似的Firewall設備的缺陷,即無論企業網/駐地網出口為哪種類型的NAT/FW,都可以實現NAT的穿透,同時TURN支持基於 TCP的應用,如H323協議。TURN的局限性在於所有報文都必須經過TURNServer轉發,增大了包的延遲和丟包的可能性.
ICE
ICE跟STUN和TURN不一樣,ICE不是一種協議,而是一個framework,它整合了STUN和TURN。
UPnP
UPnP是若干網絡協議的組合,主要用於設備的互聯,但是一種叫做Internet Gateway Device (IGD) Protocol的防火牆穿越技術是基於UPnP的。
http://blog.chinaunix.net/uid-11572501-id-2868684.html
STUN簡介 STUN(Simple Traversal of UDP over NATs,NAT 的UDP簡單穿越)是一種網絡協議,它允許位於NAT(或多重NAT)后的客戶端找出自己的公網地址,查出自己位於哪種類型的NAT網絡之后以及NAT管理設備為某一個本地端口所綁定的Internet端端口。這些信息被用來在兩個同時處於NAT路由器之后的主機之間建立UDP通信。該協議由RFC 3489定義。
一旦客戶端得知了Internet端的UDP端口,通信就可以開始了。
SIP之類的協議是使用UDP分組在Internet上傳輸音頻和/或視頻數據的。不幸的是,由於通信的兩個末端往往位於NAT管理設備之后,因此用傳統的方法是無法建立連接的。這也就是STUN發揮作用的地方。
STUN是一個客戶機-服務器協議。一個VoIP電話或軟件包可能會包括一個STUN客戶端。這個客戶端會向STUN服務器發送請求,之后,服務器就會向STUN客戶端報告NAT路由器的公網IP地址以及NAT為允許傳入流量傳回內網而開通的端口。
以上的響應同時還使得STUN客戶端能夠確定正在使用的NAT類型——因為不同的NAT類型處理傳入的UDP分組的方式是不同的。四種主要類型中有三種是可以使用的:完全圓錐型NAT、受限圓錐型NAT和端口受限圓錐型NAT——但大型公司網絡中經常采用的對稱型NAT(又稱為雙向NAT)則不能使用。
NAT工作原理:NAT主要的通過對數據包頭的地址替換來完成內網計算機訪問外網服務的。當內部機器要訪問外部網絡時,NAT管理設備把內部的IP1與端口號1(網絡層地址與傳輸層地址),轉換成NAT的外部IP2與新的端口號2,再送給外部網絡,數據返回時,再把目的為IP2:端口2的數據包替換為IP1:端口 1,送給內網機器。若通訊協議的內容中有IP地址的傳遞,如FTP協議,NAT管理設備在翻譯時還要注意數據包內涉及協議地址交互的地方也要替換,否則協議就會出現地址混亂。在NAT管理設備中維護了這個要替換地址的映射表,並根據內部計算機的通訊需求維護該表。外部網絡來數據包能否進入NAT,主要是看是否已經有可映射的表項,若沒有就會丟棄
NAT給P2P帶來的問題是:NAT只允許單方面發起連接,通訊的雙方不是平等的,P2P網絡的基礎有了問題,具體的表現為:
- 內網主機IP是私有的,外部主機看不到,也無法主動發起連接
- 即使知道了內網IP,但NAT管理設備會丟棄沒有在影射表的數據包
- 內網主機可以作為客戶端訪問外網,但不能作為服務器提供服務
- 當兩個主機都位於各自的NAT管理設備之后,要實現P2P的連接,就不僅是誰主動的問題,而是如何解決在兩個NAT管理設備上同時有對方映射表項的問題。
STUN標准中,根據內部終端的地址(P:p)到NAT出口的公網地址(A:b)的影射方式,把NAT分為四種類型:
1. Full Cone:來自相同的內部地址的請求消息映射為相同的外部地址,與外部地址(目的地址)無關。映射關系為P:p↔A:b,任何外部主機可通過(A:b)發送到數據到(P:p)上。
2. Restricted Cone:來自相同的內部地址的請求消息映射為相同的外部地址,返回的數據只接受該內部節點曾發數據的那個目的計算機地址X。映射關系為P:p↔A:b↔X,只有來自X的數據包才可通過(A:b)發送到數據到(P:p)上。
3. Port Restricted Cone:來自相同的內部地址的請求消息映射為相同的外部地址,返回的數據只接受該內部節點曾發數據的那個目的地址X:x。映射關系為 P:p↔A:b↔X:x,只有來自X:x的數據包才可通過(A:b)發送到數據到(P:p)上。
4. Symmetric(對稱) NAT:只有來自相同的內部地址(P:p),並且發送到同一個地址(X:x) 的請求消息,才被映射為相同的外部地址(A:b),返回的數據只接受該內部節點曾發數據的那個目的地址X:x。映射關系為P:p↔A:b↔X:x,當 (P:p)訪問(Y:y)時,映射為P:p↔B:c↔Y:y。
P2P利用STUN穿越NAT:
位於NAT后面終端A與B要穿越NAT直接通訊,可以借助在公網上的第三者Server來幫助。
穿越NAT的情況分為為兩種方式:
1、一方在NAT管理設備之后,一方在公網上。這種情況相對簡單,只要讓NAT管理設備之后的終端先發起通訊,NAT管理設備就沒有作用了,它可以從Server上取得另一個Peer的地址,主動連接,回來的數據包就可以方便地穿越NAT。
2、雙方都在NAT管理設備之后,連接的成功與否與兩個NAT網絡的類型有關。
主要的思路的先通過終端與Server的連接,獲得兩個終端在NAT管理設備的外部地址(IP與端口號),再由終端向對方的外部地址發邀請包,獲取自己與對方通訊的外部地址,俗稱為“打洞”。關鍵是獲取了NAT管理設備外部映射的地址,就可以發包直接溝通,建立連接。但當一方是對稱型,另一方是Port Restricted或對稱型時,無法有效獲取外部地址,邀請包無法到達對方,也就無法穿越NAT。具體的分析可以根據兩個NAT網絡的類型分成若干情況分析,這里給一般的穿越例子。
實例:UDP穿越NAT管理設備:
A登錄Server,NAT管理設備A 分配端口11000,Server得到A的地址為100.10.10.10:11000 (實際上是NAT管理設備A的地址和端口)
B登錄Server,NAT管理設備B 分配端口22000,Server得到B的地址為200.20.20.20:22000
此時B會把直接來自A的包丟棄(A也會直接把來自B的包丟棄),所以要在NAT管理設備B 上打一個方向為A的洞,那么A就可以向200.20.20.20:22000發送數據了
打洞的指令來自Server。即Server告訴B向A的地址100.10.10.10:11000發一個UDP報文,被NAT管理設備A 丟棄,但在NAT管理設備B上建立了映射記錄,NAT管理設備B不在丟棄來自A的報文。
Server通知A立即與B進行通訊,A發起數據UDP包給B,NAT管理設備B放行,B收到A的包,雙方開始通訊
注:若是對稱NAT網絡,當B向A打洞的端口要重新分配(NAT A不會再分配11000端口),B無法獲取這個端口,所以不適用本方法。
實例:TCP穿越NAT:
tcp打洞與udp打洞的區別:tcp在傳輸數據前要connect,connect 過程中兩方要通信
A登錄Server,NAT管理設備A 分配端口11000,Server得到A的地址為100.10.10.10:11000
B登錄Server,NAT管理設備B 分配端口22000,Server得到B的地址為200.20.20.20:22000
Server告訴A向B發送TCP數據包 SYN:192.168.10.11:1234 => 200.20.20.20:22000,在NAT管理設備A上打洞
Server再告訴B向A發送TCP數據包 SYN:192.168.20.22:1234 => 100.10.10.10:11000,在NAT管理設備B上打洞
通道建立,A與B三次握手建立TCP連接
TCP(傳輸控制協議)和UDP(用戶數據報協議是網絡體系結構TCP/IP模型中傳輸層一層中的兩個不同的通信協議。
TCP:傳輸控制協議,一種面向連接的協議,給用戶進程提供可靠的全雙工的字節流,TCP套接口是字節流套接口(stream socket)的一種。
UDP:用戶數據報協議。UDP是一種無連接協議。UDP套接口是數據報套接口(datagram socket)的一種。