udp協議怎麼穿透Symmetric NAT?
如題:
udp打洞時,如果兩台處於內網的電腦,至少有一台處於內網,屬於對稱結構(Symmetric),那麼怎麼為他們點對點建立通道?
除了猜測連接外網的埠(比如有的會是剛用過埠的下幾個埠),還有其他辦法嗎?相關內容參考:
http://blog.csdn.net/jq0123/article/details/840302
NAT大致分為下面四類
1) Full Cone
這種NAT內部的機器A連接過外網機器C後,NAT會打開一個埠.然後外網的任何發到這個打開的埠的UDP數據報都可以到達A.不管是不是C發過來的.
例如 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)2) Restricted Cone
這種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)3) Port Restricted Cone
這種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通稱Cone NAT.我們只能用這種NAT進行UDP打洞.4) Symmetic
對於這種NAT.連接不同的外部目標.原來NAT打開的埠會變化.而Cone NAT不會.雖然可以用埠猜測.但是成功的概率很小.因此放棄這種NAT的UDP打洞.
正好,我們已經對UDP打洞問題研究了近一個月,對於兩方都是對稱nat的情況,至少從可以了解的途徑上(比如google,相關論壇)都沒找到解決方案,我們自己也進行過測試,不行。
但是對於一端是對稱nat,一端是埠限制性Cone nat的情況是可以打洞成功的,特別是我們實驗的對稱nat的埠變化還是有規律的(加1),我們使用埠猜測的方法進行打洞成功率還是非常高的。對於埠變化無規律的對稱nat,這個猜測還是靠演算法的設計,你可以看看
A New Method for Symmetric NAT Traversal in UDP and TCP (http://www.goto.info.waseda.ac.jp/~wei/file/wei-apan-v10.pdf)
把4種類型分別標為1234,有兩台主機A:portA和B:portB(port都為外網埠,是與打洞伺服器通信的埠),以及打洞伺服器S,情景是B拿到了A:portA的信息,要與A通信。
(1)、A為類型1;無論B為哪種類型,都可以直接與A:portA tcp連接;
(2)、A為類型2;無論B為哪種類型,在A知道B之前都無法直接連接,B給S發一個打洞請求,S轉發該請求到A。若B的類型為1,則A:portA可直接tcp連接到B:portB;若B的類型為2或3,則A:portA和B:portB各自向對方發送一個一位元組的udp包,分別在自己的路由器上打洞,從此A:portA和B:portB可進行udp通信;若B為類型4,則portB在與不同的ip:port通信時會不一樣,所以A:portA先向B發送一個一位元組的udp包,在路由器上打洞,然後等待B:portB先發送數據,A:portA接收到B:portB的數據後,即知道portB,也可互通數據了;
(3)、A為類型3;無論B為哪種類型,在A知道B之前都無法直接連接,B給S發一個打洞請求,S轉發該請求到A。若B的類型為1,則A:portA可直接tcp連接到B:portB;若B的類型為2或3,則A:portA和B:portB各自向對方發送一個一位元組的udp包,分別在自己的路由器上打下洞,從此A:portA和B:portB可進行udp通信;若B為類型4,則portB在與不同的ip:port通信時會不一樣,而A又要求知道portB的才可讓B:portB連進來,所以這種情況A只能猜測與A:portA通信的portB,通信概率小;
(4)、A為類型4;無論B為哪種類型,在A知道B之前都無法直接連接,B給S發一個打洞請求,S轉發該請求到A。若B的類型為1,則A:portA可直接tcp連接到B:portB;若B的類型為2,則B:portB先向A發送一個一位元組的udp包,在路由器上打洞,然後等待A:portA先發送數據,B:portB接收到A:portA的數據後,即知道portA,也可互通數據了;若B的類型為3,見(3)中B為類型4的描述;若B為4,雙方無法知道對方的埠,無法通信。
ps:純手打,根據工作中的理解整理。關於UDP/TCP打洞的原理可以參考這篇paper:
USENIX "05 ? Technical Paper, General Track
最近也在研究P2P網路中的NAT穿透,看到有說用ICE(STUN+TURN)的方式基本上可以解決所有的NAT問題,僅供參考:
STUN :RFC 5389 - Session Traversal Utilities for (NAT) (STUN)
ICE:RFC 5245 - Interactive Connectivity Establishment (ICE): A Methodology for Network Address Translator (NAT) Traversal for Offer/Answer Protocols
要做到高成功率,還是需要有伺服器進行配合,你可以參考一下webrtc的p2p連接建立的過程
不知道你要做的是怎麼樣一個應用。。。
是不是一定要自動打洞?
能否讓用戶自己配置埠映射或者用UPNP?如某些P2P下載工具,能實現這一條的用戶可獲得更多資源(多了內網資源),而無法實現者只能分享外網資源。
請參考我於 http://www.zhihu.com/question/20034397 回答的問題:
對於您的問題補充:
- STUN不能解決Symmetric NAT的問題
- 用TURN也就是Relay Server的話,就要求提前兩個要聊天的host都彼此於這個server上留下了一個開開的port,但是這個就會增加management的複雜度,以及用中間電腦來傳輸的話,速度也會受影響。
如果兩台處於內網的電腦,至少有一台處於內網
這句看的混身難受
我研究這個問題研究了很久無解,目前只能通過挖洞,建立反向隧道暫時頂一下。
PS:有篇論文叫做pwnat,如果上級路由沒有屏蔽icmp,那麼可以不用第三方伺服器。
Symmetric需要猜測的
請借鑒
去中心化的網路設計 ― P2P的實現 - 自強不息 厚德載物 - 51CTO技術博客
大姚介紹的對稱 NAT 的穿透方法,我找到了具體實現的源碼。
看了下源碼,就是用了埠預測還有生日攻擊演算法。
https://github.com/jflyup/nat_traversal
我下載後進行了測試,但源碼只實現了兩個對稱 nat 之間的打洞。
而我的環境,一個是 symmetric NAT,另外一個是 port-restricted cone。用以上的代碼測試沒有成功。
看哪位大牛再能修改完善下,再做成一個庫,那就完美了
美國有家公司號稱能做到成功率95%以上,埠預測用的是生日攻擊演算法
本人已實測成功,生日攻擊演算法確實可以解決對稱型與埠限制型之間的穿透,而且可以達到100%,現在就剩對稱型與對稱型之間沒想到好辦法。
打洞的一方 Peer 向 Symmetric NAT 網路後端的 Peer,及另外一個外網 Server,依次、連續發出 3 包數據,就有可能看到與 Symmetric NAT 打洞的【IP:Port】
推薦閱讀:
※黑馬程序員有傳說中的那麼好嗎?
※為什麼計算機網路話題的關注數明顯不如編程類?
※「部隊里的通信兵的編程能力能爆市面上的大多數程序員」是真的嗎?
※GitHub 或者其他的開源平台中是否有一些適合初學者的 C++ 項目?
※如何用c操作圖片?
TAG:編程 | P2P | UDP | 計算機網路 | 計算機科學 | 網路傳輸協議 | 網路編程 | TCPIP | 對等網路P2P |