申請並設定免費的SSL憑證(Let’s Encrypt)
Setup SSL
Let’s Encrypt是一個非營利組織,提供免費的TLS/SSL 憑證,透過Cerbot這個自動化工具,就可以讓網站使用HTTPS加密網頁,也能自動的更新憑證。
下載SSL憑證
Let’s Encrypt可以手動更新也可以透過指令工具進行下載,這邊使用官方建議的Certbot自動化工具來下載。
從 Certbot 官方網站下載 certbot-auto
,設定執行權限,並將它放在 /opt
下:
1 | wget https://dl.eff.org/certbot-auto |
執行 certbot-auto
,讓它自動安裝所有相依套件(需要root權限):
1 | /opt/letsencrypt/certbot-auto |
接著我們要透過 webroot
的方式,使用既有的 nginx 網頁伺服器來向 Let’s Encrypt 取得憑證,而在認證的過程會需要在網頁根目錄中建立一個 .well-known/acme-challenge/
目錄,讓 Let’s Encrypt 的伺服器來讀取其中的內容。
一般的 nginx 伺服器通常會設定把句點開頭的隱藏檔案都擋掉,遇到這樣的狀況就會無法進行認證,這時候可以再加一小段設定,讓 .well-known/acme-challenge/
目錄可以被正常讀取:
1 | location ^~ /.well-known/acme-challenge/ { |
使用 certonly
功能下載憑證,此處會要輸入Email跟使用條款確認,若無錯誤即可取得憑證:
1 | /opt/letsencrypt/certbot-auto certonly --webroot -w [網頁路徑] -d [domain] |
成功取得的憑證儲存在 /etc/letsencrypt/live/
[domain] 目錄之下,其中 fullchain.pem
就是 nginx 需要憑證,而 privkey.pem
則是私鑰
設定 nginx 伺服器使用 SSL 憑證
若要啟用nginx的HTTPS功能需要再增加一些設定1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20server {
# listen HTTPS port 443
listen 443;
# IPv6 listen HTTPS port 443
listen [::]:443;
server_name [請自行填入server_name];
root [網頁路徑位置];
index index.php index.html index.htm;
# 啟用 SSL
ssl on;
# 其他 SSL 選項
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2; # omit SSLv3 because of POODLE (CVE-2014-3566)
ssl_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA256:DHE-RSA-AES256-SHA:ECDHE-ECDSA-DES-CBC3-SHA:ECDHE-RSA-DES-CBC3-SHA:EDH-RSA-DES-CBC3-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:DES-CBC3-SHA:!DSS';
ssl_prefer_server_ciphers on;
}
設定完畢後可使用指令測試設定檔是否正確:1
service nginx -t
若設定無誤,重新載入設定檔即可:1
serivce nginx reload
若用Cloudflare代管的話請記得將Crypto中的設定改為Full或是Full(strict),讓主機到Cloudflare這段過程是加密的。(在瀏覽器端看到的簽證會是Cloudflare,若要測試是否有成功可先讓DNS設定不要過CDN來查看憑證狀況)
以下是Cloudflare的SSL幾個選項的介紹:
- Flexible SSL:
- 部分SSL加密連線,你不必擁有SSL證書。免技術直接套用Cloudflare免費SSL。訪客連線到Cloudflare是採用加密連線,從Cloudflare到主機則不走加密連線。
- Full SSL:
- 全程SSL加密連線,你必須擁有一個SSL證書在你的主機上,不過Cloudflare並不會檢查你的SSL證書是自己簽署或第三方公正單位發下來的。
- Full SSL(Strict):
- 全程使用SSL加密連線,你必須擁有一個SSL證書在你網站上,而且Cloudflare會檢查你主機端的SSL證書是否為第三方公正單位簽署(不能使用自己簽署的)。
自動更新憑證
Let’s Encrypt 的憑證使用期限為3個月,在憑證到期前的1個月可以使用 certbot-auto
來更新憑證,在實際更新之前我們可以加入 --dry-run
參數,先進行測試:1
/opt/letsencrypt/certbot-auto renew --dry-run
若測試無誤可執行下列指令:1
/opt/letsencrypt/certbot-auto renew --quiet --no-self-upgrade
可以寫一支shell放在 /opt/letsencrypt/renew.sh
中,方便使用:1
2
/opt/letsencrypt/certbot-auto renew --quiet --no-self-upgrade --post-hook "service nginx reload"
--post-hook
可以讓憑證更新完後,可以自動重新載入 nginx 伺服器的設定,讓憑證生效。
接著把這個 /opt/letsencrypt/renew.sh
指令稿寫進 crontab 中:1
2# m h dom mon dow command
30 2 * * 0 /opt/letsencrypt/renew.sh
官方的建議是這個指令可以一天執行兩次,讓伺服器的憑證隨時保持在最新的狀態,這裡我是設定讓伺服器每週日凌晨兩點半進行憑證的檢查與更新,若要其他時間可在自己更改crontab或是用 此工具 參考設定做調整設定。Certbot 只有在憑證到期前一個月才會進行更新,如果憑證尚未到期,就不會更新。