NAT穿透(UDP打洞)

1、NAT(Network Address Translator)介紹

532288-20170726190839609-188399264.png

NAT有兩大類,基本NAT和NAPT。

1.1、基本NAT

靜態(tài)NAT:一個公網IP對應一個內部IP,一對一轉換

動態(tài)NAT:N個公網IP對應M個內部IP,不固定的一對一轉換關系

** 1.2、NAPT(Network Address/Port Translator)**

現在基本使用這種,又分為對稱和錐型NAT。

錐型NAT,有完全錐型、受限制錐型、端口受限制錐型三種:

  • a)Full Cone NAT(完全圓錐型):從同一私網地址端口192.168.0.8:4000發(fā)至公網的所有請求都映射成同一個公網地址端口1.2.3.4:62000 ,192.168.0.8可以收到任意外部主機發(fā)到1.2.3.4:62000的數據報。
  • b)Address Restricted Cone NAT (地址限制圓錐型):從同一私網地址端口192.168.0.8:4000發(fā)至公網的所有請求都映射成同一個公網地址端口1.2.3.4:62000,只有當內部主機192.168.0.8先給服務器C 6.7.8.9發(fā)送一個數據報后,192.168.0.8才能收到6.7.8.9發(fā)送到1.2.3.4:62000的數據報。
  • c)Port Restricted Cone NAT(端口限制圓錐型):從同一私網地址端口192.168.0.8:4000發(fā)至公網的所有請求都映射成同一個公網地址端口1.2.3.4:62000,只有當內部主機192.168.0.8先向外部主機地址端口6.7.8.9:8000發(fā)送一個數據報后,192.168.0.8才能收到6.7.8.9:8000發(fā)送到1.2.3.4:62000的數據報。

對稱NAT

把所有來自相同內部IP地址和端口號,到特定目的IP地址和端口號的請求映射到相同的外部IP地址和端口。如果同一主機使用不同的源地址和端口對,發(fā)送的目的地址不同,則使用不同的映射。只有收到了一個IP包的外部主機才能夠向該內部主機發(fā)送回一個UDP包。對稱的NAT不保證所有會話中的(私有地址,私有端口)和(公開IP,公開端口)之間綁定的一致性。相反,它為每個新的會話分配一個新的端口號。

對稱NAT是一個請求對應一個端口,非對稱NAT是多個請求對應一個端口(象錐形,所以叫Cone NAT)。

1.3、檢測NAT類型:

連接服務器為A,NAT檢測服務器為B。

第一步:當一個接收客戶端(Endpoint-Receiver ,簡稱 EP-R)需要接收文件信息時,在其向連接服務器發(fā)送文件請求的同時緊接著向檢測服務器發(fā)送NAT檢測請求。此處再次強調是“緊接著”,因為對于對稱型NAT來說,這個操作可以直接算出其地址分配的增量(⊿p)。

第二步:當EP-R收到A或B的反饋信息時發(fā)現其外部地址與自身地址不同時就可以確定自己在NAT后面;否則,就是公網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是否在公網,還是在某種NAT后面。

1.4、NAT映射老化時間

這也是一項可選配置任務,可根據需要為NAT 地址映射表配置老化時間,以控制用戶對NAT 配置的使用,確保內、外網的通信安全。

配置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 命令配置即可。參數 time-value的取值范圍為1~65 535的整數秒。如果要配置多個會話表項的超時時間需要分別用本命令配置。

