BACK
Featured image of post nginx 設定 ssl + 自動續約 Let’s Encrypt 免費域名證書

nginx 設定 ssl + 自動續約 Let’s Encrypt 免費域名證書

Let's Encrypt 是免費、自動化和開放的憑證頒發機構,由非營利組織網路安全研究小組 (Internet Security Research Group, ISRG) 營運。

參考文章

版本一

步驟 1 - 下載安裝及執行的腳本

1
2
3
wget https://dl.eff.org/certbot-auto --no-check-certificate
chmod +x ./certbot-auto
./certbot-auto -n
生成證書,只需要輸入郵件地址和網站根目錄,提示以下內容,說明安裝完成
1
2
3
Saving debug log to /var/log/letsencrypt/letsencrypt.log

Missing command line flags. For non-interactive execution, you will need to specify a plugin on the command line.  Run with '--help plugins' to see a list of options, and see https://eff.org/letsencrypt-plugins for more detail on what the plugins do and how to use them.

步驟 2 - nginx設定隱藏目錄訪問

1
2
3
location ~ /.well-known {
    allow all;
}

步驟 3 - 生成域名證書

1
./certbot-auto certonly --email [email protected] --agree-tos --no-eff-email --webroot -w /var/www/ -d hack.idv.tw
到目錄內查看
1
cd /etc/letsencrypt/live/

萬用字元的申請指令 (需要驗證dns)
1
certbot-auto certonly -d *.manpc.tk --manual --preferred-challenges dns

步驟 4 - 設定nginx

 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
27
28
29
server {
    listen 80; # IPv4
    listen [::]:80;
    server_name hack.idv.tw ;
    proxy_set_header    Host $host;
    proxy_set_header    X-Real-IP $remote_addr;
    proxy_set_header    X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header    X-Forwarded-Proto $scheme;
    #rewrite ^(.*) https://$host$1 permanent;
    return 301 https://www.itnotetk.com$request_uri;    #跳轉到Https
}

