導(dǎo)語
最近介入測試P2P的相關(guān)邏輯,因此對NAT穿透原理做了一定程度的了解(當(dāng)然也沒有很深入)。。寫本文的目的就是,用自己的語言描述了這個過程,同時也在描述過程中加入了一些自己的理解,形成一篇文章作為要點的記錄。對于這一塊的知識,自己也有很多盲點,還請各路大神多多指教。
一、背景知識介紹
1.什么是NAT?
NAT(Network Address Translation,網(wǎng)絡(luò)地址轉(zhuǎn)換),也叫做網(wǎng)絡(luò)掩蔽或者IP掩蔽。NAT是一種網(wǎng)絡(luò)地址翻譯技術(shù),主要是將內(nèi)部的私有IP地址(private IP)轉(zhuǎn)換成可以在公網(wǎng)使用的公網(wǎng)IP(public IP)。
2.為什么會有NAT?
時光回到上個世紀(jì)80年代,當(dāng)時的人們在設(shè)計網(wǎng)絡(luò)地址的時候,覺得再怎么樣也不會有超過32bits位長即2的32次冪臺終端設(shè)備連入互聯(lián)網(wǎng),再加上增加ip的長度(即使是從4字節(jié)增到6字節(jié))對當(dāng)時設(shè)備的計算、存儲、傳輸成本也是相當(dāng)巨大的。后來逐漸發(fā)現(xiàn)IP地址不夠用了,然后就NAT就誕生了!(雖然ipv6也是解決辦法,但始終普及不開來,而且未來到底ipv6夠不夠用仍是未知)。
因此,NAT技術(shù)能夠興起的原因還是因為在我們國家公網(wǎng)IP地址太少了,不夠用,所以才會采取這種地址轉(zhuǎn)換的策略。可見,NAT的本質(zhì)就是讓一群機(jī)器公用同一個IP,這樣就暫時解決了IP短缺的問題。
3.NAT有什么優(yōu)缺點?
優(yōu)勢其實上面已經(jīng)剛剛討論過了,根據(jù)定義,比較容易看出,NAT可以同時讓多個計算機(jī)同時聯(lián)網(wǎng),并隱藏其內(nèi)網(wǎng)IP,因此也增加了內(nèi)網(wǎng)的網(wǎng)絡(luò)安全性;此外,NAT對來自外部的數(shù)據(jù)查看其NAT映射記錄,對沒有相應(yīng)記錄的數(shù)據(jù)包進(jìn)行拒絕,提高了網(wǎng)絡(luò)安全性。
那么,NAT與此同時也帶來一些弊端:首先是,NAT設(shè)備會對數(shù)據(jù)包進(jìn)行編輯修改,這樣就降低了發(fā)送數(shù)據(jù)的效率;此外,各種協(xié)議的應(yīng)用各有不同,有的協(xié)議是無法通過NAT的(不能通過NAT的協(xié)議還是蠻多的),這就需要通過穿透技術(shù)來解決。我們后面會重點討論穿透技術(shù)。
簡單的背景了解過后,下面介紹下NAT實現(xiàn)的主要方式,以及NAT都有哪些類型。
二、NAT實現(xiàn)方式及主要類型
1.NAT實現(xiàn)方式
1)靜態(tài)NAT:也就是靜態(tài)地址轉(zhuǎn)換。是指一個公網(wǎng)IP對應(yīng)一個私有IP,是一對一的轉(zhuǎn)換,同時注意,這里只進(jìn)行了IP轉(zhuǎn)換,而沒有進(jìn)行端口的轉(zhuǎn)換。舉個栗子:

2)NAPT:端口多路復(fù)用技術(shù)。與靜態(tài)NAT的差別是,NAPT不但要轉(zhuǎn)換IP地址,還要進(jìn)行傳輸層的端口轉(zhuǎn)換。具體的表現(xiàn)形式就是,對外只有一個公網(wǎng)IP,通過端口來區(qū)別不同私有IP主機(jī)的數(shù)據(jù)。再舉個栗子。