缺省情況下,各協(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 命令恢復對應會話表項的超時時間為缺省值。


2、UDP打洞

2.1、p2p可實現的條件需要:

1、 中間服務器保存信息、并能發(fā)出建立UDP隧道的命令

2、 網關均要求為Cone NAT類型。Symmetric NAT不適合。

3、 完全圓錐型網關可以無需建立udp隧道,但這種情況非常少,要求雙方均為這種類型網關的更少。

4、 假如X1網關為Symmetric NAT, Y1為Address Restricted Cone NAT 或Full Cone NAT型網關,各自建立隧道后,A1可通過X1發(fā)送數據報給Y1到B1(因為Y1最多只進行IP級別的甄別),但B2發(fā)送給X1的將會被丟棄(因為發(fā)送來的數據報中端口與X1上存在會話的端口不一致,雖然IP地址一致),所以同樣沒有什么意義。

5、 假如雙方均為Symmetric NAT的情形,新開了端口,對方可以在不知道的情況下嘗試猜解,也可以達到目的,但這種情形成功率很低,且?guī)眍~外的系統(tǒng)開支,不是個好的解決辦法。

6、 不同網關型設置的差異在于,對內會采用替換IP的方式、使用不同端口不同會話的方式,使用相同端口不同會話的方式;對外會采用什么都不限制、限制IP地址、限制IP地址及端口。

7、 這里還沒有考慮同一內網不同用戶同時訪問同一服務器的情形,如果此時網關采用AddressRestricted Cone NAT 或Full Cone NAT型,有可能導致不同用戶客戶端可收到別人的數據包,這顯然是不合適的。

2.2、udp和tcp打洞

為什么網上講到的P2P打洞基本上都是基于UDP協(xié)議的打洞?難道TCP不可能打洞?還是TCP打洞難于實現?
假設現在有內網客戶端A和內網客戶端B,有公網服務端S。
如果A和B想要進行UDP通信,則必須穿透雙方的NAT路由。假設為NAT-A和NAT-B。

A發(fā)送數據包到公網S,B發(fā)送數據包到公網S,則S分別得到了A和B的公網IP,

S也和A B 分別建立了會話,由S發(fā)到NAT-A的數據包會被NAT-A直接轉發(fā)給A,
由S發(fā)到NAT-B的數據包會被NAT-B直接轉發(fā)給B,除了S發(fā)出的數據包之外的則會被丟棄。
所以:現在A B 都能分別和S進行全雙工通訊了,但是A B之間還不能直接通訊。

解決辦法是:A向B的公網IP發(fā)送一個數據包,則NAT-A能接收來自NAT-B的數據包

并轉發(fā)給A了(即B現在能訪問A了);再由S命令B向A的公網IP發(fā)送一個數據包,則
NAT-B能接收來自NAT-A的數據包并轉發(fā)給B了(即A現在能訪問B了)。

以上就是“打洞”的原理。

<pre style="margin: 0px; padding: 0px; white-space: pre-wrap; overflow-wrap: break-word;">為了保證A的路由器有與B的session,A要定時與B做心跳包,同樣,B也要定時與A做心跳,這樣,雙方的通信通道都是通的,就可以進行任意的通信了。</pre>

但是TCP和UDP在打洞上卻有點不同。這是因為伯克利socket(標準socket規(guī)范)的

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ā)送數據包到對方的公網IP。但是
問題就在這里:因為NAT設備是根據端口號來確定session,如果是UDP的socket,A B可以
分別再創(chuàng)建socket,然后將socket綁定到8888,這樣打洞就成功了。但是如果是TCP的
socket,則不能再創(chuàng)建socket并綁定到8888了,這樣打洞就無法成功。

**UDP打洞**的過程大致如此:

1、雙方都通過UDP與服務器通訊后,網關默認就是做了一個外網IP和端口號 與你內網IP與端口號的映射,這個無需設置的,服務器也不需要知道客戶的真正內網IP

2、用戶A先通過服務器知道用戶B的外網地址與端口

3、用戶A向用戶B的外網地址與端口發(fā)送消息,

4、在這一次發(fā)送中,用戶B的網關會拒收這條消息,因為它的映射中并沒有這條規(guī)則。

5、但是用戶A的網關就會增加了一條允許規(guī)則,允許接收從B發(fā)送過來的消息

6、服務器要求用戶B發(fā)送一個消息到用戶A的外網IP與端口號

7、用戶B發(fā)送一條消息,這時用戶A就可以接收到B的消息,而且網關B也增加了允許規(guī)則

