SSD Nodes Learn Hosting plans →
指南 Matt Connor作者: Matt Connor · 已更新 2026-08-30

透過 Tor Onion Service 隱藏 SSH 埠教學

將 sshd 隱藏在 Tor onion service 後方,讓 VPS 無需開放任何入站埠。本指南提供 v3 客戶端授權設定步驟,並詳列避免鎖定伺服器的正確操作順序,確保您能安全地完成遠端連線配置。

透過 Tor onion service 執行 SSH 的變更

透過 Tor onion service 執行 SSH,讓您能管理一台在任何埠皆不接受外部連線的 VPS。伺服器會主動撥號至 Tor 網路並保持連線開啟。您的 SSH 連線會經由該通道傳回,因此伺服器無須在公開 IP 位址上監聽任何埠。

對日誌的影響立竿見影。一台開放公開 SSH 埠的伺服器,每天會收集數千次來自掃描器的失敗密碼嘗試。將 sshd 移至 onion service 後方並在防火牆阻擋所有入站流量,/var/log/auth.log 便只會記錄您親自發起的連線。

其代價是 tor 必須存在於每個管理連線的路徑中。它是一個使用者空間(userspace)的 daemon,每次重新開機後都必須啟動並完成引導,您才能登入。在關閉埠之前請務必規劃好,因為此處的失敗模式是導致您無法存取實體無法觸及的機器。

在進行任何變更前先建立復原路徑

在擁有不依賴 SSH 的復原路徑之前,請勿開始操作。

現在請開啟服務供應商的控制台(例如 VNC 或序列埠控制台),並透過該介面登入。若不清楚 root 密碼,請先 從控制台重設 root 密碼 並確認可成功登入。未經測試的控制台無法作為有效的復原路徑。

下列步驟順序至關重要。每個步驟在執行下一步前都必須經過驗證,且在 Onion 路由運作正常前,請保持 22 埠開啟。

  1. 安裝 tor 並確認其完成啟動程序(bootstrap)。
  2. 定義 Onion 服務並讀取其位址。
  3. 在 22 埠仍開啟的狀態下,透過 Onion 位址進行連線。
  4. 新增客戶端授權(client authorisation),然後再次連線。
  5. 將 sshd 綁定至 loopback 介面,並關閉 22 埠。
  6. 重新開機,然後再次透過 Onion 位址連線。

請在整個過程中保持目前的 SSH 連線開啟。已建立的連線在防火牆變更後仍能維持,這將是您的第一道救援防線。

在伺服器上安裝 tor

Ubuntu 軟體庫內建 tor,但該版本通常較為老舊。Tor Project 的軟體庫提供其說明文件所描述的版本。請依照其 apt 軟體庫指南 中的指令進行新增。

sudo apt update
sudo apt install -y apt-transport-https wget gpg
wget -qO- https://deb.torproject.org/torproject.org/A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89.asc | gpg --dearmor | sudo tee /usr/share/keyrings/deb.torproject.org-keyring.gpg >/dev/null

執行 /etc/apt/sources.list.d/tor.sources。Suites 需要您的發行版代號,可透過 lsb_release -cs 取得(在 Ubuntu 24.04 上為 noble)。

Types: deb deb-src
URIs: https://deb.torproject.org/torproject.org/
Suites: noble
Components: main
Signed-By: /usr/share/keyrings/deb.torproject.org-keyring.gpg
sudo apt update
sudo apt install -y tor deb.torproject.org-keyring
sudo journalctl -u tor@default -n 20 --no-pager

日誌結尾應顯示 Bootstrapped 100% (done)。若卡在此訊息下方,表示 tor 無法連線至網路,這通常是由於對外防火牆規則限制或系統時間嚴重錯誤所致。

