內(nèi)網(wǎng)穿透即NAT穿透,網(wǎng)絡連接時術語,計算機是局域網(wǎng)內(nèi)時,外網(wǎng)與內(nèi)網(wǎng)的計算機節(jié)點需要連接通信,有時就會出現(xiàn)不支持內(nèi)網(wǎng)穿透。
創(chuàng)新互聯(lián)建站專注于企業(yè)營銷型網(wǎng)站、網(wǎng)站重做改版、港北網(wǎng)站定制設計、自適應品牌網(wǎng)站建設、HTML5建站、商城開發(fā)、集團公司官網(wǎng)建設、外貿(mào)網(wǎng)站制作、高端網(wǎng)站制作、響應式網(wǎng)頁設計等建站業(yè)務,價格優(yōu)惠性價比高,為港北等各大城市提供網(wǎng)站開發(fā)制作服務。
就是說映射端口,能讓外網(wǎng)的電腦找到處于內(nèi)網(wǎng)的電腦,提高下載速度。
不管是內(nèi)網(wǎng)穿透還是其他類型的網(wǎng)絡穿透,都是網(wǎng)絡穿透的統(tǒng)一方法來研究和解決。在百科詞條
NAT穿越,nat穿透中有關于網(wǎng)絡穿透的詳細信息。
NAT,即NAT Traversal,可譯為網(wǎng)絡地址轉換或網(wǎng)絡地址翻譯。
NAT英文全稱是“Network Address Translation”,中文意思是“網(wǎng)絡地址轉換”,它是一個IETF(Internet Engineering Task Force, Internet工程任務組)標準,允許一個整體機構以一個公用IP(Internet Protocol)地址出現(xiàn)在Internet上。顧名思義,它是一種把內(nèi)部私有網(wǎng)絡地址(IP地址)翻譯成合法網(wǎng)絡IP地址的技術。
簡單的說,NAT就是在局域網(wǎng)內(nèi)部網(wǎng)絡中使用內(nèi)部地址,而當內(nèi)部節(jié)點要與外部網(wǎng)絡進行通訊時,就在網(wǎng)關(可以理解為出口,打個比方就像院子的門一樣)處,將內(nèi)部地址替換成公用地址,從而在外部公網(wǎng)(internet)上正常使用,NAT可以使多臺計算機共享Internet連接,這一功能很好地解決了公共IP地址緊缺的問題。通過這種方法,您可以只申請一個合法IP地址,就把整個局域網(wǎng)中的計算機接入Internet中。這時,NAT屏蔽了內(nèi)部網(wǎng)絡,所有內(nèi)部網(wǎng)計算機對于公共網(wǎng)絡來說是不可見的,而內(nèi)部網(wǎng)計算機用戶通常不會意識到NAT的存在。
nat穿透:在處于使用了NAT設備的私有TCP/IP網(wǎng)絡中的主機之間建立連接
內(nèi)網(wǎng)穿透即是使用公網(wǎng)服務器作為代理,轉發(fā)內(nèi)網(wǎng)(如辦公室、家里)的網(wǎng)絡請求使其能夠在外網(wǎng)中被訪問到。
server端監(jiān)聽兩個端口,一個用來和接收用戶的http請求,一個監(jiān)聽gRPC客戶端,和內(nèi)網(wǎng)服務器進行通信;
client啟動時連接server端;
當User請求server http端口時,將http進行阻塞,并將User請求內(nèi)容通過gRPC發(fā)給client;
client將從server收到的請求發(fā)往本地的http服務;
client將從本地程序收到的http response通過gRPC發(fā)送給server;
server結束http阻塞,將從client收到的http response發(fā)給User。
github地址:
原文鏈接:
一、什么是NAT?為什么要使用NAT?
NAT是將私有地址轉換為合法IP地址的技術,通俗的講就是將內(nèi)網(wǎng)與內(nèi)網(wǎng)通信時怎么將內(nèi)網(wǎng)私有IP地址轉換為可在網(wǎng)絡中傳播的合法IP地址。NAT的出現(xiàn)完美地解決了lP地址不足的問題,而且還能夠有效地避免來自網(wǎng)絡外部的攻擊,隱藏并保護網(wǎng)絡內(nèi)部的計算機。
二、NAT的分類
STUN標準中,根據(jù)內(nèi)部終端的地址(LocalIP:LocalPort)到NAT出口的公網(wǎng)地址(PublicIP:PublicPort)的影射方式,把NAT分為四種類型:
1、Full Cone NAT: 內(nèi)網(wǎng)主機建立一個socket(LocalIP:LocalPort) 第一次使用這個socket給外部主機發(fā)送數(shù)據(jù)時NAT會給其分配一個公網(wǎng)(PublicIP:PublicPort),以后用這個socket向外面任何主機發(fā)送數(shù)據(jù)都將使用這對(PublicIP:PublicPort)。此外,任何外部主機只要知道這個(PublicIP:PublicPort)就可以發(fā)送數(shù)據(jù)給(PublicIP:PublicPort),內(nèi)網(wǎng)的主機就能收到這個數(shù)據(jù)包。
2、Restricted Cone NAT: 內(nèi)網(wǎng)主機建立一個socket(LocalIP:LocalPort) 第一次使用這個socket給外部主機發(fā)送數(shù)據(jù)時NAT會給其分配一個公網(wǎng)(PublicIP:PublicPort),以后用這個socket向外面任何主機發(fā)送數(shù)據(jù)都將使用這對(PublicIP:PublicPort)。此外,如果任何外部主機想要發(fā)送數(shù)據(jù)給這個內(nèi)網(wǎng)主機,只要知道這個(PublicIP:PublicPort)并且內(nèi)網(wǎng)主機之前用這個socket曾向這個外部主機IP發(fā)送過數(shù)據(jù)。只要滿足這兩個條件,這個外部主機就可以用自己的(IP,任何端口)發(fā)送數(shù)據(jù)給(PublicIP:PublicPort),內(nèi)網(wǎng)的主機就能收到這個數(shù)據(jù)包。
3、Port Restricted Cone NAT: 內(nèi)網(wǎng)主機建立一個socket(LocalIP:LocalPort) 第一次使用這個socket給外部主機發(fā)送數(shù)據(jù)時NAT會給其分配一個公網(wǎng)(PublicIP:PublicPort),以后用這個socket向外面任何主機發(fā)送數(shù)據(jù)都將使用這對(PublicIP:PublicPort)。此外,如果任何外部主機想要發(fā)送數(shù)據(jù)給這個內(nèi)網(wǎng)主機,只要知道這個(PublicIP:PublicPort)并且內(nèi)網(wǎng)主機之前用這個socket曾向這個外部主機(IP,Port)發(fā)送過數(shù)據(jù)。只要滿足這兩個條件,這個外部主機就可以用自己的(IP,Port)發(fā)送數(shù)據(jù)給(PublicIP:PublicPort),內(nèi)網(wǎng)的主機就能收到這個數(shù)據(jù)包。
4、Symmetric NAT: 內(nèi)網(wǎng)主機建立一個socket(LocalIP,LocalPort),當用這個socket第一次發(fā)數(shù)據(jù)給外部主機1時,NAT為其映射一個(PublicIP-1,Port-1),以后內(nèi)網(wǎng)主機發(fā)送給外部主機1的所有數(shù)據(jù)都是用這個(PublicIP-1,Port-1),如果內(nèi)網(wǎng)主機同時用這個socket給外部主機2發(fā)送數(shù)據(jù),NAT會為其分配一個(PublicIP-2,Port-2), 以后內(nèi)網(wǎng)主機發(fā)送給外部主機2的所有數(shù)據(jù)都是用這個(PublicIP-2,Port-2).如果NAT有多于一個公網(wǎng)IP,則PublicIP-1和PublicIP-2可能不同,如果NAT只有一個公網(wǎng)IP,則Port-1和Port-2肯定不同,也就是說一定不能是PublicIP-1等于 PublicIP-2且Port-1等于Port-2。此外,如果任何外部主機想要發(fā)送數(shù)據(jù)給這個內(nèi)網(wǎng)主機,那么它首先應該收到內(nèi)網(wǎng)主機發(fā)給他的數(shù)據(jù),然后才能往回發(fā)送,否則即使他知道內(nèi)網(wǎng)主機的一個(PublicIP,Port)也不能發(fā)送數(shù)據(jù)給內(nèi)網(wǎng)主機,這種NAT無法實現(xiàn)P2P通信,但是如果另一方是Full Cone NAT,還是可以實現(xiàn)穿透的,下面我會詳細分析各種類型NAT穿透的情況。
NAT 功能通常被集成到路由器、防火墻、ISDN路由器或者單獨的NAT設備中。所以我們大家很少會知道NAT,上面NAT類型的概念描述是比較通俗的,但為了更便于理解,我再舉例闡述一下NAT的原理。
現(xiàn)有通信的雙方A和B,當A和B都是在公網(wǎng)的時候,通信是不用NAT的。假設A在內(nèi)網(wǎng),內(nèi)網(wǎng)IP是192.168.1.3,端口號是5000,A經(jīng)過NAT后的IP是221.221.221.100,端口號是8000,B的IP是202.105.124.100,端口是8500。如果B要去主動連接A,即使B知道A經(jīng)過NAT后的IP和端口也是無法連接成功的,因為A沒有向B(202.105.124.100:8500)發(fā)送過數(shù)據(jù),所以B的數(shù)據(jù)包會被A的NAT丟棄,于是連接失敗。但是A如果去主動連接B,由于B是在公網(wǎng),所以會連接成功,通信也就會建立。這也就是反彈連接木馬“反彈”二字的精髓。
當客戶端A和B都是處在內(nèi)網(wǎng)的時候,雙方由于都不知道對方的公網(wǎng)IP和端口,就會無從下手,所以要在客戶端A和B之間架設一臺服務器S來為它們牽線,而且S是處在公網(wǎng),以保證A和B都能連接到S??蛻舳薃和B登錄時都首先連接S,S就會知道A和B經(jīng)過NAT后的IP和端口,當A想要連接B時,就像S發(fā)出請求,S會把B經(jīng)過NAT后的IP和端口告訴A,同時S向B發(fā)送A經(jīng)過NAT后的IP和端口,并要求B發(fā)送數(shù)據(jù)給A,B發(fā)送數(shù)據(jù)到達A時會被A的NAT拋棄,但是B的NAT會有B發(fā)送數(shù)據(jù)到A的記錄,這是A再向B發(fā)送數(shù)據(jù)時就會被B的NAT放行,因為B曾經(jīng)向A的外網(wǎng)IP和端口發(fā)送過數(shù)據(jù)??赡苡悬c亂,下面以故事的形式敘述一下這個情景。
人物:A(男) NAT_A(A家接線員)? B(女) NAT_B? (B家接線員) S
場景介紹:A想認識B,但是不知道B的電話,S跟A、B都是朋友,并且知道A和B的電話。接線員的職責:對往外轉接的電話不做詢問,對往內(nèi)轉接的電話則要過濾以免有騷擾電話。過濾規(guī)則:在一定時間內(nèi)沒有撥打過的號碼就過濾。
首先A給S打電話:
A說:我想認識你朋友B,你把她電話給我唄。
S說:行,她的電話是PublicIP_B,我讓她先給你打個電話,要不她家接線員不幫你轉接。
A說:好。
S跟B打電話:
S說:我有一個朋友A,人挺好的,他想認識你,你給他打個電話,他的電話號碼是PublicIP_A。
B說:行,打完告訴你。
S說:好的。
B打電話到A家,B家接線員NET_B看到女主人想往PublicIP_A打電話就轉接到A家了,同時把號碼PublicIP_A記錄下來,A家接線員NAT_A一看號碼是個近期沒打過的號,就給掛斷了。
B給S打電話:
B說:我打完電話了
S說:好,等著吧,一會他就給你打進來了。
S給A打電話:
S說:他給你打完電話了,你快點給她打。
A打電話到B家, A家接線員NET_A看到男主人想往PublicIP_B打電話就轉接到B家了,B家接線員NET_B看到是剛剛撥過的PublicIP_A號碼打過來的,就轉接給B了,A和B的電話也就打通了。
A和B通話:
A說:電話終于打通了,想認識你挺困難的。
B說:是啊。
∶
∶
以上雖然和實際不太一樣,但穿透的整體過程基本就是這樣。A往B發(fā)送數(shù)據(jù)的唯一阻礙就是NET_B,所以想要成功發(fā)送數(shù)據(jù),必須把NET_B穿一個洞,A是無法完成這項工作的,所以就得讓B完成這個打洞操作,也就是讓B往A發(fā)送數(shù)據(jù),這樣NET_B就會誤以為A發(fā)送的數(shù)據(jù)是上次會話的一部分從而不予阻攔。
但是,由于NAT的類型沒有一個統(tǒng)一的標準,所以NAT穿透使用的技術有很多種,穿透的成功率也不一樣。還有些NAT類型的內(nèi)網(wǎng)之間幾乎無法穿透。下面我們用實例詳細分析一下各種NAT類型穿透的可行性。
A機器在私網(wǎng)(192.168.0.3)
A側NAT服務器(221.221.221.100)
B機器在另一個私網(wǎng)(192.168.0.5)
B側NAT服務器(210.30.224.70)
C機器在公網(wǎng)(210.202.14.36)作為A和B之間的中介
A機器連接C機器,假使是A(192.168.0.3:5000)- A側NAT(轉換后221.221.221.100:8000)- C(210.202.14.36:2000)
B機器也連接C機器,假使是B(192.168.0.5:5000)- B側NAT(轉換后210.30.224.70:8000)- C(210.202.14.36:2000)
A機器連接過C機器后,A向C報告了自己的內(nèi)部地址(192.168.0.3:5000),此時C不僅知道了A的外部地址(C通過自己看到的221.221.221.100:8000)也知道了A的內(nèi)部地址。同理C也知道了B的外部地址(210.30.224.70:8000)和? 內(nèi)部地址(192.168.0.5:5000)。之后,C作為中介,把A的兩個地址告訴了B,同時也把B的兩個地址告訴了A。
假設A先知道了B的兩個地址,則A從192.168.0.3:5000處同時向B的兩個地址192.168.0.5:5000和210.30.224.70:8000發(fā)包,由于A和B在兩個不同的NAT后面,故從A(192.168.0.3:5000)到B(192.168.0.5:5000)的包肯定不通,現(xiàn)在看A(192.168.0.3:5000)到B(210.30.224.70:8000)的包,分如下兩種情況:
1、B側NAT屬于Full? Cone? NAT
則無論A側NAT屬于Cone? NAT還是Symmetric? NAT,包都能順利到達B。如果程序設計得好,使得B主動到A的包也能借用A主動發(fā)起建立的通道的話,則即使A側NAT屬于Symmetric? NAT,B發(fā)出的包也能順利到達A。
結論1:只要單側NAT屬于Full? Cone? NAT,即可實現(xiàn)雙向通信。
2、B側NAT屬于Restricted? Cone或Port? Restricted? Cone
則包不能到達B。再細分兩種情況
(1)、A側NAT屬于Restricted? Cone或Port? Restricted? Cone
雖然先前那個初始包不曾到達B,但該發(fā)包過程已經(jīng)在A側NAT上留下了足夠的記錄:A(192.168.0.3:5000)-(221.221.221.100:8000)-B(210.30.224.70:8000)。如果在這個記錄沒有超時之前,B也重復和A一樣的動作,即向A(221.221.221.100:8000)發(fā)包,雖然A側NAT屬于Restricted? Cone或Port Restricted Cone,但先前A側NAT已經(jīng)認為A已經(jīng)向B(210.30.224.70:8000)發(fā)過包,故B向A(221.221.221.100:8000)發(fā)包能夠順利到達A。同理,此后A到B的包,也能順利到達。
結論2:只要兩側NAT都不屬于Symmetric? NAT,也可雙向通信。換種說法,只要兩側NAT都屬于Cone? NAT,即可雙向通信。
(2)、A側NAT屬于Symmetric? NAT
因為A側NAT屬于Symmetric? NAT,且最初A到C發(fā)包的過程在A側NAT留下了如下記錄:A(192.168.0.3:5000)-(221.221.221.100:8000)- C(210.202.14.36:2000),故A到B發(fā)包過程在A側NAT上留下的記錄為:
A(192.168.0.3:5000)-(221.221.221.100:8001)-B(210.30.224.70:8000)(注意,轉換后端口產(chǎn)生了變化)。而B向A的發(fā)包,只能根據(jù)C給他的關于A的信息,發(fā)往A(221.221.221.100:8000),因為A端口受限,故此路不通。再來看B側NAT,由于B也向A發(fā)過了包,且B側NAT屬于Restricted? Cone或Port? Restricted? Cone,故在B側NAT上留下的記錄為:B(192.168.0.5:5000)-(210.30.224.70:8000)-A(221.221.221.100:8000),此后,如果A還繼續(xù)向B發(fā)包的話(因為同一目標,故仍然使用前面的映射),如果B側NAT屬于Restricted? Cone,則從A(221.221.221.100:8001)來的包能夠順利到達B;如果B側NAT屬于Port? Restricted? Cone,則包永遠無法到達B。
結論3:一側NAT屬于Symmetric? NAT,另一側NAT屬于Restricted? Cone,也可雙向通信。
反過來想,則可以得出另一個結論:兩個都是Symmetric NAT或者一個是Symmetric? NAT、另一個是Port Restricted Cone,則不能雙向通信,因為NAT無法穿透。
上面的例子雖然只是分析了最初發(fā)包是從A到B的情況,但是,由于兩者的對稱性,前面得出的幾條結論沒有方向性,雙向都適用。
我們上面得出了四條結論,natcheck網(wǎng)站則把他歸結為一條:只要兩側NAT都屬于Cone? NAT(含F(xiàn)ull? Cone、Restricted? Cone和Port? Restricted? Cone三者),即可雙向通信。沒有把我們的結論3包括進去。
一般情況下,只有比較注重安全的大公司會使用Symmetric NAT,禁止使用P2P類型的通信,很多地方使用的都是Cone? NAT,因此穿透技術還是有發(fā)展前景的。
三、使用UDP、TCP穿透NAT
上面講的情況可以直接應用于UDP穿透技術中,使用TCP 協(xié)議穿透NAT 的方式和使用UDP 協(xié)議穿透NAT 的方式幾乎一樣,沒有什么本質上的區(qū)別,只是將無連接的UDP 變成了面向連接的TCP 。值得注意是:
1、 B在向A打洞時,發(fā)送的SYN 數(shù)據(jù)包,而且同樣會被NAT_A 丟棄。同時,B需要在原來的socket 上監(jiān)聽,由于重用socket ,所以需要將socket 屬性設置為SO_REUSEADDR 。
A向B發(fā)送連接請求。同樣,由于B到A方向的孔已經(jīng)打好,所以連接會成功,經(jīng)過3 次握手后,A到B之間的連接就建立起來了。具體過程如下:
1、 S啟動兩個網(wǎng)絡偵聽,一個叫【主連接】偵聽,一個叫【協(xié)助打洞】的偵聽。
2、 A和B分別與S的【主連接】保持聯(lián)系。
3、 當A需要和B建立直接的TCP連接時,首先連接S的【協(xié)助打洞】端口,并發(fā)送協(xié)助連接申請。同時在該端口號上啟動偵聽。注意由于要在相同的網(wǎng)絡終端上綁定到不同的套接字上,所以必須為這些套接字設置 SO_REUSEADDR 屬性(即允許重用),否則偵聽會失敗。
4、 S的【協(xié)助打洞】連接收到A的申請后通過【主連接】通知B,并將A經(jīng)過NAT-A轉換后的公網(wǎng)IP地址和端口等信息告訴B。
5、 B收到S的連接通知后首先與S的【協(xié)助打洞】端口連接,隨便發(fā)送一些數(shù)據(jù)后立即斷開,這樣做的目的是讓S能知道B經(jīng)過NAT-B轉換后的公網(wǎng)IP和端口號。
6、 B嘗試與A的經(jīng)過NAT-A轉換后的公網(wǎng)IP地址和端口進行connect,大多數(shù)路由器對于不請自到的SYN請求包直接丟棄而導致connect失敗,但NAT-B會紀錄此次連接的源地址和端口號,為接下來真正的連 接做好了準備,這就是所謂的打洞,即B向A打了一個洞,下次A就能直接連接到B剛才使用的端口號了。
7、 客戶端B打洞的同時在相同的端口上啟動偵聽。B在一切準備就緒以后通過與S的【主連接】回復消息“我已經(jīng)準備好”,S在收到以后將B經(jīng)過NAT-B轉換后的公網(wǎng)IP和端口號告訴給A。
8、 A收到S回復的B的公網(wǎng)IP和端口號等信息以后,開始連接到B公網(wǎng)IP和端口號,由于在步驟6中B曾經(jīng)嘗試連接過A的公網(wǎng)IP地址和端口,NAT-B紀錄了此次連接的信息,所以當A主動連接B時,NAT-B會認為是合法的SYN數(shù)據(jù),并允許通過,從而直接的TCP連接建立起來了。
參考網(wǎng)址:
holer 輕量級的內(nèi)網(wǎng)穿透工具,holer服務端采用Java語言實現(xiàn),服務端界面漂亮簡潔。
Holer客戶端采用了Java語言和GO語言實現(xiàn)了兩種版本,支持幾乎所有的OS平臺。
用到流行的微服務框架springboot和Java網(wǎng)絡框架netty。
配置很簡單,針對所有TCP協(xié)議只需在客戶端設置一個holer access key即可。
采用MySQL數(shù)據(jù)庫統(tǒng)一管理數(shù)據(jù)。
NAT有兩大類,基本NAT和NAPT。
靜態(tài)NAT:一個公網(wǎng)IP對應一個內(nèi)部IP,一對一轉換
動態(tài)NAT:N個公網(wǎng)IP對應M個內(nèi)部IP,不固定的一對一轉換關系
現(xiàn)在基本使用這種,又分為對稱和錐型NAT。
錐型NAT ,有完全錐型、受限制錐型、端口受限制錐型三種:
對稱NAT :
把所有來自相同內(nèi)部IP地址和端口號,到特定目的IP地址和端口號的請求映射到相同的外部IP地址和端口。如果同一主機使用不同的源地址和端口對,發(fā)送的目的地址不同,則使用不同的映射。只有收到了一個IP包的外部主機才能夠向該內(nèi)部主機發(fā)送回一個UDP包。對稱的NAT不保證所有會話中的(私有地址,私有端口)和(公開IP,公開端口)之間綁定的一致性。相反,它為每個新的會話分配一個新的端口號。
對稱NAT是一個請求對應一個端口,非對稱NAT是多個請求對應一個端口(象錐形,所以叫Cone NAT)。
連接服務器為A,NAT檢測服務器為B。
第一步:當一個接收客戶端(Endpoint-Receiver ,簡稱 EP-R)需要接收文件信息時,在其向連接服務器發(fā)送文件請求的同時緊接著向檢測服務器發(fā)送NAT檢測請求。此處再次強調(diào)是“緊接著”,因為對于對稱型NAT來說,這個操作可以直接算出其地址分配的增量(⊿p)。
第二步:當EP-R收到A或B的反饋信息時發(fā)現(xiàn)其外部地址與自身地址不同時就可以確定自己在NAT后面;否則,就是公網(wǎng)IP。
第三步:由服務器A向B發(fā)送其獲得的EP-R的外部映射地址(IPa/Porta),服務器B獲得后進行比較,如果端口不同,則說明這是對稱型NAT,同時可以直接計算出其分配增量:
⊿p=Portb-Porta
第四步:如果端口號相同,則由B向EP-R的Porta發(fā)送連接請求,如果EP-R有響應,則說明EP-R沒有IP和Port的限制,屬于全ConeNAT類型。
第五步:如果沒有響應,則由服務器B使用其新端口b’向EP-R的Portb端口發(fā)送連接請求,如果有響應,則說明EP-R只對IP限制,屬于限制性ConeNAT類型;否則就是對IP和port都限制,屬于端口限制性ConeNAT類型。
通過上述五步基本可以全部檢測出EP-R是否在公網(wǎng),還是在某種NAT后面。
這也是一項可選配置任務,可根據(jù)需要為NAT 地址映射表配置老化時間,以控制用戶對NAT 配置的使用,確保內(nèi)、外網(wǎng)的通信安全。
配置NAT 地址映射表項老化時間的方法也很簡單,只須在系統(tǒng)視圖下使用firewall-nat session { dns | ftp | ftp-data | http | icmp | tcp | tcp-proxy | udp | sip | sip-media | rtsp |rtsp-media }aging-time time-value 命令配置即可。參數(shù) time-value的取值范圍為1~65 535的整數(shù)秒。如果要配置多個會話表項的超時時間需要分別用本命令配置。
缺省情況下,各協(xié)議的老化時間為:DNS(120 s)、ftp(120 s)、ftp-data(120 s)、HTTP(120 s)、icmp(20 s)、tcp(600 s)、tcp-proxy(10 s)、udp(120 s)、sip(1 800 s)、sip-media ( 120 s )、rtsp ( 60 s )、rtsp-media ( 120 s ), 可用undo firewall-natsession { all | dns | ftp | ftp-data | http | icmp | tcp | tcp-proxy | udp | sip | sip-media | rtsp |rtsp-media } aging-time 命令恢復對應會話表項的超時時間為缺省值。
1、 中間服務器保存信息、并能發(fā)出建立UDP隧道的命令
2、 網(wǎng)關均要求為Cone NAT類型。Symmetric NAT不適合。
3、 完全圓錐型網(wǎng)關可以無需建立udp隧道,但這種情況非常少,要求雙方均為這種類型網(wǎng)關的更少。
4、 假如X1網(wǎng)關為Symmetric NAT, Y1為Address Restricted Cone NAT 或Full Cone NAT型網(wǎng)關,各自建立隧道后,A1可通過X1發(fā)送數(shù)據(jù)報給Y1到B1(因為Y1最多只進行IP級別的甄別),但B2發(fā)送給X1的將會被丟棄(因為發(fā)送來的數(shù)據(jù)報中端口與X1上存在會話的端口不一致,雖然IP地址一致),所以同樣沒有什么意義。
5、 假如雙方均為Symmetric NAT的情形,新開了端口,對方可以在不知道的情況下嘗試猜解,也可以達到目的,但這種情形成功率很低,且?guī)眍~外的系統(tǒng)開支,不是個好的解決辦法。
6、 不同網(wǎng)關型設置的差異在于,對內(nèi)會采用替換IP的方式、使用不同端口不同會話的方式,使用相同端口不同會話的方式;對外會采用什么都不限制、限制IP地址、限制IP地址及端口。
7、 這里還沒有考慮同一內(nèi)網(wǎng)不同用戶同時訪問同一服務器的情形,如果此時網(wǎng)關采用AddressRestricted Cone NAT 或Full Cone NAT型,有可能導致不同用戶客戶端可收到別人的數(shù)據(jù)包,這顯然是不合適的。
為什么網(wǎng)上講到的P2P打洞基本上都是基于UDP協(xié)議的打洞?難道TCP不可能打洞?還是TCP打洞難于實現(xiàn)?
假設現(xiàn)在有內(nèi)網(wǎng)客戶端A和內(nèi)網(wǎng)客戶端B,有公網(wǎng)服務端S。
如果A和B想要進行UDP通信,則必須穿透雙方的NAT路由。假設為NAT-A和NAT-B。
S也和A B 分別建立了會話,由S發(fā)到NAT-A的數(shù)據(jù)包會被NAT-A直接轉發(fā)給A,
由S發(fā)到NAT-B的數(shù)據(jù)包會被NAT-B直接轉發(fā)給B,除了S發(fā)出的數(shù)據(jù)包之外的則會被丟棄。
所以:現(xiàn)在A B 都能分別和S進行全雙工通訊了,但是A B之間還不能直接通訊。
并轉發(fā)給A了(即B現(xiàn)在能訪問A了);再由S命令B向A的公網(wǎng)IP發(fā)送一個數(shù)據(jù)包,則
NAT-B能接收來自NAT-A的數(shù)據(jù)包并轉發(fā)給B了(即A現(xiàn)在能訪問B了)。
以上就是“打洞”的原理。
pre style="margin: 0px; padding: 0px; white-space: pre-wrap; overflow-wrap: break-word;"為了保證A的路由器有與B的session,A要定時與B做心跳包,同樣,B也要定時與A做心跳,這樣,雙方的通信通道都是通的,就可以進行任意的通信了。/pre
API造成的。
UDP的socket允許多個socket綁定到同一個本地端口,而TCP的socket則不允許。
這是這樣一個意思:A B要連接到S,肯定首先A B雙方都會在本地創(chuàng)建一個socket,
去連接S上的socket。創(chuàng)建一個socket必然會綁定一個本地端口(就算應用程序里面沒寫
端口,實際上也是綁定了的,至少java確實如此),假設為8888,這樣A和B才分別建立了到
S的通信信道。接下來就需要打洞了,打洞則需要A和B分別發(fā)送數(shù)據(jù)包到對方的公網(wǎng)IP。但是
問題就在這里:因為NAT設備是根據(jù)端口號來確定session,如果是UDP的socket,A B可以
分別再創(chuàng)建socket,然后將socket綁定到8888,這樣打洞就成功了。但是如果是TCP的
socket,則不能再創(chuàng)建socket并綁定到8888了,這樣打洞就無法成功。
**UDP打洞**的過程大致如此:
1、雙方都通過UDP與服務器通訊后,網(wǎng)關默認就是做了一個外網(wǎng)IP和端口號 與你內(nèi)網(wǎng)IP與端口號的映射,這個無需設置的,服務器也不需要知道客戶的真正內(nèi)網(wǎng)IP
2、用戶A先通過服務器知道用戶B的外網(wǎng)地址與端口
3、用戶A向用戶B的外網(wǎng)地址與端口發(fā)送消息,
4、在這一次發(fā)送中,用戶B的網(wǎng)關會拒收這條消息,因為它的映射中并沒有這條規(guī)則。
5、但是用戶A的網(wǎng)關就會增加了一條允許規(guī)則,允許接收從B發(fā)送過來的消息
6、服務器要求用戶B發(fā)送一個消息到用戶A的外網(wǎng)IP與端口號
7、用戶B發(fā)送一條消息,這時用戶A就可以接收到B的消息,而且網(wǎng)關B也增加了允許規(guī)則
8、之后,由于網(wǎng)關A與網(wǎng)關B都增加了允許規(guī)則,所以A與B都可以向對方的外網(wǎng)IP和端口號發(fā)送消息。
TCP打洞 技術:
tcp打洞也需要NAT設備支持才行。
tcp的打洞流程和udp的基本一樣,但tcp的api決定了tcp打洞的實現(xiàn)過程和udp不一樣。
tcp按cs方式工作,一個端口只能用來connect或listen,所以需要使用端口重用,才能利用本地nat的端口映射關系。(設置SO_REUSEADDR,在支持SO_REUSEPORT的系統(tǒng)上,要設置這兩個參數(shù)。)
連接過程:(以udp打洞的第2種情況為例(典型情況))
nat后的兩個peer,A和B,A和B都bind自己listen的端口,向對方發(fā)起連接(connect),即使用相同的端口同時連接和等待連接。因為A和B發(fā)出連接的順序有時間差,假設A的syn包到達B的nat時,B的syn包還沒有發(fā)出,那么B的nat映射還沒有建立,會導致A的連接請求失?。ㄟB接失敗或無法連接,如果nat返回RST或者icmp差錯,api上可能表現(xiàn)為被RST;有些nat不返回信息直接丟棄syn包(反而更好)),(應用程序發(fā)現(xiàn)失敗時,不能關閉socket,closesocket()可能會導致NAT刪除端口映射;隔一段時間(1-2s)后未連接還要繼續(xù)嘗試);但后發(fā)B的syn包在到達A的nat時,由于A的nat已經(jīng)建立的映射關系,B的syn包會通過A的nat,被nat轉給A的listen端口,從而進去三次握手,完成tcp連接。
從應用程序角度看,連接成功的過程可能有兩種不同表現(xiàn):(以上述假設過程為例)
1、連接建立成功表現(xiàn)為A的connect返回成功。即A端以TCP的同時打開流程完成連接。
2、A端通過listen的端口完成和B的握手,而connect嘗試持續(xù)失敗,應用程序通過accept獲取到連接,最終放棄connect(這時可closesocket(conn_fd))。
多數(shù)Linux和Windows的協(xié)議棧表現(xiàn)為第2種。
但有一個問題是,建立連接的client端,其connect綁定的端口號就是主機listen的端口號,或許這個peer后續(xù)還會有更多的這種socket。雖然理論上說,socket是一個五元組,端口號是一個邏輯數(shù)字,傳輸層能夠因為五元組的不同而區(qū)分開這些socket,但是是否存在實際上的異常,還有待更多觀察。
1、Windows XP SP2操作系統(tǒng)之前的主機,這些主機不能正確處理TCP同時開啟,或者TCP套接字不支持SO_REUSEADDR的參數(shù)。需要讓AB有序的發(fā)起連接才可能完成。
上述tcp連接過程,僅對NAT1、2、3有效,對NAT4(對稱型)無效。
由于對稱型nat通常采用規(guī)律的外部端口分配方法,對于nat4的打洞,可以采用端口預測的方式進行嘗試。
ALG(應用層網(wǎng)關) :它可以是一個設備或插件,用于支持SIP協(xié)議,主要類似與在網(wǎng)關上專門開辟一個通道,用于建立內(nèi)網(wǎng)與外網(wǎng)的連接,也就是說,這是一種定制的網(wǎng)關。更多只適用于使用他們的應用群體內(nèi)部之間。
UpnP :它是讓網(wǎng)關設備在進行工作時尋找一個全球共享的可路由IP來作為通道,這樣避免端口造成的影響。要求設備支持且開啟upnp功能,但大部分時候,這些功能處于安全考慮,是被關閉的。即時開啟,實際應用效果還沒經(jīng)過測試。
STUN(Simple Traversalof UDP Through Network): 這種方式即是類似于我們上面舉例中服務器C的處理方式。也是目前普遍采用的方式。但具體實現(xiàn)要比我們描述的復雜許多,光是做網(wǎng)關Nat類型判斷就由許多工作,RFC3489中詳細描述了。
TURN(Traveral Using Relay NAT): 該方式是將所有的數(shù)據(jù)交換都經(jīng)由服務器來完成,這樣NAT將沒有障礙,但服務器的負載、丟包、延遲性就是很大的問題。目前很多游戲均采用該方式避開NAT的問題。這種方式不叫p2p。
ICE(Interactive Connectivity Establishment): 是對上述各種技術的綜合,但明顯帶來了復雜性。