跳到內容
繁體中文

TLS 與憑證

正式部署起來就是 https:docker compose up -d 之後,網頁介面在 443,從 80 進來的明文請求會被導過去。 憑證預設由系統自己簽發,也可以換成你自己的。 這一頁講憑證來源怎麼選、CA 怎麼派發到使用者端、已經有自家 ingress 時怎麼接, 以及怎麼確認 TLS 與連線通道的 wss 真的生效。

  • 一個對外主機名,填在 .env 的 TLS_DOMAIN。內網 DNS 或使用者端 hosts 解析得到就夠,不必是公開註冊的網域。
  • .env 的 PUBLIC_BASE_URL 指向同一個主機名的 https 位址。單一登入的回呼位址由這個值組成。
  • 要用自己的憑證時,一組憑證鏈與私鑰(fullchain.pem 與 privkey.pem)。
  • 對外只發布兩個埠,預設 443(https)與 80(http,只做導向),網址不必帶埠。主機上已有服務占用這兩個埠時,在 .env 把 TLS_HTTPS_PORT 與 TLS_HTTP_PORT 改成別的一組(常見是 8443 與 8088),網址就要帶埠。

內建代理提供 TLS 1.2 以上、HSTS,以及終端與圖形連線需要的 WebSocket upgrade 轉發。 設定檔裡的主機名在啟動時由 TLS_DOMAIN 帶入,檔案本身不必編輯。 應用層也已備妥:前端依頁面協定自動在 ws 與 wss 之間切換,存取憑證走 Authorization 標頭而不放在網址上。

.env 的 TLS_MODE 出廠是 selfsigned。首次啟動時系統在 tls/ 產生一組本地 CA 與伺服器憑證, 之後每次啟動沿用。憑證涵蓋 TLS_DOMAIN 的主機名,以及 TLS_IP_SAN 列出的位址。 CA 私鑰留在主機的 tls/ca-private/,不進代理容器。

.env
TLS_DOMAIN=jumper.example.internal
TLS_IP_SAN=10.0.0.5 # 也要能用位址連時填,逗號分隔
PUBLIC_BASE_URL=https://jumper.example.internal

這三個值留空時,bash scripts/quickstart.sh 會依本機主機名與位址自動填好, 並在最後印出要開的網址與 CA 憑證的下載連結。已經填好的值原樣保留。

Terminal window
docker compose up -d

接著把 CA 憑證派發到會連進來的機器:

Terminal window
curl -sk https://jumper.example.internal/custodexa-ca.crt -o custodexa-ca.crt

Windows 網域用群組原則(電腦設定 → Windows 設定 → 安全性設定 → 公開金鑰原則 → 受信任的根憑證授權單位)派發,macOS 與行動裝置用 MDM 設定描述檔, 單機則手動匯入系統的受信任根憑證存放區。派發完成後,瀏覽器就把這個站顯示為受信任的連線。 CA 憑證是公開資料,可以直接發給使用者。

手上已經有公開 CA 或機構 CA 簽發的憑證時:

  1. 憑證鏈放 tls/fullchain.pem,私鑰放 tls/privkey.pem。
  2. .env 設 TLS_MODE=provided、TLS_DOMAIN(與憑證上的主機名一致), 以及 PUBLIC_BASE_URL=https://<主機名>(對外埠不是 443 時要帶埠)。
  3. docker compose up -d。

缺任何一個檔案,啟動會停在憑證準備這一步並指名缺哪一個,代理不會帶著半套設定起來:

Terminal window
docker compose logs tls-init

tls/ 裡已經有的憑證,之後每次啟動都沿用。要換一組,先把檔案刪掉再啟動。

機構有自己的 CA 時,在本機產私鑰與憑證簽發請求,SAN 帶上該主機名,送交簽發:

Terminal window
openssl req -newkey rsa:2048 -nodes -keyout tls/privkey.pem \
-out custodexa.csr -subj "/CN=jumper.bnc.prod" \
-addext "subjectAltName=DNS:jumper.bnc.prod"

簽回來之後,把伺服器憑證與中繼憑證依序串成 tls/fullchain.pem(葉憑證在最前面), TLS_MODE 設 provided 後重啟。使用者端對這張 CA 的信任通常由 AD 群組原則或 MDM 派發。 內網的識別提供者若走 https 且用同一把 CA,把 CA 憑證加進後端容器的信任存放區。