服務名稱是一個陷阱。 即使系統運作正常,systemctl status tor 仍會回報 Active: active (exited),這是因為 Debian 與 Ubuntu 將 tor 封裝為多實例主單元(multi-instance master unit),其唯一功能是啟動實際的實例。守護行程本身是以 tor@default.service 執行。請使用該名稱進行 status 與 journalctl。對 tor 執行啟動、停止與重新載入指令仍會作用於該實例,因此 sudo systemctl reload tor 的運作方式符合您的預期。

定義連接埠 22 的 onion 服務

在 /etc/tor/torrc 中加入兩行設定。

HiddenServiceDir /var/lib/tor/ssh/
HiddenServicePort 22 127.0.0.1:22

第二行指令告知 tor 接受 onion 位址上的虛擬連接埠 22,並連線至本機的 127.0.0.1:22。Tor 透過 loopback 介面存取 sshd,這正是為何後續能讓 sshd 停止監聽公開位址的原因。若將該行指向 127.0.0.1:80 的網頁伺服器,同樣的兩行指令即可 發布 onion 位址上的網站,這是安裝 tor 後實用的第二項服務。

sudo systemctl reload tor
sudo cat /var/lib/tor/ssh/hostname

該指令會輸出 56 個 base32 字元,後接 .onion。這些字元即為該服務的編碼公開金鑰。此過程不涉及憑證授權中心,亦無須進行任何名稱註冊。

讓 tor 自行建立 /var/lib/tor/ssh/。若手動建立且擁有者錯誤,或權限設定鬆散於 0700,tor 將拒絕使用,並在日誌中回報該目錄權限過於寬鬆。目錄內的檔案即為服務識別碼:hs_ed25519_secret_key 即是該位址。請以 600 權限備份該目錄並存放於伺服器之外,因為一旦遺失,將導致位址變更,且必須修改所有客戶端的設定。

從工作站連線

您的工作站需要一個 Tor 客戶端,且完全無需進行任何設定。在 Debian 或 Ubuntu 上,請安裝 sudo apt install -y tor netcat-openbsd。安裝後,Tor 會在 127.0.0.1:9050 監聽 SOCKS5 代理。SOCKS 是一種通用的代理協定,第 5 版支援傳輸主機名稱而非 IP 位址,這正是此處的關鍵。

OpenSSH 本身沒有 SOCKS 客戶端,因此需要透過輔助程式來建立連線。請將以下內容加入 ~/.ssh/config。

Host myvps
  HostName xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.onion
  User admin
  ProxyCommand /usr/bin/nc -X 5 -x 127.0.0.1:9050 %h %p
  ServerAliveInterval 30

-X 5 用於選擇 SOCKS5,-x 127.0.0.1:9050 則指向本機的 Tor。%h 會將 .onion 名稱傳遞給 Tor,讓 Tor 在其網路內部進行解析。此處必須使用 OpenBSD 版本的 netcat。GNU netcat 沒有 -X 選項,執行時會出現 nc: invalid option -- 'X' 錯誤並終止。

ssh myvps

首次連線速度較慢,因為 Tor 必須先建立電路才能進行後續操作。請依照一般方式接受主機金鑰指紋。此後,常見的 SSH 金鑰處理方式 均適用。傳輸層已變更,但驗證方式維持不變。

若僅需臨時連線,可跳過設定檔步驟:直接執行 torsocks ssh admin@xxxxx.onion 即可達到相同效果。

新增 v3 用戶端授權

目前只要得知位址,任何人都能連線至您的 SSH banner 並嘗試猜測密碼。雖然 Onion 位址無法從目錄系統中列舉,因此位址本身具備機密性,但它仍可能透過 shell 歷史紀錄或提交至 git 儲存庫的設定檔等常見途徑外洩。用戶端授權機制可彌補此漏洞。服務會將其描述檔加密後發布,僅持有對應金鑰的用戶端才能解密;因此,即便有人知道位址但沒有金鑰,也無法定位該服務。

請在用戶端產生一組 x25519 金鑰對。以下流程源自 Tor Project 的 用戶端授權指南,並進行了一項調整。

