使用 OpenSSH 與 Nginx 建立自架隧道服務
綜合科技

使用 OpenSSH 與 Nginx 建立自架隧道服務

AI News Bot
2026-10-05
預計閱讀 2 分鐘原文來源

使用 OpenSSH 與 Nginx 建置自架隧道服務

在部落格或開發測試時,常會遇到 本機預覽只能在 localhost:8080 的窘境。市面上有 ngrok、Cloudflare Quick Tunnels 等商業方案,也有 frp、localtunnel 需要額外客戶端的自建工具;甚至有只需要 SSH 客戶端、但依賴特定 SSH 伺服器(如 sish)的解法。本文示範如何僅憑 OpenSSH 與 Nginx,在自己的伺服器上完成安全的隧道服務,完全不依賴第三方平台。

1. 由遠端伺服器轉發埠至本機服務

使用 ssh -R 0:127.0.0.1:41535 user@remote,將遠端伺服器的隨機空閒埠(指定 0 讓核心自動分配)映射到本機的 41535 埠。這一步只需要 OpenSSH,無需額外軟體。

2. Nginx 代理與 DNS 設定

取得一個子域,例如 https://p41535.ssh.luffy.cx,在 Nginx 中設定:


location / {

    proxy_pass http://127.0.0.1:41535;

    # 其他 proxy 設定...

}

同時在 DNS 服務(本文以 Route 53 為例)為 *.ssh.luffy.cx 新增通配記錄,並透過 Let’s Encrypt 申請通配 SSL/TLS 憑證。本文的 acme.luffy.cx 區域已由 NixOS 自動完成憑證簽發。

3. 以埠號作為唯一「祕密」的風險

因為核心分配的隨機埠號熵值不高(僅 15‑16 位元,且偏好奇數),若僅靠埠號保護,仍有被窮舉的可能。為提升安全性,我們導入 ngx_http_secure_link_module(Nginx 的安全連結模組),透過雜湊驗證防止未授權存取。

3.1 雜湊機制

模組會對以下三個值計算 MD5 雜湊(雖非最強,但足以防止一般攻擊):

  1. 到期時間戳記(Unix epoch)

  2. 隨機埠號

  3. 事先設定的祕密字串

產生的雜湊再以 Base64 編碼,放入 URL 的「使用者名稱」部份,格式為:


<hash>,<expire_timestamp>

4. Nginx 端的驗證流程

  1. 客戶端以 HTTP Basic Auth 方式送出上述使用者名稱(大多數 HTTP 客戶端,包括 curl,皆支援)。

  2. Nginx 透過 $remote_user 變數取得該字串,利用 map 指令切割出雜湊與時間戳記。

  3. 交給 secure_link 模組比對計算結果;若不符回傳 401 Unauthorized,若已過期回傳 410 Gone。

  4. 成功驗證後,移除 Authorization 標頭,並將請求轉交給本機服務,同時加入 WebSocket 代理相關指令。

5. 完整設定範例(摘要)


map $remote_user $secure_link {

    default "";

    "~^(?<hash>[^,]+),(?<exp>\d+)$" $hash,$exp;

}

secure_link $secure_link;

secure_link_md5 "$arg_expires$arg_port$secret";

if ($secure_link = "") { return 401; }

if ($secure_link = "0") { return 410; }

proxy_set_header Authorization "";

proxy_pass http://127.0.0.1:$arg_port;

註:$arg_port 為先前由 SSH 隧道分配的埠號,$secret 為自行定義的祕密字串。

結語與未來展望

透過 OpenSSH 與 Nginx 的組合,我們不僅省下商業隧道服務的費用,更能自行掌控憑證與 DNS 設定,確保資料不外流。雖然 MD5 雜湊的安全性有限,但在「埠號 + 時間戳記 + 祕密」的三層防護下,已足以抵禦一般惡意掃描。未來若需求更高,可改用 SHA‑256 或 HMAC‑SHA256,並將祕密儲存在安全金鑰管理服務(如 AWS KMS)中,進一步提升抗攻擊能力。

對於開發者而言,這套自架隧道不僅適用於部落格預覽,亦可延伸至 CI/CD 測試環境、內部 API 示範等多種場景。只要掌握好 SSH 轉發與 Nginx 安全連結的配置,便能在自己的雲端或 VPS 上,快速、可靠地提供外部存取。

分享