2019年5月12日 星期日

用 certbot 幫同網域下眾網站創建共用的 ssl 憑證

從去年起, chrome 已經開始把 http (沒有 s) 的網站標示為不安全了。 現代的站長一定要學會 用 let's encryp 把 http 網站升級成 https 網站 (中文)。 但是如果你 (1) 擁有同網域底下一整個艦隊很多個網站, 但是 (2) 懶得逐一申請, 而且 (3) 委託代管 DNS 或自管 DNS, 那麼就可以直接拿同一個憑證給同網域的所有網站共用。 例如我擁有 frdm.info, 委託 pchome 代管 DNS, 而且想要讓 abcdef.frdm.info 跟 uvwxyz.frdm.info 及其他子網域都共用同一組 ssl 憑證。 以下就是我的筆記。 也可以參考 Sam Tang 的中文文章 Saurabh Palande 的英文文章

我的伺服器跑的是 ubuntu 18.04。 所以先這樣安裝所需套件:

apt install software-properties-common
add-apt-repository ppa:certbot/certbot
apt install certbot

[2020/7/18 警告: 不要用 --manual 。 用了這個, 會無法自動更新, 有點麻煩!] 其實當初還按照教學文一併安裝了 python-certbot-apache 套件; 不過後來下指令時 (用 --manual 選項) 要求 certbot 不要自動幫我修改 apache2 的設定檔, 所以可能其實並不需要這個套件? 總之再來就是用 certbot 產生全網域通用憑證 (以我的網域 *.frdm.info 為例):

certbot certonly --manual --preferred-challenges dns -d *.frdm.info

這會產生很多檔案放在 /etc/letsencrypt 底下, 其中 /etc/letsencrypt/live/frdm.info/ 底下有捷徑 (symbolic links) 指向你的金鑰。 另外, 它也會印出類似這樣的訊息:

Please deploy a DNS TXT record under the name
_acme-challenge.frdm.info with the following value:

xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

把它存起來, 等一下會用到!

再來要手動修改 apache2 的設定檔。 進入 /etc/apache2/sites-available/ , 幫 default-ssl.conf 製作一個備份, 例如取名為 default-ssl.conf.orig (副檔名不要是 .conf)。 再編輯 default-ssl.conf , 把這兩句:

    SSLCertificateFile  /etc/ssl/certs/ssl-cert-snakeoil.pem
    SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key

改成類似這樣:

    SSLCertificateFile /etc/letsencrypt/live/frdm.info/fullchain.pem
    SSLCertificateKeyFile /etc/letsencrypt/live/frdm.info/privkey.pem

又參考 /etc/apache2/sites-enabled 底下現行的 apache2 設定, 適當修改你的 default-ssl.conf。 例如我的設定檔長得像 這樣。 最後 a2ensite default-ssl.conf ; systemctl reload apache2 啟用你的加密網站!

再前往你的 DNS 服務商, 新增一筆 TXT 類型的記錄, 並且按照先前存起來的 _acme-challenge.frdm.info 那一段的說明填值, 類似下圖。

certbot 的 _acme-challenge

再回到命令列, 用 nslookup -q=txt _acme-challenge.frdm.info 8.8.8.8 查看確認。 可能要等一下子才會生效, 才會看到印出類似這樣:

Server:  8.8.8.8
Address: 8.8.8.8#53

Non-authoritative answer:
_acme-challenge.frdm.info text = "tNj8cJDZ_GoCJGOs80AJdEZCgBjia_ojhC5k_5xJwW8"

Authoritative answers can be found from:

這意味著: 位於 Let's Encrypt 的 CA (憑證機構) 可以透過這個公開查詢確認你確實擁有這一整群子網域, 所以可以幫這一整群子網域背書。 以上指令從 這裡 看來的。

補充說明:

  1. 通用憑證只對子網域有效。 如果造訪父網域 https://frdm.info 則會看到 「frdm.info 用了無效的安全憑證。 憑證只對 *.frdm.info 有效。 錯誤碼: SSL_ERROR_BAD_CERT_DOMAIN」 之類的錯誤訊息。 詳見 這個問答
  2. 在 /etc/cron.d/certbot 底下有一些規則, 會叫系統每天兩次自動檢查是否需要更新憑證。
  3. 在原來未加密網站 (abcdef) 的 apache2 設定檔裡面, 我還補上一句: Redirect permanent / https://abcdef.frdm.info/ 以便把所有的 http 流量通通導到相對應的 https 網址去。
  4. 寫完之後才發現 Let's Encrypt 官網解說文 andyyou 的好文。 除了用 DNS 取得 Let's Encrypt 的 CA 的信任之外, 另一個方法是按照 CA 的指示, 在特定的網頁裡放一個特定的內容, 並且對指定的字串簽章。 這兩篇文章有解說第二種方法 (Provisioning an HTTP resource under a well-known URI )。 Andyyou 的中文文章有解說各種選項的意義。

[2020/7/18] 後記: 用 "manual" 的話, 後續更新也就必須手動, 較不方便。 後來我改用 certbot certonly --preferred-challenges http --standalone -d frdm.info -d abc.frdm.info -d def.frdm.info -w /var/www/acme/ 然後測試一下更新指令: certbot renew --dry-run --apache 如果順利的話, 拿掉 --dry-run , 改採 apache 方式確實手動更新一次: certbot renew --apache 以後應該就會自動更新了。 詳見 Trouble switching from a manual to regular cert Convert manual to Webroot renewal

沒有留言:

張貼留言

因為垃圾留言太多,現在改為審核後才發佈,請耐心等候一兩天。