最近實驗室領了主機,一臺windows 32GB i7-14,平時也不用win,想著搞成linux server掛在實驗室挺好的,24小時不斷電,遠程操控codex完成一些橫向😃。實驗室也有一些共用的server,但是共享的總還是不如私有的舒服,安全性也不可控(實驗室的server幾天前被人下了挖礦腳本,整成礦機了...),再說,性能也不如這臺主機。於是我開始了折騰。
正常來說,想要外網訪問內網機器,一個frp內網穿透就可以用了,這是最簡單的。但是frp需要一臺公網服務器,而我手上的騰訊雲vps恰好快到期了,這時候我想起了之前經常聽說的tailscale,好像是用來組網的,我一直想試試。
tailscale原理
先問了一下gpt這個tailscale是什麼原理,gpt吐出p2p的時候,興趣就來了,我想起來了一些遠古的p2p下載軟件例如迅某雷軟件的輝煌過去。
tailscale的核心是一種叫做UDP打洞的技術,我查了一下,這項技術已經很老了,以前的bt也用過UDP打洞的方式,是一種很p2p的方式。最常用的目的是為了讓兩個躲在各自內網(躲在各自的NAT背後)的主機直接建立通信。

具體的打洞並建立直連的完整過程是這樣的:
Tailscale有一臺協調服務器(tracker,login.tailscale.com)
- tracker是認證中心,但這部分Tailscale做得其實很薄,他們在博客中也寫到,這部分主要是外包給像Gmail這樣的中心化服務廠商來做的。
- tracker主要負責登錄認證、公鑰分發等一些常見服務。這裡的公鑰分發最關鍵的應該是WireGuard的公鑰分發。後面會提到,兩臺主機之間的PTP連接主要依靠WireGuard這種隧道來連接,所以公鑰分發是很重要的一步。
兩個內網主機需要先登錄Tailscale,經過登錄認證和公鑰分發之後,就算加入了同一個虛擬內網(常說的Tailnet)。
- Tailnet是Tailscale的核心特色,你可以實現很多有意思的,之後會提到。就像使用真正的局域網一樣去使用Tailnet中的所有設備,這件事是非常舒服的。
兩臺主機正式開始嘗試建立建立P2P直連了。首先,兩臺主機需要拿到自己的候選地址。
- 候選地址一般是為了讓對方連接,且對方可以連接的地址。你可以基本理解為這兩臺主機各自的公網IP地址和端口信息。為什麼要說候選地址,而不直接說公網地址呢?因為有可能你的兩臺主機並不在兩個獨立的內網裡。這種情況下,這個候選地址可能就是局域網內的地址,所以統一稱為候選地址。
- 探測候選地址的過程一般會使用STUN。STUN 是一種網絡探測協議,藉助外部服務器看到自己的公網 IP 和端口是什麼,全稱是 Session Traversal Utilities for NAT。
- 一般的STUN服務是由DERP中繼服務器同時提供的。DERP我們後面會講。
- 在兩臺主機都拿到自己的候選地址之後,它們需要把候選地址發送給對方。但是他們現在又沒有直接途徑連接到對方併發送這個信息。如果有,就不用搭Tailscale了,他們可以直接直連。這時候,Tailscale中最重要的角色——DERP中繼服務器就出現了。
由DERP負責協商兩臺主機,就是在兩條主機之間提供一條轉發通道,交換它們的候選地址和其他加密信息,使兩臺主機都可以拿到對方的候選地址,並以此為目的地嘗試建立WireGuard直連隧道。
- DERP 全稱 Designated Encrypted Relay for Packets,Encrypted表示DERP只負責轉發加密的WireGuard數據包,沒有能力解密。WireGuard的私鑰始終只留在節點本地,永遠不上傳。
- Tailscale官方提供全球各個常見地區的DERP,沒有大陸哈
- 以上海為例,不配自己的DERP的話,一般走官方的洛杉磯DERP,200ms的延遲,總體能用,只是有時候不穩定。但是如果打洞直連失敗,fallback到使用DERP轉發數據失敗就很卡了,這個後面會說。
具體建立WireGuard直連隧道的過程是這樣的:一方主機拿到對方的候選地址之後,向對方的公網地址發 disco 探測包(Ping),一邊通過DERP給對方發一條叫做 CallMeMaybe 的信息,裡面帶著自己的公網地址。對方收到後也向這些地址發探測包。Ping pong完成之後,路徑就可用了,整個WireGuard的數據直連就建立起來了。
A B ├──────── UDP DISCO Ping,探测 B 的地址 ───────────→ │ ├──────── DERP:CallMeMaybe(附 A 的候选地址) ───→ │ ←──────── UDP DISCO Ping,探测 A 的地址 ───────────┤ │ ├──────────────── DISCO Ping / Pong ──────────────┤ │ └──────── 路径可用后,WireGuard 数据直连 ──────────┘
- 詳細的分析可以看官方的這篇博客:https://tailscale.com/blog/how-tailscale-works
上面的整個過程,是建立P2P直連成功的理想情況。
仍然有一定概率無法建立P2P直連。這時候,所有數據流量也會通過之前提到的官方DERP做中繼轉發。注意,在上面提到的整個過程中,DERP幾乎只是做控制平面的轉發功能,用來協商兩臺內網主機形成P2P直連。形成直連之後,幾乎不用再用到DERP了。它們的數據將通過直連的WireGuard隧道傳播,這樣速度比較快。
如果建立P2P直連失敗,這時候就會fallback到用官方的DERP做數據轉發。只用官方的DERP,就會非常卡。這時候你就需要買一臺公網vps來自建的DERP了,由於我手頭正好有一臺公網VPS,應該是騰訊雲一年68元的輕量應用服務器,這個我也搭建了,後面會提到。
好了,你已經完全懂得tailscale了,之後可以讓agent一把梭開始配置了,本地配好 ~/.ssh/config 就好了,agent會自己ssh上去配好所有的tailscale節點的哈哈。
配置的過程唯一需要人操作的就是在每臺機器上都要登錄tailscale的網站認證一下,這個agent也會給你網址的,常規的設備碼的認證方式。
你的mac上可以下載一個tailscale客戶端,可以看看有哪些機器,但是大部分高級的操作還是隻能在官方網頁上完成,比如加自己的中繼和peer relay