openssl genpkey -algorithm x25519 -out /tmp/k1.prv.pem
grep -v " PRIVATE KEY" /tmp/k1.prv.pem | base64 -d | tail --bytes=32 | base32 | sed 's/=//g' > /tmp/k1.prv.key
openssl pkey -in /tmp/k1.prv.pem -pubout | grep -v " PUBLIC KEY" | base64 -d | tail --bytes=32 | base32 | sed 's/=//g' > /tmp/k1.pub.key

上述指令的原始版本使用了 base64pem -d,但標準 Ubuntu 安裝並不包含此工具,導致指令會因 base64pem: command not found 而中斷。GNU base64 -d 可解碼相同的 PEM 本體,請改用此工具。

在伺服器端,安裝公開金鑰。

sudo install -d -m 700 -o debian-tor -g debian-tor /var/lib/tor/ssh/authorized_clients
echo "descriptor:x25519:PASTE_PUBLIC_KEY_HERE" | sudo tee /var/lib/tor/ssh/authorized_clients/laptop.auth >/dev/null
sudo chown debian-tor:debian-tor /var/lib/tor/ssh/authorized_clients/laptop.auth
sudo systemctl reload tor

系統僅會讀取以 .auth 結尾的檔案。若將其儲存為 laptop.auth.txt,tor 會直接忽略該檔案且不會顯示錯誤訊息,導致服務仍對所有持有位址的人開放。

在用戶端,安裝私密金鑰。在 Ubuntu 上,tor daemon 以 debian-tor 使用者身分執行,無法讀取您家目錄中的檔案,請將目錄放置在該使用者可存取的位置。

sudo install -d -m 700 -o debian-tor -g debian-tor /var/lib/tor/onion_auth
echo "ADDRESS_WITHOUT_DOT_ONION:descriptor:x25519:PASTE_PRIVATE_KEY_HERE" | sudo tee /var/lib/tor/onion_auth/myvps.auth_private >/dev/null
sudo chown debian-tor:debian-tor /var/lib/tor/onion_auth/myvps.auth_private
sudo chmod 600 /var/lib/tor/onion_auth/myvps.auth_private

將 ClientOnionAuthDir /var/lib/tor/onion_auth 加入用戶端的 /etc/tor/torrc 並重新載入 tor。若您是以個人使用者身分執行 tor(例如 macOS 上的 Homebrew 版本),請將 ClientOnionAuthDir 指向 ~/.tor/onion_auth,並設定權限為 0700。

該檔案內的位址應為 56 個字元,且不包含 .onion 後綴。完成後,請刪除 /tmp/k1.prv.pem 與 /tmp/k1.prv.key。

現在測試雙向連線。ssh myvps 應仍能正常連線。從未持有金鑰的機器連線至相同位址時應會失敗。該失敗結果即證明授權機制已生效。

關閉 22 埠,請依此順序操作

請先設定安全防護機制。若您不慎將自己鎖在伺服器外,此指令將在 15 分鐘後自動復原以下兩項變更。

sudo systemd-run --on-active=15m --unit=ssh-rescue \
  /bin/sh -c 'ufw allow 22/tcp; rm -f /etc/systemd/system/ssh.socket.d/override.conf; systemctl daemon-reload; systemctl restart ssh.socket'

確認 Onion 路由仍可正常運作後,請執行 sudo systemctl stop ssh-rescue.timer 取消該排程。

接著,停止 sshd 在公開位址上的監聽。Ubuntu 24.04 透過 socket 單元啟用 SSH,因此 sshd_config 中的 ListenAddress 會被忽略:ssh.socket 才是監聽 socket 的擁有者,而非 sshd。請確認您屬於哪種情況。

systemctl is-enabled ssh.socket

若輸出顯示 enabled,請執行 sudo systemctl edit ssh.socket 並加入以下內容。

[Socket]
ListenStream=
ListenStream=127.0.0.1:22

