本文原址 http://www.cnblogs.com/lidabo/p/3828846.html
在網絡編碼中會發現程序在局域網中是可以適用的,但是在外網與內網之間和內網與內網之間就不可行。
問題就在於NAT。首先介紹下NAT。
NAT的作用NAT(Network Address Translator),網絡地址轉換。顧名思義,它是一種把內部私有網絡IP地址翻譯成公有網絡IP地址的技術,如圖5-1所示。NAT是在IP地址日益缺乏的情況下產生的,它的主要目的是使地址能夠重用[9]。
圖5-1 NAT模型
IP地址分為五類:A類,B類,C類,D類,E類(這里不考慮保留的IP地址)。A、B、C類可被計算機作為IP地址,D類為組播地址,E類為特殊用途的地址。A、B、C類中,又可分為公有地址和私有地址,私有地址用於內網,不同的內網,私有地址可重用,從而節省了公網地址,它不可在公網中被路由,所以內網的主機要訪問公網的服務器,便要經過NAT。公有地址是全球唯一的,能在公網上被路由。
內網主機用私有地址在內網能與其它的內網主機無誤地通信,但它不能直接用私有地址訪問外網的主機,因為私有地址不能被路由。它要與外網通信,必須經過NAT設備(如網關,路由器),如圖5-2所示。主機A與服務器S通信,它須先通過網關,此時網關改變它的數據包地址及端口,把私有地址(10.0.0.2)改為公有地址(155.99.25.11),使數據包能在公網上被路由,送至服務器端。服務器端返回的數據包到達網關后,網關把公網地址改為相應的私有地址,然后轉發到主機A。通過這種方法,一個內網只需一個公有IP地址,就把整個內網的計算機接入Internet,從而解決IP地址缺乏的問題。
NAT功能通常被集成到路由器、防火牆、ISDN路由器或者單獨的NAT設備中。也可通過軟件實現這一功能,Windows 98 SE、Windows 2000 都包含了這一功能。
NAT的分類及工作原理
基本NAT與NAPT如圖5-3所示,NAT分為兩大類,基本的NAT和NAPT(Network Address/Port Translator)[10][11]。
基本的NAT,它僅將內網主機的私有IP地址轉換成公網IP地址,但並不將TCP/UDP端口信息進行轉換,有動態與靜態之區分。由於現在大部分都屬於另一種類型,即NAPT,故這里不詳細討論基礎NAT。
另外一種NAT叫做NAPT(Network Address/Port Translator),從名稱上我們也可以看得出,NAPT不但會改變經過這個NAT設備的IP數據報的IP地址,還會改變IP數據報的TCP/UDP端口。NAPT的地址及端口的轉換過程,請看圖5-4:
私有網絡中某一主機Client A(10.0.0.2),它的某個進程通過1234端口,想訪問外網服務器18.181.0.31的1235端口。那么當數據包通過NAT時,這個NAT的外網地址是155.99.25.11,首先NAT會改變這個數據包的原IP地址,改為155.99.25.11。並分配一個端口(如62000)給Client A,把數據包的原端口號改為62000。所以本來是(10.0.0.2:1234->18.181.0.31:1235)的數據包到了互聯網上變為了(155.99.25.11:62000->18.181.0.31:1235),如圖5-4左圖所示。NAT會記住62000端口對應的是10.0.0.2的1234端口,以后從外網服務器18.181.0.31發送到62000端口的數據會被NAT自動的改變目的IP和端口號,然后轉發到10.0.0.2上(如圖5-4右圖所示)
錐型NAT與對稱型NAT
NAPT又分為錐型(Cone)和對稱型(Symmetric),如圖5-5所示,它們的區別在於,在NAT已分配端口號給Client A的情況下,如果Client A繼續用1235端口與另一外網服務器通訊,錐型NAT還會繼續用原來62000端口,即所分配的端口號不變。而對於對等型NAT,NAT將會分配另一端口號(如62001)給Client A的1235端口。也就是說,同一內網主機同一端口號,對於錐型NAT,無論與哪一外網主機通訊,都不改變所分配的端口號;而對於對等型NAT,同一內網主機同一端口號,每一次與不同的外網主機通訊,就重新分配另一個端口號。
完全錐型NAT、受限制錐型NAT與端口受限制型NAT
錐型NAT可另外分類為完全錐形(Full Cone)NAT,受限制錐形(Restricted Cone)NAT,端口受限制錐形(Port Restricted Cone)NAT。
①完全錐形(Full Cone)NAT
這種NAT內部的主機A連接過外網主機C后,NAT會打開一個端口。然后外網的任何發到這個打開的端口的UDP數據報都可以到達A,不管是不是C發過來的[12]。
例如 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)。
②受限制錐形(Restricted Cone)NAT
這種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)。
③端口受限制錐形(Port Restricted Cone)NAT
這種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產生的問題
NAT很好地解決了地址緊缺的問題,屏蔽了內部網絡,但也帶來一些問題。內網的主機向外連接是很容易的(NAT相當於透明的,內網的和外網的主機均不用知道NAT的情況)。但如果外部的計算機想訪問子網內的計算機就比較困難了,這可以使內網主機先發起連接從而解決問題。但是如果兩台主機都分別位於兩不同NAT后面時,兩台主機無法通信。當分別位於兩不同NAT(NAT A,NAT B)后面的兩台主機A和B欲進行通訊時,若主機B主動發起連接,它該連哪個地址呢?第一種情況:試圖直接連到主機A的內網私有地址(10.0.0.2:1234)肯定會失敗,因為10.0.0.2根本就不是一個可以在公網上路由的IP地址;第二種情況,試圖直接連到B的NAT公有地址(155.99.25.11:62000),NAT A會拒絕這個數據包,因為這個端口並無綁定內網主機的某個端口,或即使有所綁定,但這個端口所綁定的外網地址和端口並不是B的地址和端口。若A主動連接B,結果一樣。
有兩種方法解決這個問題。方法一:通過服務器,服務器作為中間人,轉發主機間的數據。但若用戶數量到達一定數目時,這方法浪費帶寬且給服務器帶來很大壓力,所以方法不可行。方法二,還是通過服務器,但服務器只充當“介紹人”,不轉發主機間的數據,具體請看下面的“UDP打孔技術” (UDP hole punching)
穿透NAT——UDP打孔技術
所謂的“打孔技術”,就是在內網的NAT設備上打上一個“孔”(也就是在NAT上建立一個會話,綁定地址和端口號),這個孔不能由外部來打,只能由內網內的主機來打。而且這個孔可能是有方向的,比如從內部某台主機(比如:192.168.0.10)向外部的某個IP(比如:219.237.60.1)發送一個UDP包,那么就在這個內網的NAT設備上打了一個方向為219.237.60.1的“孔”,以后219.237.60.1就可以通過這個孔與內網的192.168.0.10聯系了[13]。
下面就根據NAT的各種類型詳細解析如何“打孔”,如何穿透NAT。
1.完全錐形(Full Cone)NAT
處於不同內網的主機A和主機B,各自先連接服務器,從而在各自NAT設備上打開了一個“孔”,服務器收到主機A和主機B的連接后,知道A與B的公網地址和NAT分配給它們的端口號,然后把這些NAT地址與端口號告訴A與B,由於在完全錐形NAT的特點,A和B給服務器所打開的“孔”,能給別的任何的主機使用。故A與B可連接對方的公網地址和端口直接進行通信。服務器在這里充當“介紹人”,告訴A與B對方的地址和端口號。
2.受限制錐形(Restricted Cone)NAT
A和B還是要先連接服務器,服務器發送A和B的地址和端口信息給A和B,但由於受限制錐形NAT的特點,他們所打開的“孔”,只能與服務器通信。要使他們可以直接通信,解決辦法如下:
假如主機A開始發送一個UDP信息到主機B的公網地址上,與此同時,它又通過服務器中轉發送了一個邀請信息給主機B,請求主機B也給主機A發送一個UDP信息到主機A的公網地址上。這時主機A向主機B的公網IP發送的信息導致NAT A打開一個處於主機A的和主機B之間的會話,與此同時,NAT B也打開了一個處於主機B和主機A的會話。一旦這個新的UDP會話各自向對方打開了,主機A和主機B之間就可以直接通信了[14]。
3.端口受限制錐形(Port Restricted Cone)NAT
對於該類型的NAT,解決辦法跟上面的方法一樣。
4.對稱型(Symmetric)NAT
對稱型NAT,對於不同的外網主機地址,它都會分配不同的端口號,所以進行UDP打孔比較困難,但也可以進行端口預測打孔,不過不能保證成功。
以上的穿透NAT,是對NAPT來進行穿透,主要是針對UDP協議。TCP協議也有可能,但是可行性非常小,要求更高。並且,語音視頻通信是用UDP傳輸的,故針對TCP的NAT穿透在這里不作討論。基礎NAT不修改經過的數據包的端口號,它們可以看作是完全錐形NAT的精簡版本,即基礎NAT也可以被穿透。NAT設備將在一定時間后關閉UDP的一個映射,所以為了保持與服務器能夠一直通信,服務器或客戶端必須要周期性地發送UDP包,保持映射不被關閉。
目前比較常用的NAT類型是完全錐型NAT
如圖6-7所示,步驟如下:
①客戶端A發UDP數據報經NAT A,把數據發送到服務器。NAT A分配端口給客戶端A。服務器接收到信息后,把客戶端A經NAT A后的地址及端口信息記錄下來。
②客戶端B發UDP數據報經NAT B,把數據發送到服務器。NAT B分配端口給客戶端B。服務器接收到信息后,把客戶端B經NAT B后的地址及端口信息記錄下來。
③ 服務器把客戶端B的地址及端口信息發送給客戶端A,把客戶端A的地址及端口信息發送給客戶端B,客戶端A、B就可以通過所獲得的對方的地址及端口號進行通信了。