NAT/STUN

1.RFC3489 - STUN

RFC 3489 《STUN – Simple Traversal of UDP Through NATs》(《簡單的用UDP穿透NATs》)描述了一套用於使UDP穿過NAT的協議,本文並不關心STUN協議的實現,如STUN Client或Server。相反我們更關心作爲STUN穿透對象的NAT。

NAT是爲了解決網絡地址資源的問題出現的一種折中辦法,顯然使用NAT並不如擁有一個專用的Internet地址來得方便,但是從另一個角度看,NAT也爲網絡提供了許多安全保障。NAT的實現細節是多種多樣的,但總的來說,越開放的則越危險,越封閉的則越安全。

2.NAT 的劃分

RFC3489中將NAT的實現分爲四大類:

1.Full Cone NAT 完全錐形NAT

2.Restricted Cone NAT 限制錐形NAT(可以理解爲IP限制)

3.Port Restricted Cone NAT 端口限制錐形NAT(IP+Port限制)

4.Symmetric NAT 對稱NAT

其中完全錐形的穿透性最好,而對稱形的安全性最高。

1.錐形NAT與對稱NAT的區別

所謂錐形NAT是指:只要是從同一個內部地址和端口出來的包,無論目的地址是否相同,NAT都將它轉換成同一個外部地址和端口。

“同一個外部地址和端口”與“無論目的地址是否相同”形成了一個類似錐形的網絡結構,也是這一名稱的由來。

反過來,不滿足這一條件的即爲對稱NAT。

舉個例子:

NAT內的主機A: IP記爲A,使用端口1000

NAT網關: IP記爲NAT,用於NAT的端口池假設爲(5001-5999)

公網上的主機B: IP記爲B,開放端口2000

公網上的主機C: IP記爲C,開放端口3000

假設主機A先後訪問主機B和C

1)如果是錐形NAT:

那麼成功連接後,狀態必然如下:

A(1000) ——> NAT(5001)——> B(2000)

A(1000) ——> NAT(5001)——> C(3000)

也就是說,只要是從A主機的1000端口發出的包,經過地址轉換後的源端口一定相同。

2)如果是對稱形NAT:

連接後,狀態有可能(注意是可能,不是一定)如下:

A(1000) ——> NAT(5001)——> B(2000)

A(1000) ——> NAT(5002)——> C(3000)

兩者的區別顯而易見。

2.三種CONE NAT之間的區別

仍然以上面的網絡環境爲例:

假設A先與B建立了連接,

A(1000) ——> NAT(5001)———> B(2000)

1)Port Restricted Cone NAT

只有B(2000)發往NAT(5001)的數據包可以到達A(1000)

B(2000) ——> NAT(5001) ———> A(1000)

B(3000) ——> NAT(5001) —X—> A(1000)

C(2000) ——> NAT(5001) —X—> A(1000)

2)Restricted Cone NAT

只要是從B主機發往NAT(5001)的數據包都可以到達A(1000)

B(2000) ——> NAT(5001) ———> A(1000)

B(3000) ——> NAT(5001) ———> A(1000)

C(2000) ——> NAT(5001) —X—> A(1000)

3)Full Cone NAT

任意地址發往NAT(5001)的數據包都可以到達A(1000)

B(2000) ——> NAT(5001) ———> A(1000)

B(3000) ——> NAT(5001) ———> A(1000)

C(3000) ——> NAT(5001) ———> A(1000)

3.Linux的NAT

Linux的NAT“MASQUERADE”屬於對稱形NAT。

說明這一點只需要否定MASQUERADE爲錐形NAT即可。

Linux在進行地址轉換時,會遵循兩個原則:

1、儘量不去修改源端口,也就是說,ip僞裝後的源端口儘可能保持不變。

2、更爲重要的是,ip僞裝後必須保證僞裝後的源地址/端口與目標地址/端口(即所謂的socket)唯一。

假設如下的情況:

內網有主機A和D,公網有主機B和C。

先後建立如下三條連接:

A(1000) ——> NAT(1000)——> B(2000)

D(1000) ——> NAT(1000)——> C(2000)

A(1000) ——> NAT(1001)——> C(2000)

可以看到,前兩條連接遵循了原則1,並且不違背原則2

而第三條連接爲了避免與第二條產生相同的socket而改變了源端口

比較第一和第三條連接,同樣來自A(1000)的數據包在經過NAT後源端口分別變爲了1000和1001。說明Linux的NAT是對稱NAT。

4.對協議的支持

CONENAT要求原始源地址端口相同的數據包經過地址轉換後,新源地址和端口也相同,換句話說,原始源地址端口不同的數據包,轉換後的源地址和端口也一定不同。

那麼,是不是Full Cone NAT的可穿透性一定比Symmetric NAT要好呢,或者說,通過Symmetric NAT可以建立的連接,如果換成Full Cone NAT是不是也一定能成功呢?

假設如下的情況:

內網有主機A和D,公網有主機B和C,某UDP協議服務端口爲2000,並且要求客戶端的源端口一定爲1000。

1)如果A使用該協議訪問B

A(1000) ——> NAT(1000)———> B(2000)

由於Linux有儘量不改變源端口的規則,因此在1000端口未被佔用時,連接是可以正常建立的

如果此時D也需要訪問B

D(1000) ——> NAT(1001)—X—> B(2000)

端口必須要改變了,否則將出現兩個相同的socket,後續由B(2000)發往NAT(1000)的包將不知道是轉發給A還是D。

於是B將因爲客戶端的源端口錯誤而拒絕連接。

在這種情況下,MASQUERADE與CONENAT的表現相同。

2)如果A連接B後,D也像C發起連接,而在此之後,A又向C發起連接

 ① A(1000) ——> NAT(1000)———> B(2000)

如果是MASQUERADE:

 ② D(1000) ——> NAT(1000)———> C(2000)

 ③ A(1000) ——> NAT(1001)—X—> C(2000)

如果是CONENAT:

 ② D(1000) ——> NAT(1001)—X—> C(2000)

 ③ A(1000) ——> NAT(1000)———> C(2000)

對於MASQUERADE來說,只要在沒有重複的socket的情況下,總是堅持儘量不改變源端口的原則,因此第二條連接仍然採用源端口1000,而第三條連接爲了避免重複的socket而改變了端口。

對於CONENAT,爲了保證所有來自A(1000)的數據包均被轉換爲NAT(1000),因此D在向C發起連接時,即使不會產生重複的socket,但因爲NAT的1000端口已經被A(1000)“佔用”了,只好使用新的端口。

可以看出,不同的target產生不同的結果。我們也不能絕對的說,在任何時候,全錐形NAT的可穿透性都比對稱NAT要好,比如上面的例子,如果只存在連接①和②,顯然是對稱形NAT要更適用。

因此,選擇哪種NAT,除了對網絡安全和普遍的可穿透性的考慮外,有時還需要根據具體應用來決定。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章