前面已經有雲端負載平衡器,或既有的 nginx、Traefik 時,用 overlay 把內建代理讓開, 由前端自己發布 HTTP 埠給你的 ingress 連:

Terminal window
docker compose -f docker-compose.yml -f docker-compose.external-ingress.yml up -d

在 .env 設 COMPOSE_FILE=docker-compose.yml:docker-compose.external-ingress.yml, 之後 up -d、ps、down 就不必每次帶 -f。 這個形態下前端發布 80(.env 的 HTTP_PORT 可改),對外 TLS 由你的 ingress 承載: TLS 1.2 以上、可信憑證、HTTP 轉 HTTPS、HSTS,以及 WebSocket upgrade 轉發; ingress 到本主機這一段若跨越不可信網段,該段也要加密。 PUBLIC_BASE_URL 填使用者實際看到的 https 位址。 轉給前端的 Host 標頭要帶上使用者實際連的對外埠(不是 443 時就要帶):未設 CORS_ALLOWED_ORIGINS 時, 後端只接受同源請求,判斷方式是把請求的 Origin 與 Host 相比,Host 少了埠,帶憑證的請求就會被判成跨源。 TRUSTED_PROXIES 填你的 ingress 位址或它所在的網段:這決定每個請求歸因到哪個來源位址, 也就決定稽核紀錄裡記到什麼、登入限速用什麼當計數鍵。 (用內建代理的預設形態下,bash scripts/quickstart.sh 會把它填成 Docker 子網。)

內建範本涵蓋一般需求。要改的話複製一份,.env 指過去,原檔不動:

.env
cp docker/reverse-proxy/nginx-tls.conf.template tls/custodexa.conf.template
TLS_NGINX_TEMPLATE=./tls/custodexa.conf.template

可以改的位置:server_name(預設由 TLS_DOMAIN 帶入)、憑證路徑、額外標頭 (HSTS 的 max-age 與 includeSubDomains、preload 依你的網域策略), 以及 upstream(同一個 Docker 網路用服務名 frontend:80)。 改完 docker compose up -d tls-proxy 套用。

要用主機上既有的 nginx 而不跑代理容器:用上面的 ingress overlay 讓前端發布 HTTP 埠 (建議把映射改成 127.0.0.1:8088:80 綁在 loopback),設定沿用同一份範本, upstream 改指 127.0.0.1:8088,server_name 與憑證路徑換成你的。 nginx 1.25.1 以前的版本把 http2 on; 改寫成 listen 443 ssl http2; 即可。 其他代理(Caddy、Traefik、雲端負載平衡器)滿足上一節那組契約即可, docker/reverse-proxy/Caddyfile.example 是等效的 Caddy 版本。

Terminal window
docker compose ps # tls-proxy 為 Up;tls-init 備好憑證後結束
curl -sI http://localhost/ | head -1 # 301,導向 https
curl -skI https://localhost/ | head -1 # 200
curl --cacert tls/ca-public/custodexa-ca.crt -sI https://<TLS_DOMAIN>/ | head -1 # 自簽模式:200

第四項用 CA 憑證驗證整條信任鏈,回 200 代表憑證與主機名對得上。 再登入開一條連線,瀏覽器開發者工具的 Network 分頁應該看到 wss:// 的串流。

換發登入狀態用的憑證走 HttpOnly cookie。政策頁「連線與帳號」段有一個 「登入狀態僅在 https 連線保存」開關,出廠開啟。開啟時 cookie 只在加密連線上送出, 儲存後下一次發放的 cookie 就採新值,不需要重啟。

政策尚無值時,初值依序取 .env 的 AUTH_REFRESH_COOKIE_SECURE、PUBLIC_BASE_URL 的協定、出廠預設。 啟動日誌會印出生效值與它的來源:

Terminal window
docker compose logs backend | grep "refresh cookie"

稽核紀錄的時間戳來自宿主時鐘。正式部署請在宿主啟用時間同步服務,時間源採 UTC。

  • 傳輸安全頁的通道清冊列出各通道目前的加密狀態,其中網頁層標為部署方管理,並附偏離提示。
  • 清冊可匯出快照,快照帶產生時間與產生者,匯出動作本身進稽核。
  • 政策開關的變更留一筆紀錄,含變更者與變更前後的值。