TCP點對點穿透探索 失敗

2021-09-07 14:57:17 字數 4574 閱讀 8488

點對點穿透,需要實現的是對nat的穿透。想實現nat的穿透,當然要先了解nat到底是什麼,以及nat是用來幹什麼的。

nat全稱network address translation,意思是網路位址轉換,在2023年提出。它可以對不同的ip及埠進行對映,將乙個網路位址轉換為另乙個。nat的主要用途,大家可以看路由器。路由器具有乙個wan口及多個lan口;wan口對外,連線網際網路,擁有公網ip;lan口對內,構建本地網路,分配的是私網ip。當處於lan網下的本地主機想要訪問網際網路的時候,路由器就會通過nat技術,將lan 口的私網ip對映到wan口的公網ip,實現網路位址的轉換,這樣本地主機就可以訪問網際網路了。

nat技術的出現,有效減緩了ipv4時代可用ip位址枯竭的問題。至於為何可以緩解ip位址枯竭,我們依舊可以參照路由器來加以理解。路由器的lan網下擴充套件了多台本地主機,這些本地主機需要不同的ip位址加以區分。如果它們都是接在英特網下,那麼每台主機都需要消耗乙個公網ip,但是通過路由器的nat服務,這些本地主機可以先分配不同的私網ip,然後在需要連線到英特網的時候對映到公網ip的不同埠上完成對網際網路的訪問,從而節省ip位址的消耗。至於私網ip位址,由於nat的存在,本地網路與英特網處於隔離狀態,不必擔心與其他網路產生衝突。

上面是對nat的一些簡單的介紹,以及nat工作方式的簡單描述,如果覺得難以理解,可以自行查閱更多資料。

舉個例子,假如路由器wan口獲取到的公網ip是55.66.77.88(隨便寫的),lan網下某台本地主機獲取到的私網ip是192.168.0.100(路由器多是192.168.0.0網段)。現在本地主機想要向英特網發起連線,它通過自己的10000埠發起了連線,路由器知道有本地主機向英特網發起連線,便會分配乙個wan口的可用埠做對映,比如分配到的是5000埠。這時,192.168.0.10010000埠便和55.66.77.885000埠產生了對映關係。55.66.77.885000埠收到的網路包便會**到192.168.0.10010000埠,192.168.0.10010000埠收到的網路包也會**到55.66.77.885000埠。當然,由於是網路位址轉換,這途中還會有拆包,重新裝包的過程,不做詳細說明。

大致知道nat怎麼工作的之後,接下來了解為什麼要穿透nat。

按照上面的描述,nat的工作需要lan網下的本地裝置主動發起網路連線,然後nat服務才會將這個連線對映到wan口的公網ip完成轉換。也就是說,如果本地主機沒有主動發起連線,那麼這個對映就不會存在,那麼公網上的機器就無法訪問到私網上的機器。也就是說,只能是私網機器主動連線公網機器,而不能是公網機器主動連線私網機器。而為了實現公網機器主動連線私網機器,我們就需要穿透nat,這就是nat穿透的由來。

目前比較好實現nat穿透的方式是採用udp連線對nat進行打洞,然後完成連線。何為打洞呢?就是為了使nat產生乙個可用的對映。具體步驟就是在私網機器上用udp向某台公網機器發起連線,使得nat產生乙個可以使用的對映(洞)。然後通過這個對映(洞),就可以穿透nat。

至於為什麼要用udp,這是由於udp的某些特性。udp通訊需要先繫結本地機器的埠,完成後就可以從這個埠收發資料,至於從**收,發到**,可以在收發資料的時候再決定,這也就意味著我可以用這乙個埠同時和多個物件通訊,只要我收發資料的時候指定不同的物件即可。當本地機器用udp向英特網上的某個伺服器傳送資料的時候,這個對映不但能用來和這個伺服器進行資料互動,也能用來接收其他主機發來的資料。nat穿透就是本地主機向公網上的某台伺服器傳送資料,這時伺服器就可以獲得nat對這台主機的對映,在之前舉得例子中就是55.66.77.88:5000這個位址。由於nat會將55.66.77.88:5000收到的資料**至本地主機,所以公網上的其他機器可以從伺服器獲取到55.66.77.88:5000這個網路位址,然後通過這個網路位址向私網下的機器發出資料。

而至於為什麼不用tcp,也是由於tcp的某些特性。tcp通訊的步驟與udp不同,它需要先在兩個物件之間建立乙個專用通道,再用這個通道收發資料。也就是說外人無法插手。這樣一來,雖然其他機器可以通過伺服器獲取到nat的對映物件,也沒辦法利用它向私網下的機器發出資料。

關於tcp與udp的更多細節,請參考socket程式設計。

為了嘗試使用tcp實現點對點穿透,需要現對tcp做更多的了解。我之前有詳細查過tcp連線中的各種狀態變化,做了簡單的整理,可以做個參考:tcp連線狀態變化