空的 ListenStream= 會清除繼承自套件預設單元的值。若遺漏該行,您將會同時保留公開監聽埠並新增另一個監聽埠,這是此步驟最常見的失敗原因。

sudo systemctl daemon-reload
sudo systemctl restart ssh.socket
ss -tlnp | grep ':22'

ss 應顯示 127.0.0.1:22,且 0.0.0.0:22 不應有任何輸出。若 ssh.socket 已被停用,請將 ListenAddress 127.0.0.1 加入 /etc/ssh/sshd_config.d/10-onion.conf,執行 sudo systemctl restart ssh,再以相同的 ss 指令檢查。無論哪種情況,該輸出即為驗證依據。

接著處理防火牆,這與一般的 VPS 上的 ufw 規則管理 相同。請先執行 sudo ufw status numbered,並刪除其中列出的 SSH 規則。

sudo ufw status numbered
sudo ufw delete allow OpenSSH
sudo ufw default allow outgoing
sudo ufw default deny incoming
sudo ufw status verbose

請保留對外連線(outgoing traffic)的權限。Tor 會透過 443 與 9001 等埠連線至中繼節點,若設定預設拒絕(default-deny)的出站政策,將導致 Tor 無法啟動,同時也會斷絕您最後的存取路徑。大多數供應商在控制面板中還設有獨立的網路防火牆,請務必一併關閉 22 埠,否則無論 ufw 狀態為何,該埠仍可能對外開放。

若此伺服器執行 Docker,請在完成上述步驟前檢查其發布的連接埠。Docker 會自行將規則寫入相同的表格,且 容器連接埠會直接繞過 ufw 發布,因此僅設定 ufw 拒絕規則並不代表已完全封鎖。

重開機以驗證服務狀態

systemctl is-enabled tor@default
sudo reboot

若第一個指令未顯示該服務已啟用,請在重開機前執行 sudo systemctl enable tor@default。等待兩分鐘後,執行 ssh myvps。Tor 在開機後需要時間進行 bootstrap,因此 onion 位址會在機器啟動後一段時間才開始回應。

若服務無法恢復,請開啟主控台並讀取 sudo journalctl -u tor@default -b。該處會顯示 torrc 語法錯誤或目錄權限問題。您也可以在套用前先檢查 torrc 的編輯內容。

sudo -u debian-tor tor --verify-config

與 WireGuard 通道相比的成本

與 自行架設 VPS 上的 WireGuard VPN 相比,Onion service 的速度較慢且較不穩定。在投入使用前,請務必誠實評估此取捨。

延遲。 客戶端電路包含三個中繼站,服務端則增加另外三個,因此您的按鍵輸入大約會經過全球隨機挑選的六台機器。互動式輸入會有明顯延遲,檔案傳輸速度也較慢。WireGuard 僅增加一個節點。請使用 time ssh myvps 'echo ok' 測量您的實際情況,因為數值取決於 tor 當下建立的電路,且會在 tor 重新建立電路時改變。

關鍵路徑上的使用者空間 daemon。 WireGuard 位於核心層,隨網路啟動。Tor 則是一個必須啟動、引導並連接到 guard relay 才能運作的行程。當它失敗時,您必須透過服務供應商的控制台進行排解。

時鐘準確度。 Onion service 的描述檔是依據時間週期發布的,因此若系統時鐘嚴重偏差,將導致位址查詢失敗,且不會有任何明確的錯誤訊息。timedatectl 應回報 System clock synchronized: yes。

您獲得的回報是無需再依賴防火牆規則正確性的暴露防護。沒有可掃描的連接埠,也沒有可獲取的 banner,且位址本身就是公開金鑰,因此端點在 SSH 啟動前即已驗證其身分。

實務上的建議通常是兩者並用。將 WireGuard 作為日常連線路徑,並保留 Onion service 作為 WireGuard 設定錯誤時的備援路徑。這樣只需開啟一個 UDP 連接埠,而非公開 SSH 連接埠。這些措施都無法取代 強化 sshd 本身:僅限金鑰驗證與非 root 登入仍然至關重要,因為 Onion service 僅保護網路路徑,並不涵蓋路徑之後的任何層面。