server {
    listen 443 ssl http2;
    server_name hack.idv.tw ;
    ssl on;
    ssl_certificate /etc/letsencrypt/live/hack.idv.tw/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/hack.idv.tw/privkey.pem;
    client_max_body_size 256m;
    ssl_dhparam /etc/nginx/certs/dhparam.pem;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_stapling on;
    ssl_ciphers "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA";
    ssl_prefer_server_ciphers on;
    #add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains;preload" always;
    # ...
Let’s Encrypt憑證只有90天 需要手動續約
1
0 1 * * * /root/certbot-auto renew --disable-hook-validation --renew-hook "/etc/init.d/nginx reload"

版本二

網路出處

  • Let’s Encrypt 是一家新的證書頒發機構(Certificate Authority,簡稱 CA),其提供免費的 TLS/SSL 憑證再配合 Certbot 這個自動化工具,讓一般的網站可以很容易地使用 HTTPS 的安全加密網頁,設定很簡單,憑證的更新也可以自動處理。
  • 以下我以 Ubuntu Linux 14.04 的系統為例,示範 nginx 伺服器使用 Let’s Encrypt 憑證設定 HTTPS 安全加密網頁的方法。

步驟 1 - 從 Certbot 官方網站下載 certbot-auto 指令稿,並設定其執行權限

1
2
wget https://dl.eff.org/certbot-auto
chmod a+x certbot-auto
certbot-auto 要放在哪裡都可以,建議一開始就找一個適合的地方放好,例如建立一個 /opt/letsencrypt 目錄,把 certbot-auto 放在這裡
1
2
mkdir /opt/letsencrypt
mv certbot-auto /opt/letsencrypt/

步驟 2 - 執行 certbot-auto ,讓它自動安裝所有相依套件

1
/opt/letsencrypt/certbot-auto
執行 certbot-auto 時,會需要輸入密碼取得 root 權限

步驟 3:

  • 安裝完成所有需要的系統套件後,接著我們要透過 webroot 的方式,使用既有的 nginx 網頁伺服器來向 Let’s Encrypt 取得憑證,而在認證的過程會需要在網頁根目錄中建立一個 .well-known/acme-challenge/ 目錄,讓 Let’s Encrypt 的伺服器來讀取其中的內容。
  • 一般的 nginx 伺服器通常會設定把句點開頭的隱藏檔案都擋掉,遇到這樣的狀況就會無法進行認證,這時候可以再加一小段設定,讓 .well-known/acme-challenge/ 目錄可以被正常讀取。
1
2
3
4
5
6
location ^~ /.well-known/acme-challenge/ {
# the usual settings
}
location ~ /\. {
deny all;
}

步驟 4 - 使用 certonly 功能下載憑證

1
/opt/letsencrypt/certbot-auto certonly --webroot -w /var/www/blog.gtwang.org/ -d blog.gtwang.org -d gtwang.org

步驟 5 - 輸入自己的 Email 信箱

步驟 6 - 閱讀使用條款,選擇「Agree」繼續

步驟 7 - 下載完成後,會出現類似這樣的成功訊息

1
2
3
4
5
6
7
8
IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at
/etc/letsencrypt/live/blog.gtwang.org/fullchain.pem. Your cert will
expire on 2016-08-13. To obtain a new version of the certificate in
the future, simply run Certbot again.
- If you like Certbot, please consider supporting our work by:
Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
Donating to EFF:                    https://eff.org/donate-le
  • 這樣就成功取得 Let’s Encrypt 的憑證了,而 nginx 用的憑證就儲存在 /etc/letsencrypt/live/blog.gtwang.org/ 目錄之下,其中 fullchain.pem 就是 nginx 需要憑證,而 privkey.pem 則是需要保護好的私鑰,關於憑證檔案的詳細說明,請參考 Certbot 的說明文件。
  • Certbot 還有提供另外一個 standalone 的方式來向 Let’s Encrypt 取得憑證,這種方式是由 Certbot 建立一個獨立的網頁伺服器,提供 Let’s Encrypt 讀取驗證用的資料,不過這樣的做法需要綁定 80443 連接埠,所以通常還會需要暫停既有的網頁伺服器,對於一般的網站而言,會造成網站有幾秒鐘的斷線現象,所以我個人不喜歡這樣的方式。
  • 接下來要設定 nginx 伺服器,使用這個新憑證來提供 HTTPS 的安全加密網頁。

步驟 8 - 要讓 nginx 啟用 HTTPS 安全加密網頁,只要加上 SSL 相關的幾行設定即可,其餘的設定保持不變,以下是我個人使用的 nginx 伺服器設定

 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 {
    # 傾聽 HTTPS 標準埠號 443
    listen 443;

    # 同時啟用 IPv6 的 HTTPS 安全加密網頁
    listen [::]:443;

    server_name blog.gtwang.org;
    root /var/www/blog.gtwang.org/;
    index index.php index.html index.htm;

    # 啟用 SSL
    ssl on;

    # 設定 SSL 憑證
    ssl_certificate /etc/letsencrypt/live/blog.gtwang.org/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/blog.gtwang.org/privkey.pem;

    # 其他 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;

    # ...
}
ssl_protocols 的部分記得要 把SSLv3拿掉 ,避免 POODLE 攻擊(CVE-2014-3566)。

步驟 9 - 設定好之後,檢查一下設定檔是否正確

1
service nginx configtest

步驟 10 - 確認無誤之後,重新載入設定檔

1
service nginx reload
  • 這樣就完成 nginx 伺服器的設定了,接著就可以開啟 HTTPS 加密的網址來測試了,正常來說,使用 Google Chrome 瀏覽器開啟自己主機的 HTTPS 加密網址,應該就會顯示一個綠色的鎖頭,這樣就代表我們安裝的 SSL 憑證是有效的。
Let’s Encrypt 的憑證使用期限只有三個月,在憑證到期前的一個月可以使用 certbot-auto 來更新憑證,在實際更新之前我們可以加入 --dry-run 參數,先進行測試。
1
/opt/letsencrypt/certbot-auto renew --dry-run
  • 若測試沒問題,就可以使用正式指令來更新
1
/opt/letsencrypt/certbot-auto renew --quiet --no-self-upgrade
  • 而為了方便起見,可以將這個更新指令寫在 /opt/letsencrypt/renew.sh 指令稿中
1
2
#!/bin/sh
/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
官方的建議是這個指令可以一天執行兩次,讓伺服器的憑證隨時保持在最新的狀態,這裡我是設定讓伺服器每週日凌晨兩點半進行憑證的檢查與更新,Certbot 只有在憑證到期前一個月才會進行更新,如果憑證尚未到期,就不會更新

comments powered by Disqus