STUN(RFC3489)的NAT類型
在現(xiàn)實(shí)Internet網(wǎng)絡(luò)環(huán)境中,大多數(shù)計(jì)算機(jī)主機(jī)都位于防火墻或NAT之后,只有少部分主機(jī)能夠直接接入Internet。很多時(shí)候,我們希望網(wǎng)絡(luò)中的兩臺主機(jī)能夠直接進(jìn)行通信(即所謂的P2P通信),而不需要其它公共服務(wù)器的中轉(zhuǎn)。由于主機(jī)可能位于防火墻或NAT之后,在進(jìn)行P2P通信之前,我們需要進(jìn)行檢測以確認(rèn)它們之間能否進(jìn)行P2P通信以及如何通信。這種技術(shù)通常被稱為NAT穿透(NAT Traversal)。最常見的NAT穿透是基于UDP的技術(shù)(如下面的RFC3489/STUN),也有基于TCP的穿透技術(shù)。NAT穿透技術(shù)最重要的是識別目標(biāo)主機(jī)的NAT類型,這也是本文所要介紹的內(nèi)容。

NAT有兩大類,基本NAT和NAPT。
基本NAT
靜態(tài)NAT:一個公網(wǎng)IP對應(yīng)一個內(nèi)部IP,一對一轉(zhuǎn)換
動態(tài)NAT:N個公網(wǎng)IP對應(yīng)M個內(nèi)部IP,不固定的一對一轉(zhuǎn)換關(guān)系
NAPT(Network Address/Port Translator)
現(xiàn)在基本使用這種,又分為對稱和錐型NAT。
錐型NAT,有完全錐型、受限制錐型、端口受限制錐型三種:
Full Cone NAT(完全圓錐型):從同一私網(wǎng)地址端口192.168.0.8:4000發(fā)至公網(wǎng)的所有請求都映射成同一個公網(wǎng)地址端口1.2.3.4:62000 ,192.168.0.8可以收到任意外部主機(jī)發(fā)到1.2.3.4:62000的數(shù)據(jù)報(bào)。
Address Restricted Cone NAT (地址限制圓錐型):從同一私網(wǎng)地址端口192.168.0.8:4000發(fā)至公網(wǎng)的所有請求都映射成同一個公網(wǎng)地址端口1.2.3.4:62000,只有當(dāng)內(nèi)部主機(jī)192.168.0.8先給服務(wù)器C 6.7.8.9發(fā)送一個數(shù)據(jù)報(bào)后,192.168.0.8才能收到6.7.8.9發(fā)送到1.2.3.4:62000的數(shù)據(jù)報(bào)。
Port Restricted Cone NAT(端口限制圓錐型):從同一私網(wǎng)地址端口192.168.0.8:4000發(fā)至公網(wǎng)的所有請求都映射成同一個公網(wǎng)地址端口1.2.3.4:62000,只有當(dāng)內(nèi)部主機(jī)192.168.0.8先向外部主機(jī)地址端口6.7.8.9:8000發(fā)送一個數(shù)據(jù)報(bào)后,192.168.0.8才能收到6.7.8.9:8000發(fā)送到1.2.3.4:62000的數(shù)據(jù)報(bào)。
對稱NAT,把所有來自相同內(nèi)部IP地址和端口號,到特定目的IP地址和端口號的請求映射到相同的外部IP地址和端口。如果同一主機(jī)使用不同的源地址和端口對,發(fā)送的目的地址不同,則使用不同的映射。只有收到了一個IP包的外部主機(jī)才能夠向該內(nèi)部主機(jī)發(fā)送回一個UDP包。對稱的NAT不保證所有會話中的(私有地址,私有端口)和(公開IP,公開端口)之間綁定的一致性。相反,它為每個新的會話分配一個新的端口號。
NAT類型
在RFC3489/STUN[1]中,基于UDP的NAT(Network Address Translation)穿透技術(shù)把主機(jī)劃分為如下七種NAT類型:
UDP Blocked、Open Internet、Symmetric Firewall、Full Cone NAT、Restricted Cone NAT、Port Restricted Cone NAT、Symmetric NAT。具體解釋如下:
(1)Open Internet:主機(jī)具有公網(wǎng)IP,允許主動發(fā)起和被動響應(yīng)兩種方式的UDP通信。
(2)UDP Blocked:位于防火墻之后,并且防火墻阻止了UDP通信。
(3)Symmetric Firewall:主機(jī)具有公網(wǎng)IP,但位于防火墻之后,且防火墻阻止了外部主機(jī)的主動UDP通信。
(4)Full Cone NAT:當(dāng)內(nèi)網(wǎng)主機(jī)創(chuàng)建一個UDP socket并通過它第一次向外發(fā)送UDP數(shù)據(jù)包時(shí),NAT會為之分配一個固定的公網(wǎng){IP:端口}。此后,通過這個socket發(fā)送的任何UDP數(shù)據(jù)包都是通過這個公網(wǎng){IP:端口}發(fā)送出去的;同時(shí),任何外部主機(jī)都可以使用這個公網(wǎng){IP:端口}向該socket發(fā)送UDP數(shù)據(jù)包。即是說,NAT維護(hù)了一個映射表,內(nèi)網(wǎng)主機(jī)的內(nèi)網(wǎng){IP:端口}與公網(wǎng){IP:端口}是一一對應(yīng)的關(guān)系。一旦這個映射關(guān)系建立起來(內(nèi)部主機(jī)向某一外部主機(jī)發(fā)送一次數(shù)據(jù)即可),任何外部主機(jī)就可以直接向NAT內(nèi)的這臺主機(jī)發(fā)起UDP通信了,此時(shí)NAT透明化了。
(5)Restricted Cone NAT:當(dāng)內(nèi)網(wǎng)主機(jī)創(chuàng)建一個UDP socket并通過它第一次向外發(fā)送UDP數(shù)據(jù)包時(shí),NAT會為之分配一個公網(wǎng){IP:端口}。此后,通過這個socket向外發(fā)送的任何UDP數(shù)據(jù)包都是通過這個公網(wǎng){IP:端口}發(fā)送出去的;而任何收到過從這個socket發(fā)送來的數(shù)據(jù)的外部主機(jī)(由IP標(biāo)識),都可以通過這個公網(wǎng){IP:端口}向該socket發(fā)送UDP數(shù)據(jù)包。即是說,NAT維護(hù)了一個內(nèi)網(wǎng){IP:端口}到公網(wǎng){IP:端口}的映射,還維護(hù)了一個{外部主機(jī)IP, 公網(wǎng){IP:端口}}到內(nèi)網(wǎng){IP:端口}的映射。因此,要想外部主機(jī)能夠主動向該內(nèi)部主機(jī)發(fā)起通信,必須先由該內(nèi)部主機(jī)向這個外部發(fā)起一次通信。
(6)Port Restricted Cone NAT:當(dāng)內(nèi)網(wǎng)主機(jī)創(chuàng)建一個UDP socket并通過它第一次向外發(fā)送UDP數(shù)據(jù)包時(shí),NAT會為之分配一個公網(wǎng){IP:端口}。此后,通過這個socket向外部發(fā)送的任何UDP數(shù)據(jù)包都是通過這個公網(wǎng){IP:端口}發(fā)送出去的;一旦外部主機(jī)在{IP:端口}上收到過從這個socket發(fā)送來的數(shù)據(jù)后,都可以通過這個外部主機(jī){IP:端口}向該socket發(fā)送UDP數(shù)據(jù)包。即是說,NAT維護(hù)了一個從內(nèi)網(wǎng){IP:端口}到公網(wǎng){IP:端口}的映射,還維護(hù)了一個從{外部主機(jī){IP:端口}, 公網(wǎng){IP:端口}}到內(nèi)網(wǎng){IP:端口}的映射。
(7)Symmetrict NAT:當(dāng)內(nèi)網(wǎng)主機(jī)創(chuàng)建一個UDP socket并通過它第一次向外部主機(jī)1發(fā)送UDP數(shù)據(jù)包時(shí),NAT為其分配一個公網(wǎng){IP1:端口1},以后內(nèi)網(wǎng)主機(jī)發(fā)送給外部主機(jī)1的所有UDP數(shù)據(jù)包都是通過公網(wǎng){IP1:端口1}發(fā)送的;當(dāng)內(nèi)網(wǎng)主機(jī)通過這個socket向外部主機(jī)2發(fā)送UDP數(shù)據(jù)包時(shí),NAT為其分配一個公網(wǎng){IP2:端口2},以后內(nèi)網(wǎng)主機(jī)發(fā)送給外部主機(jī)2的所有UDP數(shù)據(jù)包都是通過公網(wǎng){IP2:端口2}發(fā)送的。公網(wǎng){IP1:端口1}和公網(wǎng){IP2:端口2}一定不會完全相同(即要么IP不同,要么端口不同,或者都不同)。這種情況下,外部主機(jī)只能在接收到內(nèi)網(wǎng)主機(jī)發(fā)來的數(shù)據(jù)時(shí),才能向內(nèi)網(wǎng)主機(jī)回送數(shù)據(jù)。
錐形NAT與對稱NAT的區(qū)別
所謂錐形NAT 是指:只要是從同一個內(nèi)部地址和端口出來的包,無論目的地址是否相同,NAT 都將它轉(zhuǎn)換成同一個外部地址和端口。
“同一個外部地址和端口”與“無論目的地址是否相同”形成了一個類似錐形的網(wǎng)絡(luò)結(jié)構(gòu),也是這一名稱的由來。反過來,不滿足這一條件的即為對稱NAT 。
舉例說明,假設(shè):
NAT 內(nèi)的主機(jī) A : IP 記為 A ,使用端口 1000
NAT 網(wǎng)關(guān) : IP 記為 NAT ,用于 NAT 的端口池假設(shè)為( 5001-5999 )
公網(wǎng)上的主機(jī) B : IP 記為B ,開放端口 2000
公網(wǎng)上的主機(jī) C : IP 記為C ,開放端口 3000
假設(shè)主機(jī) A 先后訪問主機(jī) B 和 C
1 )如果是錐形 NAT :
那么成功連接后,狀態(tài)必然如下:
A ( 1000 ) —— > NAT ( 5001 )—— > B ( 2000 )
A ( 1000 ) —— > NAT ( 5001 )—— > C ( 3000 )
也就是說,只要是從 A 主機(jī)的 1000 端口發(fā)出的包,經(jīng)過地址轉(zhuǎn)換后的源端口一定相同。
2 )如果是對稱形 NAT :
連接后,狀態(tài)有可能(注意是可能,不是一定)如下:
A ( 1000 ) —— > NAT ( 5001 )—— > B ( 2000 )
A ( 1000 ) —— > NAT ( 5002 )—— > C ( 3000 )
兩者的區(qū)別顯而易見。
三種CONE NAT之間的區(qū)別
仍然以上面的網(wǎng)絡(luò)環(huán)境為例, 假設(shè) A 先與 B 建立了連接:
A ( 1000 ) —— > NAT ( 5001 )——— > B ( 2000 )
1) Port Restricted Cone NAT:
只有 B ( 2000 )發(fā)往 NAT ( 5001 )的數(shù)據(jù)包可以到達(dá) A ( 1000 )
B ( 2000 ) —— > NAT ( 5001 ) ——— > A ( 1000 )
B ( 3000 ) —— > NAT ( 5001 ) — X — > A ( 1000 )
C ( 2000 ) —— > NAT ( 5001 ) — X — > A ( 1000 )
該nat 將內(nèi)網(wǎng)中一臺主機(jī)的IP和端口映射到公網(wǎng)IP和一個指定端口,只有訪問過的IP和端口可以通過映射后的IP和端口連接主機(jī)A
2) Restricted Cone NAT
只要是從 B 主機(jī)發(fā)往 NAT ( 5001 )的數(shù)據(jù)包都可以到達(dá) A ( 1000 )
B ( 2000 ) —— > NAT ( 5001 ) ——— > A ( 1000 )
B ( 3000 ) —— > NAT ( 5001 ) ——— > A ( 1000 )
C ( 2000 ) —— > NAT ( 5001 ) — X — > A ( 1000 )
該nat 將內(nèi)網(wǎng)中一臺主機(jī)的IP和端口映射到公網(wǎng)IP和一個指定端口,只有訪問過的IP可以通過映射后的IP和端口連接主機(jī)A
3) Full Cone NAT
任意地址發(fā)往 NAT ( 5001 )的數(shù)據(jù)包都可以到達(dá) A ( 1000 )
B ( 2000 ) —— > NAT ( 5001 ) ——— > A ( 1000 )
B ( 3000 ) —— > NAT ( 5001 ) ——— > A ( 1000 )
C ( 3000 ) —— > NAT ( 5001 ) ——— > A ( 1000 )
該nat 將內(nèi)網(wǎng)中一臺主機(jī)的IP和端口映射到公網(wǎng)IP和一個指定端口,外網(wǎng)的任何主機(jī)都可以通過映射后的IP和端口發(fā)送消息
Linux的NAT
Linux的NAT“MASQUERADE”屬于對稱形NAT。說明這一點(diǎn)只需要否定 MASQUERADE 為錐形 NAT 即可。
linux 在進(jìn)行地址轉(zhuǎn)換時(shí),會遵循兩個原則:
盡量不去修改源端口,也就是說,ip 偽裝后的源端口盡可能保持不變。
更為重要的是,ip 偽裝后必須 保證偽裝后的源地址/ 端口與目標(biāo)地址/ 端口(即所謂的socket )唯一。
假設(shè)如下的情況( 內(nèi)網(wǎng)有主機(jī) A 和 D ,公網(wǎng)有主機(jī) B 和 C ):
先后 建立如下三條連接:
A ( 1000 ) —— > NAT ( 1000 )—— > B ( 2000 )
D ( 1000 ) —— > NAT ( 1000 )—— > C ( 2000 )
A ( 1000 ) —— > NAT ( 1001 )—— > C ( 2000 )
可以看到,前兩條連接遵循了原則 1 ,并且不違背原則 2 而第三條連接為了避免與第二條產(chǎn)生相同的 socket 而改變了源端口比較第一和第三條連接,同樣來自 A(1000) 的數(shù)據(jù)包在經(jīng)過 NAT 后源端口分別變?yōu)榱?1000 和1001 。說明 Linux 的 NAT 是對稱 NAT 。
對協(xié)議的支持
CONE NAT 要求原始源地址端口相同的數(shù)據(jù)包經(jīng)過地址轉(zhuǎn)換后,新源地址和端口也相同,換句話說,原始源地址端口不同的數(shù)據(jù)包,轉(zhuǎn)換后的源地址和端口也一定不同。
那么,是不是 Full Cone NAT 的可穿透性一定比 Symmetric NAT 要好呢,或者說,通過 Symmetric NAT 可以建立的連接,如果換成 Full Cone NAT 是不是也一定能成功呢?
假設(shè)如下的情況:
(內(nèi)網(wǎng)有主機(jī)A和D,公網(wǎng)有主機(jī)B和C,某 UDP 協(xié)議服務(wù)端口為 2000 ,并且要求客戶端的源端口一定為 1000 。 )
1)如果A使用該協(xié)議訪問B:
A ( 1000 ) —— > NAT ( 1000 )——— > B ( 2000 )
由于 Linux 有盡量不改變源端口的規(guī)則,因此在 1000 端口未被占用時(shí),連接是可以正常建立的如果此時(shí)D也需要訪問B:
D ( 1000 ) —— > NAT ( 1001 )—X— > B ( 2000 )
端口必須要改變了,否則將出現(xiàn)兩個相同的 socket ,后續(xù)由 B(2000) 發(fā)往NAT( 1000 )的包將不知道是轉(zhuǎn)發(fā)給A還是D。于是B將因?yàn)榭蛻舳说脑炊丝阱e誤而拒絕連接。在這種情況下, MASQUERADE 與 CONENAT 的表現(xiàn)相同。
2)如果A連接B后,D也像C發(fā)起連接,而在此之后,A又向C發(fā)起連接
① A ( 1000 ) —— > NAT ( 1000 )——— > B ( 2000 )
如果是 MASQUERADE :
② D ( 1000 ) —— > NAT ( 1000 )——— > C ( 2000 )
③ A ( 1000 ) —— > NAT ( 1001 )—X— > C ( 2000 )
如果是 CONE NAT :
② D ( 1000 ) —— > NAT ( 1001 )—X— > C ( 2000 )
③ A ( 1000 ) —— > NAT ( 1000 )——— > C ( 2000 )
對于 MASQUERADE 來說,只要在沒有重復(fù)的 socket 的情況下,總是堅(jiān)持盡量不改變源端口的原則,因此第二條連接仍然采用源端口 1000 ,而第三條連接為了避免重復(fù)的 socket 而改變了端口。
對于 CONE NAT ,為了保證所有來自 A(1000) 的數(shù)據(jù)包均被轉(zhuǎn)換為 NAT(1000) ,因此 D 在向 C 發(fā)起連接時(shí),即使不會產(chǎn)生重復(fù)的 socket ,但因?yàn)?NAT 的 1000 端口已經(jīng)被 A(1000) “占用”了,只好使用新的端口。
可以看出,不同的 target 產(chǎn)生不同的結(jié)果。我們也不能絕對的說,在任何時(shí)候,全錐形 NAT 的可穿透性都比對稱 NAT 要好,比如上面的例子,如果只存在連接①和②,顯然是對稱形 NAT 要更適用。因此,選擇哪種 NAT ,除了對網(wǎng)絡(luò)安全和普遍的可穿透性的考慮外,有時(shí)還需要根據(jù)具體應(yīng)用來決定。
RFC3489/STUN協(xié)議判斷過程
輸入和輸出準(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)如果每次都超時(shí)收不到服務(wù)器的響應(yīng),則說明客戶端無法進(jìn)行UDP通信,可能是:防火墻阻止UDP通信;
b)如果能收到回應(yīng),則把服務(wù)器返回的客戶端的(IP:PORT)同(Local IP: Local Port)比較:
如果完全相同則客戶端不在NAT后,這樣的客戶端是:具有公網(wǎng)IP可以直接監(jiān)聽UDP端口接收數(shù)據(jù)進(jìn)行通信或者對稱NAT。
否則客戶端在NAT后要做進(jìn)一步的NAT類型檢測(繼續(xù))。
STEP2:檢測客戶端防火墻類型 -- Test2
STUN客戶端向STUN服務(wù)器發(fā)送請求,要求服務(wù)器從其他IP和PORT向客戶端回復(fù)包:
a)收不到服務(wù)器從其他IP地址的回復(fù),認(rèn)為包前被前置防火墻阻斷,網(wǎng)絡(luò)類型為對稱NAT;
b)收到則認(rèn)為客戶端處在一個開放的網(wǎng)絡(luò)上,網(wǎng)絡(luò)類型為公開的互聯(lián)網(wǎng)IP。
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)如果每次都超時(shí),無法接受到服務(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)(一定能夠收到,因?yàn)榈谝徊奖WC了這個客戶端可以進(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通信(檢測停止)因?yàn)閷ΨQ型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ù)這個過程若干次。如果每次都超時(shí),無法接受到服務(wù)器的回應(yīng),則說明客戶端是一個Port Restricted Cone NAT,如果能夠收到服務(wù)器的響應(yīng)則說明客戶端是一個Restricted Cone NAT。以上兩種NAT都可以進(jìn)行UDP-P2P通信。
一些說明:
STUN Client and Server library(http://sourceforge.net/projects/stun/)
這個庫實(shí)現(xiàn)了RFC3489中的STUN協(xié)議。其中,Client程序輸出結(jié)果意義如下:
(1)"Open"表示這里的Open Internet
(2)"Independent Mapping, Independent Filter"表示這里的Full Cone NAT
(3)"Independedt Mapping, Address Dependendent Filter"表示這里的Restricted Core NAT
(4)"Indepndent Mapping, Port Dependent Filter"表示這里的Port Restricted Core NAT
(5)"Dependent Mapping"表示這里的Symmetric NAT
(6)"Firewall"表示這里的Symmetric Firewall
(7)"Blocked or could not reach STUN server"表示這里的UDP Blocked
reTurn (http://www.resiprocate.org/ReTurn_Overview)
實(shí)現(xiàn)了RFC5389中的STUN協(xié)議和TURN協(xié)議。
網(wǎng)上一些可用STUN Server(注意:STUN協(xié)議指定默認(rèn)端口為3478)
stun01.sipphone.com
stun.iptel.org
stun.softjoys.com
stun.xten.com(這個STUN Server的實(shí)現(xiàn)好像有問題,測試結(jié)果與前面三個不相同)
[1] RFC3489中的STUN協(xié)議(Simple Traversal of UDP Through NATs)是一個完整的NAT穿透方案,但其修訂版本(RFC5389)把STUN協(xié)議(Session Traversal Utilities for NAT)定位于為穿透NAT提供工具,并不提供一個完整的解決方案。此外,RFC3489只提供了UDP的NAT穿透,而RFC5389還支持TCP的穿透)。
Reference
NAT穿透
NAT(Network address translation)
作者:老鼠AI大米_Java全棧
鏈接:https://www.jianshu.com/p/1432c729df4d