故障模式與常見錯誤訊息

Tor 無法通過 Bootstrapped 0%。 這是因為對外流量遭到封鎖,或是系統時間偏差過大。請使用 sudo ufw status verbose 檢查對外連線策略,接著執行 timedatectl。

systemctl status tor 顯示 active (exited)。 這在 Debian 與 Ubuntu 上屬於正常現象。請改為閱讀 tor@default。

找不到描述檔 (Descriptor)。 Tor 會回傳 SOCKS 擴充錯誤 F0,即「Onion Service Descriptor Can Not be Found」。這可能是因為重新載入後描述檔尚未發布(需要一點時間),或是伺服器上的 tor 服務未執行。

F4,「Onion Service Missing Client Authorization」。 客戶端缺少 tor 可用的對應 .auth_private。請確認 torrc 中已包含 ClientOnionAuthDir,目錄權限為 0700,檔案名稱以 .auth_private 結尾,且 debian-tor 有權讀取該檔案。

F5,「Onion Service Wrong Client Authorization」。 私鑰與伺服器上的 .auth 檔案不符。base32 字串中若包含多餘的 = 或意外的換行符號,皆會導致此錯誤。

nc: invalid option -- 'X'。 系統安裝的是 GNU netcat 而非 OpenBSD 版本。請執行 sudo apt install -y netcat-openbsd。

Could not resolve hostname。 ssh 嘗試使用一般 DNS 解析,但 .onion 沒有對應記錄,導致 ProxyCommand 未執行。~/.ssh/config 中的 Host 模式與您輸入的名稱不符。

Permission denied (publickey)。 通道已建立且 tor 任務完成。請將此視為 一般的 publickey 權限拒絕問題,此時已與 tor 無關。

FAQ

使用 onion service 是否代表我的 VPS 上沒有開啟任何連接埠?

是的,只要將 sshd 綁定至 127.0.0.1 且防火牆阻擋所有入站流量即可。Tor 會建立連往中繼站(relay)的出站 TCP 連線,您的連線會透過該路徑傳回,因此伺服器上不會有任何服務在公用位址上監聽連線。您可以透過在伺服器執行 ss -tlnp 並從外部進行連接埠掃描來驗證。請勿忽略雲端供應商控制台中的網路防火牆,該防火牆與 ufw 是分開的,必須一併關閉。

單憑 .onion 位址對 SSH 來說足夠安全嗎?

不足夠。該位址長度為 56 個字元,無法透過目錄系統猜測或枚舉,因此具有秘密的特性,但它可能會透過 shell 歷史紀錄與設定檔洩漏。請加入 v3 用戶端授權(client authorisation)。啟用後,服務描述檔會使用您的用戶端金鑰加密,因此僅持有位址的人只會收到擴充錯誤 F4,完全無法觸及 sshd。

如果 Tor 在重新開機後無法啟動該怎麼辦?

您將完全失去 SSH 存取權,因為 onion 位址是唯一的進入途徑。這就是為什麼在關閉 22 埠之前,必須先測試供應商提供的控制台功能。此外,Tor 在開機後需要時間進行引導(bootstrap),因此該位址回應的時間會比機器回應 ping 的時間晚。如果它始終沒有回應,請透過控制台登入並讀取 sudo journalctl -u tor@default -b,通常會顯示 torrc 語法錯誤或 /var/lib/tor/ssh 的權限問題。

SSH over Tor 是否比 WireGuard 慢?

是的,差距很大。連線至 onion service 會隨機經過約六個中繼站,而 WireGuard 則是直接連往伺服器的一次加密跳躍。操作時會有延遲感,傳輸速度也較慢。常見的配置是將 WireGuard 用於日常工作,並將 onion service 保留為當 VPN 設定損毀時的緊急備援路徑。