穿越NAT的意義: NAT是爲了節省IP地址而設計的,但它隱藏了內網機器的地址,「意外」起到了安全的做用。對外不可見,不透明的內部網絡也與互聯網的「公平」應用,「相互共享」的思想所不容,尤爲是P2P網絡中「相互服務」的宗旨,因此穿越NAT,讓衆多內部網絡的機器也參與到P2P網絡中的大集體中來,一直是P2P開發者的所但願的。穿越NAT須要藉助外部的支持,說白了就是「內外勾結」,騙過NAT。不少P2P網絡成功地實現了這一目標,但仍是有一些「遺憾」---並不是全部的狀況下均可以。因爲客戶端是主動登陸P2P網絡纔可穿越,因此P2P的方式也沒有違背企業的內部管理原則,畢竟「自由世界」的加入都是自覺自願的。 NAT原理: NAT(Network Address Translation)網絡地址轉換/網絡地址翻譯。 工做原理:NAT主要的經過對數據包頭的地址替換來完成內網計算機訪問外網服務的。當內部機器要訪問外部網絡時,NAT設備把內部的IP1與端口號1(網絡層地址與傳輸層地址),轉換成NAT的外部IP2與新的端口號2,再送給外部網絡,數據返回時,再把目的爲IP2:端口2的數據包替換爲IP1:端口1,送給內網機器。若通信協議的內容中有IP地址的傳遞,如FTP協議,NAT在翻譯時還要注意數據包內涉及協議地址交互的地方也要替換,不然協議就會出現地址混亂。在NAT設備中維護了這個要替換地址的映射表,並根據內部計算機的通信需求維護該表。外部網絡來數據包可否進入NAT,主要是看是否已經有可映射的表項,若沒有就會丟棄。 NAT的外部公網地址能夠是一個IP,也能夠是一個網段,造成地址池。NAT還能夠把某個外網地址直接影射給內網的某個服務器,讓外網的用戶能夠直接訪問到這臺服務器。NAT的工做的隱藏內網的機器,但容許內網主動打開到外網的通信「通道」,也就是創建映射表項。 NAT給P2P帶來的問題是:NAT只容許單方面發起鏈接,通信的雙方不是平等的,P2P網絡的基礎有了問題,具體的表現爲: 內網主機IP是私有的,外部主機看不到,也沒法主動發起鏈接 即便知道了內網IP,但NAT會丟棄沒有在影射表的數據包 內網主機能夠做爲客戶端訪問外網,但不能做爲服務器提供服務 當兩個主機都位於各自的NAT以後,要實現P2P的鏈接,就不只是誰主動的問題,而是如何解決在兩個NAT上同時有對方映射表項的問題。 STUN協議(IETF RFC 3489): STUN協議是一種通道協議,能夠做爲正式通信前的通路創建,它採用的是用戶終端干預的一種方法,能夠解決應用協議內部傳遞IP地址給NAT帶來的麻煩。用戶經過其餘方法獲得其地址對應在NAT出口上的對外地址,而後在報文負載中所描述的地址信息就直接填寫NAT上對外地址,而不是內網的私有IP,這樣報文的內容在通過NAT時就按普通的NAT流程轉換報文頭部的IP地址便可,負載內的IP地址信息無需再修改。利用STUN的思路能夠穿越NAT。STUN協議是客戶端/服務器協議,分兩種請求方式:一是UDP發送的綁定請求(Binding Requests),二是TCP發送的祕密請求(Shared Secret Requests)。綁定請求用於肯定NAT分配的綁定地址。 STUN標準中,根據內部終端的地址(P:p)到NAT出口的公網地址(A:b)的影射方式,把NAT分爲四種類型: 1. Full Cone:來自相同的內部地址的請求消息映射爲相同的外部地址,與外部地址(目的地址)無關。映射關係爲P:p↔A:b,任何外部主機可經過(A:b)發送到數據到(P:p)上。 2. Restricted Cone:來自相同的內部地址的請求消息映射爲相同的外部地址,返回的數據只接受該內部節點曾發數據的那個目的計算機地址X。映射關係爲P:p↔A:b↔X,只有來自X的數據包纔可經過(A:b)發送到數據到(P:p)上。 3. Port Restricted Cone:來自相同的內部地址的請求消息映射爲相同的外部地址,返回的數據只接受該內部節點曾發數據的那個目的地址X:x。映射關係爲P:p↔A:b↔X:x,只有來自X:x的數據包纔可經過(A:b)發送到數據到(P:p)上。 4. Symmetric(對稱) NAT:只有來自相同的內部地址(P:p),而且發送到同一個地址(X:x) 的請求消息,才被映射爲相同的外部地址(A:b),返回的數據只接受該內部節點曾發數據的那個目的地址X:x。映射關係爲P:p↔A:b↔X:x,當(P:p)訪問(Y:y)時,映射爲P:p↔B:c↔Y:y。 P2P利用STUN穿越NAT: 位於NAT後面終端A與B要穿越NAT直接通信,能夠藉助在公網上的第三者Server來幫助。 穿越NAT的狀況分爲爲兩種方式: 一、一方在NAT以後,一方在公網上。這種狀況相對簡單,只要讓NAT以後的終端先發起通信,NAT就沒有做用了,它能夠從Server上取得另外一個Peer的地址,主動鏈接,回來的數據包就能夠方便地穿越NAT。 二、雙方都在NAT以後,鏈接的成功與否與兩個NAT的類型有關。主要的思路的先經過終端與Server的鏈接,得到兩個終端在NAT外部的地址(IP與端口號),再由終端向對方的外部地址發邀請包,獲取本身與對方通信的外部地址,俗稱爲「打洞」。關鍵是獲取了NAT外部映射的地址,就能夠發包直接溝通,創建鏈接。但當一方是對稱型,另外一方是Port Restricted或對稱型時,沒法有效獲取外部地址,邀請包沒法到達對方,也就沒法穿越NAT。具體的分析能夠根據兩個NAT的類型分紅若干狀況分析,這裏給通常的穿越例子。 實例:UDP穿越NAT: A登陸Server,NAT A分配端口11000,Server獲得A的地址爲100.10.10.10:11000 B登陸Server,NAT B分配端口22000,Server獲得B的地址爲200.20.20.20:22000 此時B會把直接來自A的包丟棄,因此要在NAT B上打一個方向爲A的洞,那麼A就能夠向200.20.20.20:22000發送數據了 打洞的指令來自Server。B向A的地址100.10.10.10:11000發一個UDP報文,被NAT A丟棄,但在NAT B上創建映射記錄,NAT B不在丟棄來自A的報文。 Server通知A能夠通信,A發起數據UDP包給B,NAT B放行,B收到A的包,雙方開始通信 注:如果對稱NAT,當B向A打洞的端口要從新分配(NAT A不會再分配11000端口),B沒法獲取這個端口,因此不適用本方法。 實例:TCP穿越NAT: A登陸Server,NAT A分配端口11000,Server獲得A的地址爲100.10.10.10:11000 B登陸Server,NAT B分配端口22000,Server獲得B的地址爲200.20.20.20:22000 A向B發送TCP數據包SYN:192.168.10.11:1234=>200.20.20.20:22000,在NAT A上打洞 B向A發送TCP數據包SYN:192.168.20.22:1234=>100.10.10.10:11000,在NAT B上打洞 通道創建,A與B三次握手創建TCP鏈接