通過上面NAT實現(xiàn)方式的介紹,我們其實不難看出,現(xiàn)實環(huán)境中NAPT的應(yīng)用顯然是更廣泛的。因此下面就重點介紹下NAPT的主要類型有哪些。
2.NAT的主要類型
對于NAPT我們主要分為兩大類:錐型NAT和對稱型NAT。其中錐型NAT又分:完全錐型,受限錐型和端口受限錐型。概括的說:對稱型NAT是一個請求對應(yīng)一個端口;錐型NAT(非對稱NAT)是多個請求(外部發(fā)向內(nèi)部)對應(yīng)一個端口,只要源IP端口不變,無論發(fā)往的目的IP是否相同,在NAT上都映射為同一個端口,形象的看起來就像錐子一樣。下面分別介紹這四種類型及其差異。
1)完全錐型NAT(Full Cone NAT,后面簡稱FC)
特點:IP和端口都不受限。
表現(xiàn)形式:將來自內(nèi)部同一個IP地址同一個端口號(IP_IN_A : PORT_IN_A)的主機(jī)監(jiān)聽/請求,映射到公網(wǎng)IP某個端口(IP_OUT_B : PORT_OUT_B)的監(jiān)聽。任意外部IP地址與端口對其自己公網(wǎng)的IP這個映射后的端口訪問(IP_OUT_B : PORT_OUT_B),都將重新定位到內(nèi)部這個主機(jī)(IP_IN_A : PORT_IN_A)。該技術(shù)中,基于C/S架構(gòu)的應(yīng)用可以在任何一端發(fā)起連接。是不是很繞啊。再簡單一點的說,就是,只要客戶端,由內(nèi)到外建立一個映射(NatIP:NatPort -> A:P1)之后,其他IP的主機(jī)B或端口A:P2都可以使用這個洞給客戶端發(fā)送數(shù)據(jù)。見下圖(圖片來自網(wǎng)絡(luò))。

2)受限錐型NAT(Restricted Cone NAT)
特點:IP受限,端口不受限。
表現(xiàn)形式:與完全錐形NAT不同的是,在公網(wǎng)映射端口后,并不允許所有IP進(jìn)行對于該端口的訪問,要想通信必需內(nèi)部主機(jī)對某個外部IP主機(jī)發(fā)起過連接,然后這個外部IP主機(jī)就可以與該內(nèi)部主機(jī)通信了,但端口不做限制。舉個栗子。當(dāng)客戶端由內(nèi)到外建立映射(NatIP:NatPort –> A:P1),A機(jī)器可以使用他的其他端口(P2)主動連接客戶端,但B機(jī)器則不被允許。因為IP受限啦,但是端口隨便。見下圖(綠色是允許通信,紅色是禁止通信)。

3)端口受限型NAT(Port Restricted Cone NAT)
特點:IP和端口都受限。
表現(xiàn)形式:該技術(shù)與受限錐形NAT相比更為嚴(yán)格。除具有受限錐形NAT特性,對于回復(fù)主機(jī)的端口也有要求。也就是說:只有當(dāng)內(nèi)部主機(jī)曾經(jīng)發(fā)送過報文給外部主機(jī)(假設(shè)其IP地址為A且端口為P1)之后,外部主機(jī)才能以公網(wǎng)IP:PORT中的信息作為目標(biāo)地址和目標(biāo)端口,向內(nèi)部主機(jī)發(fā)送UDP報文,同時,其請求報文的IP必須是A,端口必須為P1(使用IP地址為A,端口為P2,或者IP地址為B,端口為P1都將通信失敗)。例子見下圖。這一要求進(jìn)一步強(qiáng)化了對外部報文請求來源的限制,從而較Restrictd Cone更具安全性。

