NAT穿越模塊的設計與實(shí)現
Internet的快速發(fā)展以及IPv4地址數量的不足使得NAT設備得到了大規模的應用,然而這也給越來(lái)越多的端到端通信也帶來(lái)了不少的麻煩。一般來(lái)說(shuō),NAT設備允許內網(wǎng)內主機主動(dòng)向公網(wǎng)內主機發(fā)送數據,但卻禁止內網(wǎng)外的主機主動(dòng)向內網(wǎng)內的主機傳遞數據。由于很多的會(huì )話(huà)雙方處于不同的NAT設備后,它們通信一般通過(guò)公網(wǎng)服務(wù)器中轉,而要建立P2P通信,則必須解決NAT穿越問(wèn)題才能建立通信。
NAT 是介于內網(wǎng)和公網(wǎng)之間的設備,公網(wǎng)中的IP 地址是全球唯一的,而在內網(wǎng)中的IP 地址可以重復出現,但不能出現在公網(wǎng)中[18]。NAT的基本功能就是通過(guò)一個(gè)或幾個(gè)lP地址,來(lái)實(shí)現局域網(wǎng)上的所有主機都可以對因特網(wǎng)進(jìn)行訪(fǎng)問(wèn)[19]。
NAT實(shí)現了公網(wǎng)地址和內網(wǎng)地址之間的映射,可從兩個(gè)方面來(lái)概括:(1) 當內網(wǎng)內的IP包經(jīng)過(guò)NAT需要流入公網(wǎng)時(shí),NAT將此IP 包的源IP地址和端口改為NAT接口上的一個(gè)公網(wǎng)地址和端口;(2)當公網(wǎng)中的IP包經(jīng)過(guò)NAT 需要訪(fǎng)問(wèn)內網(wǎng)資源時(shí),NAT將此IP 包的目的地址和端口改為內網(wǎng)IP 地址和端口。
圖3.1 UDP包經(jīng)過(guò)NAT原理圖
圖 3.1是 UDP包經(jīng)過(guò)NAT后的示意圖,可以看出UDP包從內網(wǎng)主機A發(fā)出時(shí),到達NAT后它的源端IP和端口都已經(jīng)改變。同時(shí)從主機B的UDP包發(fā)往NAT-A的公網(wǎng)IP和端口后,NAT將其自動(dòng)轉發(fā)給主機A。
NAT設備的類(lèi)型對于穿越NAT,有著(zhù)十分重要的影響,根據其端口映射方式,NAT可分為如下4類(lèi),前3種NAT類(lèi)型可統稱(chēng)為cone NAT。
(1)全克隆( Full Cone) : NAT把所有來(lái)自相同內部IP地址和端口的請求映射到相同的外部IP地址和端口。任何一個(gè)外部主機均可通過(guò)該映射發(fā)送IP包到該內部主機。
(2)限制性克隆(Restricted Cone) : NAT把所有來(lái)自相同內部IP地址和端口的請求映射到相同的外部IP地址和端口。但是,只有當內部主機先給IP地址為X的外部主機發(fā)送IP包,該外部主機才能向該內部主機發(fā)送IP包。
(3)端口限制性克隆( Port Restricted Cone) :端口限制性克隆與限制性克隆類(lèi)似,只是多了端口號的限制,即只有內部主機先向IP地址為X,端口號為P的外部主機發(fā)送1個(gè)IP包,該外部主機才能夠把源端口號為P的IP包發(fā)送給該內部主機。
(4)對稱(chēng)式NAT ( Symmetric NAT) :這種類(lèi)型的NAT與上述3種類(lèi)型的不同,在于當同一內部主機使用相同的端口與不同地址的外部主機進(jìn)行通信時(shí), NAT對該內部主機的映射會(huì )有所不同。對稱(chēng)式NAT不保證所有會(huì )話(huà)中的內有地址和公開(kāi)IP之間綁定的一致性。相反,它為每個(gè)新的會(huì )話(huà)分配一個(gè)新的端口號。所以即使是同一臺外部主機的不同連接,其分配的端口號都是不一樣的,通常都是在原來(lái)的端口號上加一。
由此可見(jiàn),SymmetricCone條件最嚴格,Port /Restricted Cone次之,Full Cone條件最不嚴格。因為我國的網(wǎng)絡(luò )技術(shù)應用得比較晚,所以可以說(shuō)絕大部分的網(wǎng)絡(luò )都是cone NAT[20]。
NAT的存在,使得局域網(wǎng)的用戶(hù)可以共享一個(gè)IP地址訪(fǎng)問(wèn)因特網(wǎng),解決了IP地址的不足,同時(shí)起到了防火墻的作用。但是NAT的存在給P2P網(wǎng)絡(luò )也帶來(lái)了問(wèn)題:(1)內網(wǎng)主機的IP地址是虛擬的,在因特網(wǎng)上是非法的,因而內網(wǎng)主機對公網(wǎng)是不可見(jiàn)的。(2)即使內網(wǎng)內主機的IP地址已知,NAT仍然阻止公網(wǎng)主機主動(dòng)訪(fǎng)問(wèn)內網(wǎng)主機。(3)內網(wǎng)主機可以作為客戶(hù)機訪(fǎng)問(wèn)外網(wǎng),但不能作為服務(wù)器向外網(wǎng)提供服務(wù)[21]。
NAT產(chǎn)生種種問(wèn)題的原因主要是NAT不允許外部主機主動(dòng)訪(fǎng)問(wèn)內部主機,這樣雖然有安全性高的優(yōu)點(diǎn),但是同時(shí)帶來(lái)服務(wù)性能低的不良效果。上述這些限制使得在NAT的網(wǎng)絡(luò )中,外網(wǎng)主機無(wú)法穿過(guò)NAT主動(dòng)與內網(wǎng)主機進(jìn)行通信,P2P網(wǎng)絡(luò )各主機無(wú)法彼此發(fā)現對方進(jìn)行對等信息交換,特別是位于不同NAT之后的不同內網(wǎng)中的機器,更是無(wú)法相互連接。如果不能夠穿越NAT,P2P網(wǎng)絡(luò )就無(wú)法實(shí)現真正的對等,也就無(wú)法實(shí)現所有信息的交換或共享。
當前處于NAT后的主機通信一般通過(guò)服務(wù)器的中轉,例如當客戶(hù)機A和客戶(hù)機B都分別處于不同的NAT后面,先各自發(fā)起一個(gè)TCP或UDP的連接,連接到一個(gè)大家都知道的擁有固定IP地址的服務(wù)器S上。由于A(yíng)和B不能直接連接,兩個(gè)客戶(hù)端就使用S服務(wù)器進(jìn)行消息的傳遞。例如,A要發(fā)送一條信息到客戶(hù)端B,客戶(hù)端A以C/S連接方式簡(jiǎn)單的發(fā)送一條信息到S服務(wù)器,然后S服務(wù)器使用已經(jīng)和客戶(hù)端B建立的C/S連接發(fā)送這條信息到客戶(hù)端B。NAT后主機不建立P2P通信時(shí)發(fā)送數據的具體過(guò)程如圖3.2所示。
這種方法的優(yōu)勢在于只要兩個(gè)客戶(hù)端都連在服務(wù)器上,它就是有效的。它的明顯缺點(diǎn)是它需要了服務(wù)器的處理并占用了帶寬,而且即使服務(wù)器的網(wǎng)絡(luò )狀況良好,也有一定的通訊滯后問(wèn)題。所以我們需要對該方案進(jìn)行改進(jìn),提出了NAT穿越技術(shù)。
圖3.2 NAT后主機不建立P2P通信時(shí)發(fā)送數據的具體過(guò)程
NAT穿越的主要目的是是讓處于NAT后的通信主機在建立連接后,可以繞過(guò)服務(wù)器的中轉,直接進(jìn)行P2P通信。這樣可以大大節省網(wǎng)絡(luò )帶寬,且數據傳輸更穩定,出現延時(shí)現象更少。
UDP是是無(wú)連接的協(xié)議,幾乎不提供可靠性措施,但是UDP的效率非常高。它與TCP協(xié)議不同,不需要在傳輸數據之前要建立一種虛擬的連接關(guān)系。所以UDP連接只要知道對方的IP地址和UDP端口,就可以進(jìn)行數據傳輸。
在P2P網(wǎng)絡(luò )中,采用UDP方式進(jìn)行數據傳輸,只有獲得對方主機的公網(wǎng)IP地址和端口才可以進(jìn)行數據交換。因此,需要在P2P網(wǎng)絡(luò )中設立一臺有公網(wǎng)IP地址的注冊服務(wù)器,任何主機都要先登錄到注冊服務(wù)器,注冊服務(wù)器將記錄這個(gè)IP地址和端口號為公網(wǎng)IP地址和UDP端口。這樣在注冊服務(wù)器上將建立一張映射表,這張映射表記錄了登錄到注冊服務(wù)器的主機在內網(wǎng)中的IP地址和端口號和經(jīng)過(guò)NAT之后NAT所分配的IP地址和端口號,即(內網(wǎng)IP地址:UDP端口號)-(公網(wǎng)IP地址:UDP端口號),如果主機不在NAT之后,則二者相同,這樣每臺登錄的主機都擁有Internet上唯一的(公網(wǎng)IP地址:UDP端口號)。
圖3.3 UDP穿越示意圖
當一臺主機要和另一臺主機進(jìn)行通信,它先從注冊服務(wù)器那里獲得目的主機的公網(wǎng)IP地址和端口號,而后就可以直接進(jìn)行通信,實(shí)際的數據交換不需要注冊服務(wù)器參與,從而實(shí)現了P2P穿越NAT。
當主機A1和B1位于不同的NAT之后,它們用UDP穿越NAT建立直接通信如圖3.3所示,具體的過(guò)程如下:
(1)A1和B1先登錄到公網(wǎng)注冊服務(wù)器,并向服務(wù)器發(fā)送各自的實(shí)際IP地址和UDP端口信息。
(2)注冊服務(wù)器記錄為兩個(gè)公網(wǎng)IP地址和端口號,同時(shí)從接收到的UDP數據報頭中提取IP地址和端口信息,記錄為內網(wǎng)IP地址和端口號,這樣在注冊服務(wù)器上的映射表中就增加兩條記錄,分別為:A1:(192.168.1.2:2000)一(10.10.10.10:2000)、B1:(192.168.2.2:4000) 一(20.20.20.20:4000)。
(3)從注冊服務(wù)器的映射表可以知道A1和B1位于不同的NAT之后。A1要向B1發(fā)送UDP消息那么A1發(fā)送命令給Server,請求Server命令B1向A1方向打洞, Server在發(fā)送打洞命令時(shí)同時(shí)將Client A的公網(wǎng)地址10.10.10.10:2000發(fā)送給B1(20.20.20.20:4000)。B1收到命令后向A1的公網(wǎng)地址10.10.10.10:2000發(fā)送信息,雖然NAT A會(huì )將這個(gè)信息丟棄(因為這樣的信息是不請自來(lái)的,為了安全,大多數NAT都會(huì )執行丟棄動(dòng)作)。但是我們已經(jīng)在NAT B上打一個(gè)方向為20.20.20.20:4000(即 A1的外網(wǎng)地址)的洞,那么A1發(fā)送到20.20.20.20:4000的信息, B1就能收到了。然后 A1就可以通過(guò)B1的外網(wǎng)地址與B1進(jìn)行P2P通信了。
(4)至此,兩個(gè)不同NAT之后的主機A1和B1穿越NAT之后,實(shí)現了P2P的信息直連。
對于UDP穿越NAT,現在已經(jīng)有了一些比較標準而且有效的方法,如STUN協(xié)議。但目前尚未能完全解決TCP穿越NAT的問(wèn)題,即便有一些方法,但也處于測試階段。在此介紹一下當前一種TCP穿越實(shí)現方法,其原理是呼叫雙方處于不同的NAT后,處于NAT后的主機先與公網(wǎng)上的注冊服務(wù)器建立輔助連接( TCP、UDP均可) ,在呼叫發(fā)生時(shí),通過(guò)注冊服務(wù)器的協(xié)助在呼叫雙方間建立TCP直連。
對于cone類(lèi)型的NAT可采用圖3.4所示的方法解決TCP穿越問(wèn)題,主要過(guò)程可分為建立輔助連接、查詢(xún)被叫、TCP打孔、建立TCP直連4個(gè)部分。
3.1 建立輔助連接
各會(huì )話(huà)用戶(hù)先與注冊服務(wù)器建立UDP連接(以下稱(chēng)為輔助通道)并一直在該連接通道上發(fā)送UDP數據包以保持自己處于激活狀態(tài),服務(wù)器記錄各用戶(hù)的ID (ID是用戶(hù)的唯一標識符)。
圖3.4 “TCP打孔”方法穿越NAT過(guò)程
(注:圖中圓括號內為消息內容,方括號內為消息路徑。如連接通知(C: V)UDP[ C: R >NB: Q >B: P ]表示該消息內容為服務(wù)器地址、端口(C: V) ,消息從IP地址C端口R出發(fā)經(jīng)過(guò)IP地址NB端口Q到達IP地址B端口P。)
3.2 查詢(xún)被叫
(1)主叫A與呼叫服務(wù)器C建立TCP連接,并向服務(wù)器發(fā)送被叫ID,請求服務(wù)器協(xié)助查詢(xún)被叫IP地址、端口。服務(wù)器記錄主叫在經(jīng)NAT映射前后的IP地址、端口(NA:N)以及本次連接使用的端口V。該請求在建立TCP直連的步驟3中得到回復。
(2)呼叫服務(wù)器通過(guò)已經(jīng)建立的輔助通道向被叫發(fā)送連接通知,其中攜帶與主叫建立TCP連接使用的IP地址、端口(C:V),即通知被叫向該地址、端口回送消息。
(3)被叫向連接服務(wù)器回復連接請求,建立TCP連接,服務(wù)器記錄被叫在經(jīng)NAT映射前后的IP地址、端口(NB:Y)。
3.3 TCP打孔
(1)連接服務(wù)器向被叫返回連接的詳細信息,如主叫ID及主叫經(jīng)過(guò)NAT映射后的IP地址、端口(NA:N) ,并關(guān)閉與被叫的TCP連接;
(2)被叫嘗試向主叫的經(jīng)過(guò)NAT映射后的IP地址、端口(NA:N)發(fā)送建立TCP連接的請求。
(3)根據前述的NAT類(lèi)型,此處可能有2種情況: 1) FullCone方式下,NATA會(huì )將該TCP消息轉發(fā)到內網(wǎng)內的主叫端口M,由于主叫A 已經(jīng)使用該端口與連接服務(wù)器建立TCP連接,故主叫A會(huì )返回一個(gè)端口已占用消息; 2)Restricted Cone 或Port Restricted Cone方式下,NAT A不會(huì )轉發(fā)該消息給主叫, 而是返回一條出錯消息給被叫。如果NAT B收到該出錯消息后,將其轉發(fā)給內網(wǎng)內的被叫B,則該TCP連接終止, TCP打孔失敗。但絕大多數情況下,NATB不會(huì )將上述2種出錯消息轉發(fā)內網(wǎng)內的主機,從而完成TCP打孔。
3.4 建立TCP直連
(1)被叫B在端口X啟動(dòng)TCP監聽(tīng),并使用與上述不同的端口G與服務(wù)器建立TCP連接,以及通知服務(wù)器被叫已完成TCP打孔和做好TCP直連準備。
(2)服務(wù)器向主叫A 發(fā)送被叫(B:X) 經(jīng)NAT映射后的IP地址、端口(NB:Y),并關(guān)閉和主叫建立的TCP連接。
(3)主叫(A:M)向上述IP地址、端口(NB:Y)發(fā)送TCP連接請求,即可與被叫B成功建立TCP直連。
對于cone 類(lèi)型NAT,由于每次會(huì )話(huà)其端口是固定的,客戶(hù)機可以通過(guò)注冊服務(wù)器間接獲取其公網(wǎng)的映射IP和端口,從而可以建立連接。而對于Symmetric類(lèi)型NAT,當主機B向主機A打洞時(shí)的其會(huì )話(huà)端口已經(jīng)重新分配了,主機 B將無(wú)法知道這個(gè)端口,客戶(hù)機之間就無(wú)法建立連接。
由于Symmetric NAT映射新的端口的方式主要有三種:一是在前一次映射的端口號上加1(或增加一個(gè)固定的整數T,T>1);二是在前一次映射的端口號上增加或減少,且變化的數值隨機在一個(gè)小范圍內生成;三是在區間 (1024,65535) 隨機生成。其中第一種映射方式最為常見(jiàn),然后依次是第二和第三種的。如果可以猜測UDP端口,則建立連接的可能性就可以實(shí)現。
當前有研究人員提出一種基于端口映射方式有規律性的準隨機猜測方法來(lái)猜測UDP端口,該算法設計首先要判斷目標方NAT的映射方式,讓發(fā)起訪(fǎng)問(wèn)的客戶(hù)端(比如 A)向服務(wù)器 S查詢(xún)最近3次注冊的、相繼被映射成和目標客戶(hù)端(比如B)同一全局地址(比如202.1.1.1)的B方客戶(hù)端的端口號,若其值遞增且最后一次注冊的客戶(hù)端的端口號(記為P0)最大,則【判定1】Symmetric NAT最有可能是第一種映射方式,亦有可能是第二或第三種映射方式;如果最近一次注冊的端口號不是最大,則【判定2】Symmetric NAT一定是第二或第三種映射方式。一種極端情況,當前B方內網(wǎng)主機包括B在內向S注冊的映射為地址202.1.1.1的共不到3臺,若只有B注冊,則當成【判定1】的情形處理;若有2臺注冊,仍按后一次映射的端口號是否更大而判斷其映射方式。
在對端口測試過(guò)程中,需要對端口猜中與否的判斷:假設A和B相互發(fā)送報文時(shí),NAT映射后各自的全局插口為[IPa:Pa]和[IPb:Pb]。若A發(fā)送的猜詢(xún)報文目標端口變?yōu)镻b,即先猜中了B的端口,B的NAT仍會(huì )丟棄A的這個(gè)報文。但這時(shí)在A(yíng)方建立了會(huì )話(huà)[IPa:Pa , IPb:Pb];在此會(huì )話(huà)的生存期內,若B也猜中了A的端口Pa,則B的猜詢(xún)報文就能發(fā)送到A并收到A的響應報文,A則收到B的猜詢(xún)報文。即任意一方收到猜詢(xún)報文或響應報文就表明雙方都已猜中對方端口。若A 先猜中B的端口,而在該會(huì )話(huà)的生存期內B沒(méi)有猜中A的,則A并不知道自己已經(jīng)猜中故會(huì )繼續對B發(fā)送猜詢(xún)報文。
對于對稱(chēng)式NAT,需要先經(jīng)過(guò)地址探測技術(shù)的協(xié)助來(lái)完成穿越[22] 。近期研究表明,市場(chǎng)上對稱(chēng)式NAT應用很少,而且NAT由于意識到其對端到端通信會(huì )帶來(lái)較大障礙,因此正在力圖減少使用對稱(chēng)式的映射方式??紤]到當前應用的NAT絕大多數都是Cone類(lèi)型的,這滿(mǎn)足后期雙向透明轉換模塊的產(chǎn)品化的市場(chǎng)化需要,所以選擇了Cone類(lèi)型的NAT作為穿越目標。當前UDP穿越NAT技術(shù)已經(jīng)比較成熟,并有了標準,而TCP穿越NAT雖然有成功實(shí)驗的,但相對來(lái)說(shuō)不穩定??紤]到本課題是基于應用目的,對系統要求穩定,同時(shí)由于網(wǎng)絡(luò )數據量也較小,UDP已經(jīng)可以滿(mǎn)足要求。通過(guò)比較,選用UDP穿越Cone類(lèi)型的NAT穿越實(shí)現處于NAT后的串口設備建立P2P通信功能。
UDP是無(wú)連接的協(xié)議,NAT對UDP傳輸的映射是動(dòng)態(tài)的,也就是說(shuō)經(jīng)過(guò)一段時(shí)間之后,如果NAT后的內網(wǎng)主機不再發(fā)送或接收數據,映射后的IP地址和端口號會(huì )發(fā)生改變,映射關(guān)系會(huì )自動(dòng)解除,分配的UDP端口號會(huì )被NAT收回,重新分配給其他連接。這樣在注冊服務(wù)器上的映射表就會(huì )變得無(wú)效,主機也就不能為其他主機所識別,所以必須保持NAT的映射關(guān)系不會(huì )動(dòng)態(tài)改變。
為了保持NAT對UDP的映射不變,NAT后的主機可以定時(shí)向NAT發(fā)送保持映射的UDP消息,保證NAT為相應主機分配的UDP端口不被收回。發(fā)送的目的地址是該主機登錄注冊服務(wù)器時(shí),NAT為它分配的Internet合法IP地址和相應的UDP端口。由于UDP的無(wú)連接性,任何主機發(fā)送到該Internet合法IP地址和UDP端口的消息,經(jīng)過(guò)NAT后消息都將被相應的內網(wǎng)主機所接收到,所以此時(shí)相當于主機本身向自己發(fā)送了一條UDP消息,主機接收到這樣的消息后直接丟棄,這樣映射關(guān)系就能夠保持。
在完成UDP穿越過(guò)程中,心跳包的是設計一個(gè)必不可少的環(huán)節。按照理論,NAT將在一定時(shí)間后關(guān)閉UDP的一個(gè)映射,所以為了保持與對方能夠一直通信,主機必須要發(fā)送UDP心跳包,來(lái)保持映射不被關(guān)閉。心跳包內容可以自己定,也可以是個(gè)空數據包。在本設計中使用了二個(gè)定時(shí)器來(lái)完成發(fā)送心跳包,初始化時(shí)關(guān)閉第二個(gè)定時(shí)器,第一個(gè)定時(shí)器負責向服務(wù)器發(fā)送心跳包,維持與服務(wù)器的連接;在收到打洞命令后,關(guān)閉第一個(gè)定時(shí)器,停止向服務(wù)器發(fā)送心跳包,使能第二個(gè)定時(shí)器,由它負責向P2P的對方主機發(fā)送心跳包。
心跳包的發(fā)送間隔時(shí)間也需要注意,間隔時(shí)間太長(cháng),映射關(guān)系將被關(guān)閉,不能起到心跳包的作用。間隔時(shí)間太短,發(fā)送數據太多將占用大量的網(wǎng)絡(luò )帶寬,同時(shí)浪費資源。在本設計中,經(jīng)過(guò)大量測試,心跳包的發(fā)送間隔時(shí)間為20秒較為合適。
聯(lián)系客服