跳轉至

SSHwifty

概述

SSHwifty 係一個以瀏覽器為基礎嘅開源 Web SSH / Telnet 客戶端,管理員可以唔使安裝 PuTTY、Termius 或者任何本地終端機程式,直接透過瀏覽器開一個互動式 shell 連入內部伺服器。喺 benhoweb.com 嘅實際部署入面,SSHwifty 唔會直接暴露畀公網,而係由 Cloudflare Access 做前置閘道;所有連線要先經過 Cloudflare 邊緣節點驗證身份,再由 Authentik 作為 Identity Provider 提供 SSO 同 MFA。

換句話講,SSHwifty 自己唔係「最終安全邊界」,真正嘅保護鏈係:

瀏覽器 → Cloudflare Access → Authentik 身份驗證 → Cloudflare Tunnel → Docker cf_network → SSHwifty → 目標 SSH server

架構

呢個站嘅 SSHwifty 容器所屬 Docker network 係外部網絡 cf_networkcf_network 由其他容器共用,例如 Cloudflare Tunnel、Nginx Proxy Manager 或者同網段嘅服務。SSHwifty 被分配到靜態 IP 172.21.0.73,對外流量經 Cloudflare Tunnel 入到呢個 IP 的 8182 port;主機層面並無 publish 任何 port,所以主機上唔會見到一個隨意暴露嘅 listening socket。

Cloudflare Tunnel 同 Docker Compose 都喺同一個 L2 bridge 網絡入面,所以 upstream 可以直接用服務名稱 http://sshwifty:8182,亦都用固定 IP http://172.21.0.73:8182。採用外部網絡嘅好處係:唔需要靠 container 互傳、唔需要為每個服務重新建立 default bridge,而可以俾 Cloudflare Tunnel 單一網絡路徑轉發到 SSHwifty。

部署

本機實際使用嘅 Docker Compose 節選如下:

services:
  sshwifty:
    image: niruix/sshwifty:latest
    container_name: sshwifty
    restart: unless-stopped
    networks:
      cf_network:
        ipv4_address: 172.21.0.73
    environment:
      TZ: Asia/Hong_Kong
      SSHWIFTY_HOSTNAME: ${SSHWIFTY_HOSTNAME}
      SSHWIFTY_SHAREDKEY: ${SSHWIFTY_SHAREDKEY}
      SSHWIFTY_LISTENPORT: 8182

networks:
  cf_network:
    external: true

啟動之前要確保 cf_network 已存在;如果未建立,需要先執行 docker network create cf_network,並確認 172.21.0.73 未被其他容器佔用。.env 入面保存 SSHWIFTY_HOSTNAMESSHWIFTY_SHAREDKEY,唔好將敏感值寫死喺 Compose 檔案入面。.env 同 Compose 檔案一律要放入 git 以外嘅私有位置,例如 /opt/benhoweb/sshwifty/

配置

SSHWIFTY_HOSTNAME 一定要同 Cloudflare Access Application 嘅網址一致,例如 sshwifty.benhoweb.com。如果呢個值同瀏覽器輸入嘅 hostname 唔一致,SSHwifty 生成嘅 WebSocket URL 就好可能用錯 Host,導致連線握手失敗。

SSHWIFTY_SHAREDKEY 係一個全局限定嘅共享密鑰,用嚟保護 SSHwifty 自身嘅 HTTP/WebSocket 入口。注意它唔可以取代 CF Access 嘅用戶身份認證;CF Access 負責「邊個用戶可以登入」,而 shared key 負責「容器內唔接受未經 CF Access 放行嘅請求」。

Authentik 方面,需要開一個 OIDC Provider 畀 Cloudflare Access。Redirect URI 通常係 Cloudflare Access 提供嘅 /cdn-cgi/access/callback 地址;client ID 同 client secret 要填入 Cloudflare Access 應用程式設定。登入 policy 可以只允許特定 Authentik group,例如 benhoweb-admins

維運與監控

日常維運可以先用 docker ps 確認容器狀態,再用 docker logs sshwifty --tail 100 -f 睇連線紀錄。SSHwifty 成功建立 WebSocket 或 SSH session 時,日誌會顯示來源、目標主機以及結束原因;如果係 Access 攔截,就要去 Cloudflare Access 睇 audit log;如果係 Authentik 嘅 MFA/SSO 問題,就要去 Authentik 嘅 Events 頁面追蹤。

網絡層面可以執行:

docker inspect sshwifty

檢查 NetworkSettings.Networks.cf_network.IPAddress 是否仍然係 172.21.0.73。若果容器經常重建,固定 IP 有機會同其他 static assignment 撞,因此要定期睇 docker network inspect cf_network

資源監控方面,docker stats sshwifty 可以用嚟睇 CPU/記憶體。SSHwifty 本體好輕量,但每個活躍終端 session 會消耗一定記憶體,所以如果同時有大量用戶開 session,就要留意容器 memory limit。現時 Compose 未設 mem_limit,喺高用量環境可以考慮加入。

常見問題

點樣先可以真正安全?
唔好淨係靠 SSHwifty shared key。一定要保留 Cloudflare Access policy,並由 Authentik 做身份來源;最好再開 MFA。CF Access 係第一道閘,shared key 只係第二道內部保護。

WebSocket 一直連唔到?
多數係 SSHWIFTY_HOSTNAME 錯,或者 Cloudflare Access Application 嘅 domain 同實際訪問網址唔一致。再檢查 Cloudflare Tunnel 嘅 upstream 是否指到 sshwifty:8182,以及 cf_network 是否真係同 Tunnel 共用。

時區唔正確?
容器已經設定 TZ=Asia/Hong_Kong,同時 mount /usr/share/zoneinfo 做 read-only。如果日誌仍然顯示 UTC,通常係 base image 冇讀取 mount 或者 Docker restart 後未重新建立容器;執行 docker compose up -d --force-recreate

固定 IP 冇咗?
cf_network 係 external,如果原先建立時嘅 subnet 唔係 172.21.0.0/24,個 static IP 就唔合法。確認為同一個 Docker network,並檢查 IP 是否仍然空閒。

Access 登入一直 redirect?
多數係 Authentik Provider 嘅 redirect URI 同 Cloudflare Access callback 唔匹配。重新核對 Authentik OIDC 設定,確認 Client ID/Secret 正確,並確保 Cloudflare Access 可以 reach Authentik。

相關鏈接

docker cloudflare-tunnel authentik litellm cloudflare-zero-trust Portainer

來源

自動生成(2026-08-19 容器覆蓋率補完第二批)