8、之后,由于網關A與網關B都增加了允許規(guī)則,所以A與B都可以向對方的外網IP和端口號發(fā)送消息。

TCP打洞技術:
tcp打洞也需要NAT設備支持才行。
tcp的打洞流程和udp的基本一樣,但tcp的api決定了tcp打洞的實現過程和udp不一樣。
tcp按cs方式工作,一個端口只能用來connect或listen,所以需要使用端口重用,才能利用本地nat的端口映射關系。(設置SO_REUSEADDR,在支持SO_REUSEPORT的系統(tǒng)上,要設置這兩個參數。)

連接過程:(以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上可能表現為被RST;有些nat不返回信息直接丟棄syn包(反而更好)),(應用程序發(fā)現失敗時,不能關閉socket,closesocket()可能會導致NAT刪除端口映射;隔一段時間(1-2s)后未連接還要繼續(xù)嘗試);但后發(fā)B的syn包在到達A的nat時,由于A的nat已經建立的映射關系,B的syn包會通過A的nat,被nat轉給A的listen端口,從而進去三次握手,完成tcp連接。

從應用程序角度看,連接成功的過程可能有兩種不同表現:(以上述假設過程為例)
1、連接建立成功表現為A的connect返回成功。即A端以TCP的同時打開流程完成連接。
2、A端通過listen的端口完成和B的握手,而connect嘗試持續(xù)失敗,應用程序通過accept獲取到連接,最終放棄connect(這時可closesocket(conn_fd))。
多數Linux和Windows的協(xié)議棧表現為第2種。

但有一個問題是,建立連接的client端,其connect綁定的端口號就是主機listen的端口號,或許這個peer后續(xù)還會有更多的這種socket。雖然理論上說,socket是一個五元組,端口號是一個邏輯數字,傳輸層能夠因為五元組的不同而區(qū)分開這些socket,但是是否存在實際上的異常,還有待更多觀察。

2.3、另外的問題

1、Windows XP SP2操作系統(tǒng)之前的主機,這些主機不能正確處理TCP同時開啟,或者TCP套接字不支持SO_REUSEADDR的參數。需要讓AB有序的發(fā)起連接才可能完成。

上述tcp連接過程,僅對NAT1、2、3有效,對NAT4(對稱型)無效。
由于對稱型nat通常采用規(guī)律的外部端口分配方法,對于nat4的打洞,可以采用端口預測的方式進行嘗試。

2.4、一些常用技術

ALG(應用層網關):它可以是一個設備或插件,用于支持SIP協(xié)議,主要類似與在網關上專門開辟一個通道,用于建立內網與外網的連接,也就是說,這是一種定制的網關。更多只適用于使用他們的應用群體內部之間。

UpnP:它是讓網關設備在進行工作時尋找一個全球共享的可路由IP來作為通道,這樣避免端口造成的影響。要求設備支持且開啟upnp功能,但大部分時候,這些功能處于安全考慮,是被關閉的。即時開啟,實際應用效果還沒經過測試。

STUN(Simple Traversalof UDP Through Network):這種方式即是類似于我們上面舉例中服務器C的處理方式。也是目前普遍采用的方式。但具體實現要比我們描述的復雜許多,光是做網關Nat類型判斷就由許多工作,RFC3489中詳細描述了。

TURN(Traveral Using Relay NAT):該方式是將所有的數據交換都經由服務器來完成,這樣NAT將沒有障礙,但服務器的負載、丟包、延遲性就是很大的問題。目前很多游戲均采用該方式避開NAT的問題。這種方式不叫p2p。

ICE(Interactive Connectivity Establishment):是對上述各種技術的綜合,但明顯帶來了復雜性。


參考與引用:

http://pennlee.blog.163.com/blog/static/5259930200752511814652/

https://www.zhihu.com/question/38729355/answer/86531260

http://blog.csdn.net/byxdaz/article/details/52785697

http://book.51cto.com/art/201408/449058.htm

http://blog.csdn.net/weiyuefei/article/details/52247497

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容