Appearance
OpenSSL 自簽憑證產生
以 OpenSSL 腳本產生自簽 CA 憑證與伺服器憑證,適用於內部測試環境與私有服務的 HTTPS 設定。
概述
自簽憑證(Self-signed Certificate)是由自建的 CA 根憑證簽發的 TLS 憑證。它不在公共 CA 信任鏈內,所以瀏覽器預設不信任——但只要將自建的 CA 根憑證匯入用戶端信任庫,就能建立完整的 HTTPS 加密與身分驗證,適合內部系統、開發測試環境、Kubernetes 叢集內部通訊等場景。
現代瀏覽器的限制: Chrome、Firefox 等瀏覽器已強制要求憑證包含 Subject Alternative Name(SAN),僅設定 Common Name(CN)已無法通過驗證。本文腳本透過 v3.ext 設定檔正確填入 SAN。
核心內容
自簽憑證的兩層架構
標準做法是建立兩層憑證結構:
- CA 根憑證(
ca.crt):自簽,代表「信任根」。需手動匯入每個用戶端的信任庫(一次性操作)。 - 伺服器憑證(
server.crt):由 CA 根憑證簽發,實際部署在伺服器。
好處是:只要將 CA 根憑證匯入一次,之後由同一個 CA 簽發的所有伺服器憑證都會被自動信任,不需重複匯入。
v3 擴充設定(SAN 的必要性)
v3.ext 設定檔的作用是為伺服器憑證加入 X.509 v3 擴充,其中最關鍵的是 subjectAltName(SAN):
ini
authorityKeyIdentifier=keyid,issuer # 標示簽發者資訊
basicConstraints=CA:FALSE # 宣告此憑證非 CA,不可再簽發
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names # SAN:瀏覽器驗證的必要欄位
[alt_names]
DNS.1 = 10.22.101.202.sslip.io # 憑證對應的域名
IP.1 = 10.22.101.202 # IP 位址直接存取時也需要 IP SAN缺少 SAN 的憑證在現代瀏覽器中會觸發 ERR_CERT_COMMON_NAME_INVALID 錯誤。同時加入 DNS 與 IP 兩種 SAN 條目,可確保不論用域名或 IP 存取服務都能通過驗證。
伺服器憑證有效期
CA 根憑證可設定較長有效期(例如 3600 天),因為只有在輪替 CA 時才需要重新將根憑證發送給所有用戶端。伺服器憑證有效期應設為 397 天——這是 Apple/Chrome 政策規定的最長信任期限,超過此天數的憑證在部分平台會被標記為不受信任,即使技術上尚未過期。
sslip.io 的應用技巧
sslip.io 是一個公共 DNS 服務,自動將嵌入 IP 的域名請求解析回該 IP(例如 10.22.101.202.sslip.io → 10.22.101.202)。
這讓你可以用域名格式(而非純 IP)申請憑證,解決某些工具或瀏覽器不接受純 IP 憑證(subjectAltName = IP:...)的問題。
關鍵要點
- SAN(v3.ext)是現代瀏覽器的強制要求,不可省略
- CA 根憑證需手動匯入用戶端信任庫,否則仍顯示不安全警告
- CA 根憑證有效期可設為 3600 天(約 10 年),伺服器憑證應設 397 天(Chrome/Apple 最長信任期限)
- 同時加入
DNS.1與IP.1SAN,確保域名與 IP 直接存取都能通過驗證 - sslip.io 讓 IP 位址也能以域名格式申請憑證
- 私鑰(
ca.key、server.key)需妥善保管,不可外洩
實際應用
- Kubernetes TLS Secret:將
server.crt和server.key打包為 K8s TLS Secret,供 Ingress 使用 - 本地開發 HTTPS:搭配 Nginx 或 Caddy 設定本地 HTTPS 環境
- 內部服務:不需公開可信憑證的私有服務(可搭配 VPN 或 Cloudflare Tunnel 的 Full Strict 模式使用)
- 年度輪替 SOP 可參考 維運 SOP:憑證與帳密更新
部署設定參考
以下為實際部署時使用的完整設定,供日後查詢與複製使用。
環境參數
| 參數 | 值 |
|---|---|
| Domain | sslip.io |
| Host IP | 10.22.101.202 |
| Common Name (CN) | 10.22.101.202.sslip.io |
| 憑證有效天數 | 3600(約 10 年) |
| 金鑰長度 | RSA 2048 bit |
產出檔案說明
| 檔案 | 用途 | 是否需要保留 |
|---|---|---|
ca.key | CA 私鑰 | 是(保密保管) |
ca.crt | CA 根憑證 | 是(匯入用戶端信任庫) |
server.key | 伺服器私鑰 | 是(部署至伺服器) |
server.crt | 伺服器憑證 | 是(部署至伺服器) |
server.csr | 憑證簽署請求 | 否(過渡檔案可刪除) |
v3.ext | SAN 設定檔 | 否(過渡檔案可刪除) |
完整產生腳本
bash
#!/bin/bash
set -euo pipefail
DOMAIN="sslip.io"
HOST="10.22.101.202"
COMMON_NAME=$HOST.$DOMAIN
mkdir -p ssl
cd ssl
# 1. 產生 CA 私鑰
openssl genrsa -out ca.key 2048
# 2. 產生自簽 CA 憑證(3600 天,約 10 年)
openssl req -x509 -new -nodes -key ca.key \
-subj "/CN=My rootCA/O=${DOMAIN}" \
-sha256 -days 3600 -out ca.crt
# 3. 產生伺服器私鑰與 CSR
openssl req -new -newkey rsa:2048 -sha256 -nodes \
-keyout server.key \
-subj "/CN=${COMMON_NAME}" \
-out server.csr
# 4. 建立 v3 擴充設定檔(含 DNS + IP 雙 SAN)
cat << EOF > v3.ext
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = $COMMON_NAME
IP.1 = $HOST
EOF
# 5. 使用 CA 簽發伺服器憑證(397 天,符合瀏覽器最長信任限制)
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key \
-CAcreateserial -extfile v3.ext \
-sha256 -out server.crt -days 397操作指令
bash
# 驗證憑證內容(確認 SAN 欄位存在)
openssl x509 -in ssl/server.crt -text -noout | grep -A2 "Subject Alternative Name"
# 驗證憑證由指定 CA 簽發
openssl verify -CAfile ssl/ca.crt ssl/server.crt
# 將 CA 根憑證建立為 K8s TLS Secret(ca 憑證信任鏈)
kubectl create secret generic ca-cert --from-file=ca.crt=ssl/ca.crt -n <namespace>
# 將伺服器憑證建立為 K8s TLS Secret
kubectl create secret tls tls-cert \
--cert=ssl/server.crt \
--key=ssl/server.key \
-n <namespace>部署至 Nginx
nginx
ssl_certificate /path/to/ssl/server.crt;
ssl_certificate_key /path/to/ssl/server.key;匯入 CA 憑證至 Ubuntu 信任庫
bash
sudo cp ssl/ca.crt /usr/local/share/ca-certificates/my-rootca.crt
sudo update-ca-certificates若要讓瀏覽器或系統信任此自簽憑證,必須將
ca.crt匯入作業系統或瀏覽器的「受信任根憑證授權單位」清單。
相關概念
- 維運 SOP:憑證與帳密更新 — 多系統年度憑證輪替的完整 SOP
- GitLab Omnibus (Docker) HTTPS 連線失敗排除 SOP — GitLab 服務端憑證部署後的排錯
- Cloudflare Tunnel x Synology NAS 架構指南 — 使用 Cloudflare Origin Certificate 的替代憑證方案
來源
- 原始素材:OpenSSL 自簽憑證產生腳本
- 原始素材:OpenSSL 自簽 SSL 憑證產生腳本