Peer relay和DERP這兩個中繼區別
這裡邏輯上有一點小繞,因為它們兩個本質上都是一種中繼服務。
DERP我們之前已經頻繁提到過,它是用來協商兩臺主機之間交換候選地址及一些其他連接信息的一種中繼服務。它的協商主要體現在控制層面;Peer Relay的中繼主要體現在數據層面。
Peer relay是指對等中繼,它提供的是一種在兩臺主機之間轉發數據流量的服務。
Peer relay一般在無法建立P2P直連的情況下使用。我們前面已經提到過,官方的DERP中繼服務器會轉發你的數據包,這時候Peer relay這種服務就是由官方的DERP來提供的。
但是我們之前提到過,在中國大陸,官方的DERP,也就是官方免費的DERP中繼服務器,有最低200ms的延遲。在無法建立P2P的情況下,單純用官方DERP提供的Peer Relay服務,網速很難令人滿意。所以這時候我們就需要一臺公網VPS來自建DRP,並提供Peer Relay服務。一般來說,Peer Relay都是由DERP中繼服務器同時提供的。
配置也很簡單。你只需要讓Agent在自己的公網vps上配置DERP的時候,順便也加上Peer Relay功能就行。這部分也需要到官方網站上手動填寫一些JSON配置,Agent都會一步一步教你。
一些好玩的
當你把手機、電腦和一臺永不關機的內網服務器都連上之後,就可以實現:隨時隨地在iPhone的codex上,像訪問內網設備一樣訪問遠在學校實驗室裡的那臺24小時服務器,在上面跑一些任務,遠程Vibe Coding,跟蹤任務狀態,甚至臨時處理一些運維事情,都非常方便。
這時候你可能會說:我直接用FRP內網穿透把那臺機器透出來不就完事了嗎?是的,我以前也是這麼做的。但FRP有兩個很明顯的弊端:
FRP本身必須需要一臺公網VPS做穿透服務,而Tailscale在很多場景下幾乎不需要,它可以通過嘗試打洞的方式建立直連。在我生活中80% 的情況下,它的直連都是可以成功的。
第二個情況是一個很現實的使用場景:比如你想在手機的Codex上打開部署在內網服務器的內網地址的一個網頁,你是做不到的。因為你需要額外配置一個SSH轉發,把內網服務器localhost/內網IP的端口的web服務轉發到你手機的localhost。這件事情在iPhone上並不是那麼方便實現。
但是假如你擁有一個真正的虛擬內網Tailnet,就可以直接訪問那臺服務器上在它的內網IP某個端口監聽的服務,這件事非常絲滑。如果你在上面部署了很多端口的web服務,就不再需要一個一個SSH去做端口轉發了,你可以直接訪問任意端口。
出口節點 Exit Node
出口節點是指你可以指定Tailscale內網中的一臺設備節點,作為當前這臺設備的出網節點。這件事在具體場景下非常有用。
當你在iPhone上安裝Tailscale之後,它是作為一個VPN代理設置存在的,和手機上原本的Shadowrocket或Surge這類代理App衝突。這個時候,你就需要將iPhone這臺設備的出口節點設置為虛擬內網中的一臺服務器。
我的內網那臺服務器本身就配置了代理服務,clash/singbox這些,讓iPhone複用這個內網服務器的代理服務去出口,幾乎是一鍵配置的事情。