4)對稱型NAT(Symmetric NAT)
特點:對每個外部主機(jī)或端口的會話都會映射為不同的端口(洞)。
表現(xiàn)形式:只有來自同一內(nèi)部IP:PORT、且針對同一目標(biāo)IP:PORT的請求才被NAT轉(zhuǎn)換至同一個公網(wǎng)(外部)IP:PORT,否則的話,NAT將為之分配一個新的外部(公網(wǎng))IP:PORT。并且,只有曾經(jīng)收到過內(nèi)部主機(jī)請求的外部主機(jī)才能向內(nèi)部主機(jī)發(fā)送數(shù)據(jù)包。內(nèi)部主機(jī)用同一IP與同一端口與外部多IP通信。客戶端想和服務(wù)器A(IP_A:PORT_A)建立連接,是通過NAT映射為NatIP:NatPortA來進(jìn)行的。而客戶端和服務(wù)器B(IP_B:PORT_B)建立連接,是通過NAT映射為NatIP:NatPortB來進(jìn)行的。即同一個客戶端和不同的目標(biāo)IP:PORT通信,經(jīng)過NAT映射后的公網(wǎng)IP:PORT是不同的。此時,如果B想要和客戶端通信,也只能通過NatIP:NatPortB(也就是紫色的洞洞)來進(jìn)行,而不能通過NatIP:NatPortA(也就是黃色的洞洞)。

以上,就是NAPT的四種NAT類型。可以看出由類型1)至類型4),NAT的限制是越來越大的。
三、NAT路由類型判斷
根據(jù)上面的介紹,我們可以了解到,在實際的網(wǎng)絡(luò)情況中,各個設(shè)備所處的網(wǎng)絡(luò)環(huán)境是不同的。那么,如果這些設(shè)備想要進(jìn)行通信,首先判斷出設(shè)備所處的網(wǎng)絡(luò)類型就是非常重要的一步。舉個例子來說:對于視頻會議和VoIP軟件,對位于不同NAT內(nèi)部的主機(jī)通信需要靠服務(wù)器來轉(zhuǎn)發(fā)完成,這樣就會增加服務(wù)器的負(fù)擔(dān)。為了解決這種問題,要盡量使位于不同NAT內(nèi)部的主機(jī)建立直接通信,其中,最重要的一點就是要判斷出NAT的類型,然后才能根據(jù)NAT的類型,設(shè)計出直接通信方案。不然的話,兩個都在NAT的終端怎么通信呢?我們不知道對方的內(nèi)網(wǎng)IP,即使把消息發(fā)到對方的網(wǎng)關(guān),然后呢?網(wǎng)關(guān)怎么知道這條消息給誰,而且誰允許網(wǎng)關(guān)這么做了?
為了解決這個問題,也就是處于內(nèi)網(wǎng)的主機(jī)之間能夠穿越它們之間的NAT建立直接通信,已經(jīng)提出了許多方法,STUN(Session Traversal Utilities for NAT,NAT會話穿越應(yīng)用程序)技術(shù)就是其中比較重要的一種解決方法,并得到了廣泛的應(yīng)用。在這個部分,我們將重點介紹下STUN技術(shù)的原理。(PS:除此之外,還有UPNP技術(shù),ALG應(yīng)用層網(wǎng)關(guān)識別技術(shù),SBC會話邊界控制,ICE交互式連接建立,TURN中繼NAT穿越技術(shù)等等,本文不一一做介紹。)
四、STUN協(xié)議
STUN是一種網(wǎng)絡(luò)協(xié)議,它允許位于NAT(或多重NAT)后的客戶端找出自己的公網(wǎng)地址,查出自己位于哪種類型的NAT之后以及NAT為某一個本地端口所綁定的Internet端端口。這些信息被用來在兩個同時處于NAT路由器之后的主機(jī)之間建立UDP通信。該協(xié)議由RFC 5389定義。STUN由三部分組成:STUN客戶端、STUN服務(wù)器端、NAT路由器。STUN服務(wù)端部署在一臺有著兩個公網(wǎng)IP的服務(wù)器上。大概的結(jié)構(gòu)參考下圖。STUN客戶端通過向服務(wù)器端發(fā)送不同的消息類型,根據(jù)服務(wù)器端不同的響應(yīng)來做出相應(yīng)的判斷,一旦客戶端得知了Internet端的UDP端口,通信就可以開始了。

