NAT與NAT穿透 三

2021-06-26 16:28:44 字數 1798 閱讀 2070

一直以來,說起nat穿透,很多人都會被告知使用udp打孔這個技術,基本上沒有人會告訴你如何使用tcp協議去穿透(甚至有的人會直接告訴你tcp協議是無法實現穿透的)。但是,眾所周知的是,udp是乙個無連線的資料報協議,使用它就必須自己維護收發資料報的完整性,這常常會大大增加程式的複雜度,而且一些程式由於某些原因,必須使用tcp協議,這樣就常常令一些開發tcp網路程式的人員「談穿透色變」。那麼,使用tcp協議是不是就不能實現穿透呢?答案當然是否定的:tcp協議不僅能實現nat穿透,而且實現起來比udp穿透甚至還簡單一些。

要了解如何使用tcp穿透nat,就要首先看看如何使用udp穿透nat。

我們假設在兩個不同的區域網後面分別有2臺客戶機a和 b,ab所在的區域網都分別通過乙個路由器接入網際網路。網際網路上有一台伺服器s。

現在ab是無法直接和對方傳送資訊的,ab都不知道對方在網際網路上真正的ip和埠, ab所在的區域網的路由器只允許內部向外主動傳送的資訊通過。對於b直接傳送給a的路由器的訊息,路由會認為其「不被信任」而直接丟棄。

要實現 ab直接的通訊,就必須進行以下3步:a首先連線網際網路上的伺服器s並傳送一條訊息(對於udp這種無連線的協議其實直接初始會話傳送訊息即可),這樣s就獲取了a在網際網路上的實際終端(傳送訊息的ip和埠號)。接著 b也進行同樣的步驟,s就知道了ab在網際網路上的終端(這就是「打洞」)。接著s分別告訴a和b對方客戶端在網際網路上的實際終端,也即s告訴a客戶b的會話終端,s告訴b客戶a的會話終端。這樣,在ab都知道了對方的實際終端之後,就可以直接通過實際終端傳送訊息了(因為先前雙方都向外傳送過訊息,路由上已經有允許資料進出的訊息通道)。

用udp來實現以上3步不存在什麼理論上的問題,因為udp是無連線的協議,它允許socket進行「多對一」的通訊(即幾個具有不同ip和埠號的socket向乙個接收socket傳送訊息)。但是使用tcp就出現了問題:在一般情況下,tcp socket不允許在已經建立連線的埠上再進行監聽和使用該本地埠。換句話說,當ab連線上伺服器s後,s將ab的實際終端告訴對方,下一步本該是ab利用對方的實際終端進行直連,但這時你會發現對方的實際終端已經被占用了(就是各自連線到伺服器s的會話占用了終端),無法同時listen和 connect。於是很多人得出結論:tcp無法實現nat穿透。

於是問題的關鍵變成了如何復用乙個tcp連線的本地終端,這其實不是協議的問題,而是乙個api的問題。幸運的是,所有主流作業系統都支援乙個特定的tcp套接字選項——so_reuseaddr。這個選項允許將多個socket繫結到同乙個本地終端。我們建立socket的時候只要加上這麼一行:

setsockopt(socket, sol_socket, so_reuseaddr, &flag, len) ; //c++就這麼做

_client.setsocketoption(socketoptionlevel.socket, socketoptionname.reuseaddress, true) '這是vb.net 更加簡單

知道上面的知識就很好辦了,下面我來說說tcp協議的穿透流程:

機器布局還是和上面使用udp的一樣。現在假設客戶a想和客戶b建立tcp連線。

首先還是 ab分別和伺服器s分別建立連線,s記錄ab的網際網路實際終端。然後s分別向ab傳送對方的實際終端。接著,從a和b向s連線時使用的埠,ab都非同步呼叫connect函式連線對方的實際終端(就是s告訴的終端),同時,ab雙方都在同乙個本地埠監聽到來的連線(也可以先監聽,再connect更好)。由於雙方都向對方傳送了connect請求(假設各自的syn封包已經穿過了自己的nat),因此在對方connect請求到達本地的監聽埠時,路由器會認為這個請求是剛剛那個connect會話的一部分,是已經被許可的,本地監聽埠就會用syn-ack響應,同意連線。這樣,tcp穿透nat的點對點連線就成功了。

nat 穿透原理

其實很早我就已經實現了使用tcp協議穿透nat了,但是苦於一直沒有時間,所以沒有寫出來,現在終於放假有一點空閒,於是寫出來共享之。一直以來,說起nat穿透,很多人都會被告知使用udp打孔這個技術,基本上沒有人會告訴你如何使用tcp協議去穿透 甚至有的人會直接告訴你tcp協議是無法實現穿透的 但是,眾...

NAT穿透實戰

1 使用者a 登入伺服器 s,伺服器 s記錄使用者a經 nat轉換後的位址。2 使用者 b登入伺服器 s,伺服器 s記錄使用者b經 nat轉換後的位址。3 使用者 a想與使用者b建立 p2p通訊。4 使用者 a向伺服器傳送請求,告訴伺服器想與使用者b建立 p2p通訊。5 伺服器 s接收到使用者 a傳...

nat 穿透原理

其實很早我就已經實現了使用tcp協議穿透nat了,但是苦於一直沒有時間,所以沒有寫出來,現在終於放假有一點空閒,於是寫出來共享之。一直以來,說起nat穿透,很多人都會被告知使用udp打孔這個技術,基本上沒有人會告訴你如何使用tcp協議去穿透 甚至有的人會直接告訴你tcp協議是無法實現穿透的 但是,眾...