Let's Encrypt Wildcard 萬用憑證申請

Let's Encrypt Wildcard Certificate with DNS Challenge

Wildcard 憑證概述

Wildcard 憑證(萬用憑證)是一種特殊的 SSL/TLS 憑證,可以保護一個網域及其所有的子網域。例如,一張 *.example.com 的萬用憑證可以同時保護 www.example.comapi.example.comblog.example.com 等所有子網域。

萬用憑證的優點

  • 成本效益:只需要一張憑證即可保護多個子網域
  • 管理簡便:不需要為每個子網域單獨申請和管理憑證
  • 彈性擴展:新增子網域時無需重新申請憑證

萬用憑證的限制

  • 只能保護一層子網域(*.example.com 無法保護 sub.api.example.com
  • 必須使用 DNS-01 驗證方式

DNS-01 驗證方式說明

Let’s Encrypt 提供多種驗證方式來確認您對網域的所有權,但申請萬用憑證時,只能使用 DNS-01 驗證。

DNS-01 驗證的運作方式:

  1. Let’s Encrypt 會提供一個隨機的驗證 Token
  2. 您需要在網域的 DNS 設定中新增一筆 _acme-challenge 的 TXT 記錄
  3. Let’s Encrypt 查詢此 DNS 記錄來驗證您的網域所有權

安裝 Certbot

Certbot 是 Let’s Encrypt 官方推薦的用戶端工具,支援多種作業系統。

Ubuntu/Debian

1
2
3
4
5
6
7
8
# 更新套件列表
sudo apt update

# 安裝 Certbot
sudo apt install certbot -y

# 驗證安裝
certbot --version

CentOS/RHEL

1
2
3
4
5
# 啟用 EPEL 儲存庫
sudo yum install epel-release -y

# 安裝 Certbot
sudo yum install certbot -y

macOS(使用 Homebrew)

1
brew install certbot

手動申請 Wildcard 憑證

使用手動模式申請萬用憑證,需要手動新增 DNS TXT 記錄。

1
2
3
# 申請萬用憑證
sudo certbot certonly --manual --preferred-challenges dns \
  -d "*.example.com" -d "example.com"

執行後,Certbot 會顯示需要新增的 DNS TXT 記錄:

1
2
3
4
5
6
Please deploy a DNS TXT record under the name:
_acme-challenge.example.com
with the following value:
AbCdEfGhIjKlMnOpQrStUvWxYz1234567890

Press Enter to Continue

請依照指示到您的 DNS 服務商後台新增 TXT 記錄,等待 DNS 傳播後再按 Enter 繼續。

驗證 DNS 記錄

在按 Enter 之前,建議先驗證 DNS 記錄是否已正確傳播:

1
2
3
4
5
# 使用 dig 查詢 TXT 記錄
dig -t TXT _acme-challenge.example.com +short

# 或使用 nslookup
nslookup -type=TXT _acme-challenge.example.com

使用 DNS 外掛自動驗證(以 Cloudflare 為例)

手動驗證在憑證續約時非常不便,建議使用 DNS 外掛來自動化整個流程。

安裝 Cloudflare DNS 外掛

1
2
3
4
5
# Ubuntu/Debian
sudo apt install python3-certbot-dns-cloudflare -y

# 使用 pip 安裝
sudo pip install certbot-dns-cloudflare

建立 Cloudflare API 憑證檔案

首先,到 Cloudflare 後台取得 API Token,建議使用 API Token 而非 Global API Key。

建立憑證設定檔:

1
2
3
4
5
# 建立設定目錄
sudo mkdir -p /etc/letsencrypt/cloudflare

# 建立憑證檔案
sudo nano /etc/letsencrypt/cloudflare/credentials.ini

檔案內容:

1
2
3
4
5
6
# Cloudflare API Token(推薦方式)
dns_cloudflare_api_token = YOUR_API_TOKEN_HERE

# 或使用舊版 API Key(不推薦)
# dns_cloudflare_email = your-email@example.com
# dns_cloudflare_api_key = YOUR_GLOBAL_API_KEY

設定檔案權限:

1
sudo chmod 600 /etc/letsencrypt/cloudflare/credentials.ini

使用 Cloudflare 外掛申請憑證

1
2
3
sudo certbot certonly --dns-cloudflare \
  --dns-cloudflare-credentials /etc/letsencrypt/cloudflare/credentials.ini \
  -d "*.example.com" -d "example.com"

設定自動續約

Let’s Encrypt 憑證有效期為 90 天,建議設定自動續約。

測試續約

1
2
# 測試續約流程(不會真正續約)
sudo certbot renew --dry-run

設定 Cron 排程

1
2
3
4
5
# 編輯 crontab
sudo crontab -e

# 新增以下排程(每天凌晨 3 點檢查並續約)
0 3 * * * /usr/bin/certbot renew --quiet --post-hook "systemctl reload nginx"

使用 Systemd Timer(推薦)

現代 Linux 發行版通常已內建 Certbot 的 systemd timer:

1
2
3
4
5
6
7
8
9
# 檢查 timer 狀態
sudo systemctl status certbot.timer

# 啟用 timer
sudo systemctl enable certbot.timer
sudo systemctl start certbot.timer

# 查看排程
sudo systemctl list-timers

Nginx 設定使用萬用憑證

憑證申請成功後,檔案位置通常在 /etc/letsencrypt/live/example.com/

基本設定

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
server {
    listen 443 ssl http2;
    server_name *.example.com;

    # SSL 憑證設定
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    # SSL 安全設定
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256;
    ssl_prefer_server_ciphers off;

    # HSTS 設定
    add_header Strict-Transport-Security "max-age=63072000" always;

    root /var/www/html;
    index index.html;
}

# HTTP 導向 HTTPS
server {
    listen 80;
    server_name *.example.com;
    return 301 https://$host$request_uri;
}

測試並重新載入 Nginx

1
2
3
4
5
# 測試設定檔語法
sudo nginx -t

# 重新載入設定
sudo systemctl reload nginx

多網域與萬用憑證組合

您可以在同一張憑證中包含多個網域和萬用憑證:

1
2
3
4
5
6
sudo certbot certonly --dns-cloudflare \
  --dns-cloudflare-credentials /etc/letsencrypt/cloudflare/credentials.ini \
  -d "example.com" \
  -d "*.example.com" \
  -d "example.org" \
  -d "*.example.org"

注意事項

  • 每張憑證最多可包含 100 個網域名稱
  • 每個註冊網域每週最多可申請 50 張憑證
  • 重複申請相同網域組合的憑證有頻率限制

常見問題排解

問題 1:DNS 驗證失敗

1
2
3
4
5
IMPORTANT NOTES:
 - The following errors were reported by the server:
   Domain: example.com
   Type:   dns
   Detail: DNS problem: NXDOMAIN looking up TXT for _acme-challenge.example.com

解決方案

  • 確認 DNS TXT 記錄已正確新增
  • 等待 DNS 傳播(可能需要數分鐘到數小時)
  • 使用 dignslookup 確認記錄已生效

問題 2:達到頻率限制

1
Error: urn:ietf:params:acme:error:rateLimited

解決方案

  • 等待一週後重試
  • 開發測試時使用 staging 環境:--staging

問題 3:Cloudflare API 權限不足

確認 API Token 具有以下權限:

  • Zone - DNS - Edit
  • Zone - Zone - Read

問題 4:憑證續約失敗

1
2
3
4
5
# 檢查 Certbot 日誌
sudo cat /var/log/letsencrypt/letsencrypt.log

# 手動測試續約
sudo certbot renew --dry-run --verbose

參考資料

comments powered by Disqus
Built with Hugo
Theme Stack designed by Jimmy