STUN協(xié)議定義了三類測試過程來檢測NAT類型。
Test1:STUN Client通過端口{IP-C1:Port-C1}向STUN Server{IP-S1:Port-S1}發(fā)送一個Binding Request(沒有設(shè)置任何屬性)。STUN Server收到該請求后,通過端口{IP-S1:Port-S1}把它所看到的STUN Client的IP和端口{IP-M1,Port-M1}作為Binding Response的內(nèi)容回送給STUN Client。 Test1#2:STUN Client通過端口{IP-C1:Port-C1}向STUN Server{IP-S2:Port-S2}發(fā)送一個Binding Request(沒有設(shè)置任何屬性)。STUN Server收到該請求后,通過端口{IP-S2:Port-S2}把它所看到的STUN Client的IP和端口{IP-M1#2,Port-M1#2}作為Binding Response的內(nèi)容回送給STUN Client。
Test2:STUN Client通過端口{IP-C1:Port-C1}向STUN Server{IP-S1:Port-S1}發(fā)送一個Binding Request(設(shè)置了Change IP和Change Port屬性)。STUN Server收到該請求后,通過端口{IP-S2:Port-S2}把它所看到的STUN Client的IP和端口{IP-M2,Port-M2}作為Binding Response的內(nèi)容回送給STUN Client。
Test3:STUN Client通過端口{IP-C1:Port-C1}向STUN Server{IP-S1:Port-S1}發(fā)送一個Binding Request(設(shè)置了Change Port屬性)。STUN Server收到該請求后,通過端口{IP-S1:Port-S2}把它所看到的STUN Client的IP和端口{IP-M3,Port-M3}作為Binding Response的內(nèi)容回送給STUN Client。
STUN協(xié)議的輸出是: 1)公網(wǎng)IP和Port 2)防火墻是否設(shè)置 3)客戶端是否在NAT之后,及所處的NAT的類型
因此我們進(jìn)而整理出,通過STUN協(xié)議,我們可以檢測的類型一共有以下七種:
A:公開的互聯(lián)網(wǎng)IP。主機(jī)擁有公網(wǎng)IP,并且沒有防火墻,可自由與外部通信 B:完全錐形NAT。 C:受限制錐形NAT。 D:端口受限制形NAT。 E:對稱型UDP防火墻。主機(jī)出口處沒有NAT設(shè)備,但有防火墻,且防火墻規(guī)則如下:從主機(jī)UDP端口A發(fā)出的數(shù)據(jù)包保持源地址,但只有從之前該主機(jī)發(fā)出包的目的IP/PORT發(fā)出到該主機(jī)端口A的包才能通過防火墻。 F:對稱型NAT G:防火墻限制UDP通信。
輸入和輸出準(zhǔn)備好后,附上一張維基百科的流程圖,就可以描述STUN協(xié)議的判斷過程了。