既然tcp在連線過程中其他人不能插手,但是等它連線結束之後呢?nat對tcp連線的埠對映在連線結束後就立馬銷毀了嗎?接著深入,發現nat存在乙個老化機制。接下來看看老化是什麼意思。nat生成某個對映後,會將這個對映儲存下來,但是即使埠號非常多,它也不是無限的,而既然埠號是有限資源,那麼就不能保證對映表的無限擴充。為了合理利用資源,當某個對映一段時間內沒有發生資料互動,nat就會認為這個對映已經沒有人使用了,就會將這個對映銷毀,**埠號。這個時間,就叫做老化時間。也就是說,老化是一種對映的**機制。

tcp連線狀態變化中可以知道,tcp在斷開連線後會有一段時間的保護期,不讓這個埠進行下一次連線,這個時間是2*msl,msl在協議中的建議值為2分鐘,實際應用中常用是30秒,1分鐘和2分鐘,也就是說這個時間很有可能是一分鐘甚至更久。那老化時間有多久有多久呢,在老化時間控制中有提到,tcp的預設老化時間是86400秒,tcp-syn和tcp-fin的預設老化時間是60秒。這樣說來,按照一般情況等保護期結束的時候,nat的對映也到期了。

但是沒有關係,socket程式設計中允許有一些特殊的選項,其中有乙個叫so_reuseaddr的選項。

以下文字引用自setsockopt中引數之so_reuseaddr的意義

1、一般來說,乙個埠釋放後會等待兩分鐘之後才能再被使用,so_reuseaddr是讓埠釋放後立即就可以被再次使用。

so_reuseaddr用於對tcp套接字處於time_wait狀態下的socket,才可以重複繫結使用。server程式總是應該在呼叫bind()之前設定so_reuseaddr套接字選項。tcp,先呼叫close()的一方會進入time_wait狀態

2、so_reuseaddr和so_reuseport

so_reuseaddr提供如下四個功能:

so_reuseaddr允許啟動乙個監聽伺服器並**其眾所周知埠,即使以前建立的將此埠用做他們的本地埠的連線仍存在。這通常是重啟監聽伺服器時出現,若不設定此選項,則bind時將出錯。

so_reuseaddr允許在同一埠上啟動同一伺服器的多個例項,只要每個例項**乙個不同的本地ip位址即可。對於tcp,我們根本不可能啟動**相同ip位址和相同埠號的多個伺服器。

so_reuseaddr允許單個程序**同一埠到多個套介面上,只要每個**指定不同的本地ip位址即可。這一般不用於tcp伺服器。

so_reuseaddr允許完全重複的**:當乙個ip位址和埠繫結到某個套介面上時,還允許此ip位址和埠**到另乙個套介面上。一般來說,這個特性僅在支援多播的系統上才有,而且只對udp套介面而言(tcp不支援多播)。

so_reuseport選項有如下語義:

此選項允許完全重複**,但僅在想**相同ip位址和埠的套介面都指定了此套介面選項才行。

如果被**的ip位址是乙個多播位址,則so_reuseaddr和so_reuseport等效。

使用這兩個套介面選項的建議:

在所有tcp伺服器中,在呼叫bind之前設定so_reuseaddr套介面選項;

當編寫乙個同一時刻在同一主機上可執行多次的多播應用程式時,設定so_reuseaddr選項,並將本組的多播位址作為本地ip位址**。

if (setsockopt(fd, sol_socket, so_reuseaddr,

(const void *)&noptval , sizeof(int)) < 0) ...

so_reuseaddr 套接字選項應用例項

有了so_reuseaddr就好辦了,在剛斷開連線的時候nat的對映還沒有被老化,而由於so_reuseaddr套接字選項的關係,也可以立馬進行下一次連線。也就是說只要我們在nat服務設定的老化時間內重新建立好連線,那麼這個對映就可以繼續使用。

從原理上來說應該是存在可行性的,如果有偏頗,忘指正。後續會嘗試搭建環境,寫程式做個試驗。

TCP網路穿透

tcp協議 upd穿透原理 主要在於系統介面的限制.socket相關的介面有 connect,sendto,recvfrom,send,recv等 使用udp程式設計時,建立socket之後,就可以使用這個socket向任意位址傳送資料.但是tcp程式設計不一樣,一旦處理連線狀態之後,這個socke...

使用TCP協議的穿透技術

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

利用P2P點對點技術實現UDP內網穿透

點對點技術在近幾年應用很廣,主要代表有qq skype bt 迅雷 ppstream pplive qvod。我們可以看到,只要是資料量很大,而一般利用中轉伺服器又需要一定規模投入的應用,我們都可以考慮用p2p技術。有兩個好處 1.可以降低成本與投入。2.提高傳輸效能。從上面的描述,我們可以得出兩個...