使用TCP協議的NAT穿透技術

2021-05-27 15:01:56 字數 1659 閱讀 9630

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

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

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

要實現 a、b直接的通訊,就必須進行以下3步:

①a首先連線網際網路上的伺服器s並傳送一條訊息(對於udp這種無連線的協議其實直接初始會話傳送訊息即可),這樣s就獲取了a在網際網路上的實際終端(傳送訊息的ip和埠號)。

②接著 b也進行同樣的步驟,s就知道了a、b在網際網路上的終端(這就是「打洞」)。

③接著s分別告訴a和b對方客戶端在網際網路上的實際終端,也即s告訴a客戶b的會話終端,s告訴b客戶a的會話終端。

這樣,在a、b都知道了對方的實際終端之後,就可以直接通過實際終端傳送訊息了(因為先前雙方都向外傳送過訊息,路由上已經有允許資料進出的訊息通道)。

用udp來實現以上3步不存在什麼理論上的問題,因為udp是無連線的協議,它允許socket進行「多對一」的通訊(即幾個具有不同ip和埠號的socket向乙個接收socket傳送訊息)。但是使用tcp就出現了問題:

在一般情況下,tcp socket不允許在已經建立連線的埠上再進行監聽和使用該本地埠。換句話說,當ab連線上伺服器s後,s將ab的實際終端告訴對方,下一步本該是a、b利用對方的實際終端進行直連,但這時你會發現對方的實際終端已經被占用了(就是各自連線到伺服器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連線。

首先,還是a、b分別和伺服器s分別建立連線,s記錄a、b的網際網路實際終端。然後s分別向a、b傳送對方的實際終端。

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

使用TCP協議的NAT穿透技術

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

使用TCP協議的NAT穿透技術

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

使用TCP協議的NAT穿透技術

一直以來,說起nat穿透,很多人都會被告知使用udp打孔這個技術,基本上沒有人會告訴你如何使用tcp協議去穿透 甚至有的人會直接告訴你tcp協議是無法實現穿透的 但是,眾所周知的是,udp是乙個無連線的資料報協議,使用它就必須自己維護收發資料報的完整性,這常常會大大增加程式的複雜度,而且一些程式由於...