STEP1:檢測客戶端是否有能力進(jìn)行UDP通信以及客戶端是否位于NAT后 -- Test1 客戶端建立UDP socket,然后用這個socket向服務(wù)器的(IP-1,Port-1)發(fā)送數(shù)據(jù)包要求服務(wù)器返回客戶端的IP和Port,客戶端發(fā)送請求后立即開始接受數(shù)據(jù)包。重復(fù)幾次。 a)如果每次都超時收不到服務(wù)器的響應(yīng),則說明客戶端無法進(jìn)行UDP通信,可能是:G防火墻阻止UDP通信 b)如果能收到回應(yīng),則把服務(wù)器返回的客戶端的(IP:PORT)同(Local IP: Local Port)比較: 如果完全相同則客戶端不在NAT后,這樣的客戶端是:A具有公網(wǎng)IP可以直接監(jiān)聽UDP端口接收數(shù)據(jù)進(jìn)行通信或者E。 否則客戶端在NAT后要做進(jìn)一步的NAT類型檢測(繼續(xù))。
STEP2:檢測客戶端防火墻類型 -- Test2 STUN客戶端向STUN服務(wù)器發(fā)送請求,要求服務(wù)器從其他IP和PORT向客戶端回復(fù)包: a)收不到服務(wù)器從其他IP地址的回復(fù),認(rèn)為包前被前置防火墻阻斷,網(wǎng)絡(luò)類型為E b)收到則認(rèn)為客戶端處在一個開放的網(wǎng)絡(luò)上,網(wǎng)絡(luò)類型為A
STEP3:檢測客戶端NAT是否是FULL CONE NAT -- Test2 客戶端建立UDP socket然后用這個socket向服務(wù)器的(IP-1,Port-1)發(fā)送數(shù)據(jù)包要求服務(wù)器用另一對(IP-2,Port-2)響應(yīng)客戶端的請求往回發(fā)一個數(shù)據(jù)包,客戶端發(fā)送請求后立即開始接受數(shù)據(jù)包。 重復(fù)這個過程若干次。 a)如果每次都超時,無法接受到服務(wù)器的回應(yīng),則說明客戶端的NAT不是一個Full Cone NAT,具體類型有待下一步檢測(繼續(xù))。 b)如果能夠接受到服務(wù)器從(IP-2,Port-2)返回的應(yīng)答UDP包,則說明客戶端是一個Full Cone NAT,這樣的客戶端能夠進(jìn)行UDP-P2P通信。
STEP4:檢測客戶端NAT是否是SYMMETRIC NAT -- Test1#2 客戶端建立UDP socket然后用這個socket向服務(wù)器的(IP-1,Port-1)發(fā)送數(shù)據(jù)包要求服務(wù)器返回客戶端的IP和Port, 客戶端發(fā)送請求后立即開始接受數(shù)據(jù)包。 重復(fù)這個過程直到收到回應(yīng)(一定能夠收到,因為第一步保證了這個客戶端可以進(jìn)行UDP通信)。 用同樣的方法用一個socket向服務(wù)器的(IP-2,Port-2)發(fā)送數(shù)據(jù)包要求服務(wù)器返回客戶端的IP和Port。 比較上面兩個過程從服務(wù)器返回的客戶端(IP,Port),如果兩個過程返回的(IP,Port)有一對不同則說明客戶端為Symmetric NAT,這樣的客戶端無法進(jìn)行UDP-P2P通信(檢測停止)因為對稱型NAT,每次連接端口都不一樣,所以無法知道對稱NAT的客戶端,下一次會用什么端口。否則是Restricted Cone NAT,是否為Port Restricted Cone NAT有待檢測(繼續(xù))。
STEP5:檢測客戶端NAT是Restricted Cone 還是 Port Restricted Cone -- Test3 客戶端建立UDP socket然后用這個socket向服務(wù)器的(IP-1,Port-1)發(fā)送數(shù)據(jù)包要求服務(wù)器用IP-1和一個不同于Port-1的端口發(fā)送一個UDP 數(shù)據(jù)包響應(yīng)客戶端, 客戶端發(fā)送請求后立即開始接受數(shù)據(jù)包。重復(fù)這個過程若干次。如果每次都超時,無法接受到服務(wù)器的回應(yīng),則說明客戶端是一個Port Restricted Cone NAT,如果能夠收到服務(wù)器的響應(yīng)則說明客戶端是一個Restricted Cone NAT。以上兩種NAT都可以進(jìn)行UDP-P2P通信。
通過以上過程,至此,就可以分析和判斷出客戶端是否處于NAT之后,以及NAT的類型及其公網(wǎng)IP,以及判斷客戶端是否具備P2P通信的能力了。