申請​​ Let's Encrypt 免費​ SSL ​​憑證於​在 Nginx​ 配置和​自動更新教學

想要為網站申請SSL憑證嗎?那可以申請Let's Encrypt所提供免費SSL/TLS憑證的服務。Let's Encrypt是由EFF、Mozilla基金會、Akamai和Cisco等等許多大公司及非營利組織於2014年共同創立的ISRG組織所成立的數位憑證認證機構,目標就是要讓網站可以免費、申請簡單與自動化流程的憑證服務,以可以推廣及加速全球網站採用HTTPS安全的加密傳輸協定。Let's Encrypt已在2016年4月脫離了Beta測試階段,正式進入穩定階段,現在網站管理者可以放心的使用Let's Encrypt所提供的免費SSL憑證服務了。另外,需要注意的是,Let's Encrypt簽發的憑證有效期為3個月(90天),也就是說網站每接近3個月時都需要重新更新一次憑證,但還好我們可以透過renewal script來定期更新憑證,基本上配置好shell script及設定好cronjob排程後,就可以不用擔心憑證過期的問題。

本文教學將指引使用者如何在Debian/Ubuntu系統與Nginx網頁伺服器的主機上申請與配置SSL憑證。如果你使用其他的Linux發行版或者是其他的網頁伺服器,當然也是可以參考本教學,但在指令方面需要自行更改以調整至適用你自己系統的環境。本文教學分為3部分,開始會指引使用者如何為域名申請SSL憑證,並將憑證安裝於主機上及設定Nginx設定檔,在SSL憑證配置完成後,筆者會使用Qualys SSL Labs所提供的SSL Server Test線上服務來檢測網站的HTTPS配置及測試你網站啟用HTTPS後是否相容市面上常見的系統及瀏覽器(如舊系統的瀏覽器-Windows XP的IE 8),本文教學第二部分會指引使用者如何配置shell script及設定好crontab,以可以讓Cron自動執行及更新Let's Encrypt憑證,最後部分會指引使用者如何在Nginx伺服器上啟用HTTP/2傳輸協定,及如何檢查網站是否啟用了HTTP/2傳輸協定。

本文教學所使用的憑證申請工具為Let's Encrypt官方所提供的Let's Encrypt套件。當然你也可以使用其他第三方提供的工具來申請Let's Encrypt憑證,以下所列出的第三方工具會比官方提供套件來的輕巧,支援都很不錯,並且都是開源的,如果你有興趣,那可以考慮使用第三方工具來申請Let's Encrypt的SSL憑證,以下為第三方工具存放在GitHub上的連結:

 acme-tiny

 acme.sh

 dehydrated

 官方網站上也有整理其他第三方工具申請Let's Encrypt憑證的套件名單-ACME Client Implementations

1)開始為域名申請SSL憑證,並將憑證安裝於主機上及設定Nginx設定檔。

**在申請Let's Encrypt SSL憑證之前,需檢查要申請SSL憑證的域名或子域名DNS的A Record,是否都有對應到主機正確的IP位址。

**如果網站有使用CDN服務,那需要暫時將CDN服務暫停(如:CloudFlare),直到Let's Encrypt憑證建立完成。

**Let's Encrypt在簽發憑證時是有一些限制的,例如:單個域名簽發數量等等或其他不同的限制,而Let's Encrypt官方也曾說過隨著時間未來會慢慢放鬆這些限制,因為這些限制可能會隨著時間而改變,所以筆者這邊就不細說這些限制了,請自行至Let's Encrypt-Rate Limits頁面查看有哪些限制。

Step 1:在申請憑證之前,需先複製Let's Encrypt套件至你的主機,但因為Let's Encrypt套件是存放在GitHub上,所以我們可以使用Git下載與管理Let's Encrypt套件,在使用Git之前,你的主機需先安裝好Git工具。

sudo apt-get update

sudo apt-get install git

 

Step 2:從GitHub複製Let's Encrypt套件至你的主機

sudo git clone https://github.com/certbot/certbot /opt/letsencrypt

使用Git從GitHub複製Let's Encrypt套件至您的主機-lessl001

 

Step 3:在安裝SSL憑證時,Let's Encrypt會用到Port 80和Port 443,所以需要先停用佔用到這兩個Port的Nginx服務。如果沒有停用,會出現『The program nginx (process ID XXX) is already listening on TCP port 80. This will prevent us from binding to that port. Please stop the nginx program temporarily and then try again.』哪個程序佔用到Port 80或443的錯誤訊息。

sudo systemctl stop nginx

 

Step 4:cd至/opt/letsencrypt目錄位置,執行如下圖所示指令以可以建立新的憑證。

**這邊在安裝需要的元件會稍微久一些,稍等一下吧。

cd /opt/letsencrypt

./letsencrypt-auto certonly --standalone

開始安裝與建立新的SSL/TLS憑證-lessl021

 

Step 5:出現如下圖所示的畫面『Enter email address』,那就輸入你的電子郵件,輸入好後選擇『OK』。

輸入您的電子郵件地址-lessl022

 

Step 6:同意Let's Encrypt相關的許可協議,選擇『Agree』同意以繼續下一步。

同意Let's Encrypt許可協議-lessl023

 

Step 7:在如下圖所示的畫面『Please enter in your domain name』,輸入你要建立SSL憑證的域名,如果你要申請多個域名或子域名,可以用鍵盤『space(空白鍵)』隔開,例如:『example.com www.example.com img.example.com』,輸入好後,選擇『OK』。

輸入需要申請SSL憑證的域名-lessl024

額外補充:如果你不想要使用上面Step 5開始的Step by Step方式來申請憑證,那可以使用指令方式來申請憑證,指令格式參考如下:

./letsencrypt-auto certonly --standalone --email email@example.com --agree-tos -d example.com -d www.example.com -d img.example.com

查看Let's Encrypt指令全部的說明:

./letsencrypt-auto --help

 

Step 8:憑證建立成功,會出現如下面所示的成功訊息:

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at /etc/letsencrypt/live/demo.pcsetting.com/fullchain.pem. Your cert will expire on 2016-07-21. To obtain a new version of the certificate in the future, simply run Let's Encrypt again.
 - If you lose your account credentials, you can recover through e-mails sent to example@gmail.com.
 - Your account credentials have been saved in your Let's Encrypt configuration directory at /etc/letsencrypt. You should make a secure backup of this folder now. This configuration directory will also contain certificates and private keys obtained by Let's Encrypt so making regular backups of this folder is ideal.

已成功申請及建立SSL憑證-lessl025

 

Step 9:憑證建立完成後,你可以使用如下圖所示的方式查看憑證是否有簽發成功,在/etc/letsencrypt/live/example.com目錄下,你應該會看到『cert.pem』、『chain.pem』、『fullchain.pem』和『privkey.pem』4個不同的憑證檔案,確定憑證建立成功後,就可以啟動Nginx伺服器了。

sudo ls -l /etc/letsencrypt/live

sudo ls -l /etc/letsencrypt/live/demo.pcsetting.com

sudo systemctl start nginx

可以使用ls -l指令檢查已建立好的SSL憑證-lessl041

 

Step 10:使用OpenSSL指令產生一個2048-bit Diffie Hellman Group,以解決Diffie-Hellman金鑰預設長度不足的問題。

**這邊在產生strong DH group會稍微久一些,稍等一下吧。

sudo openssl dhparam -out /etc/ssl/certs/dhparams.pem 2048

建立一個Diffie-Hellman金鑰-lessl051

 

Step 11:如下圖所示,因為還未設定Nginx config檔,所以在網址列上,還不能看到綠色的鎖頭。

網站還未啟用HTTPS安全通訊協定-lessl061

 

Step 12:編輯Nginx設定檔,這邊的config檔路徑和名稱會跟大家不一樣,請自行設定你主機原有的config檔。以下指令為筆者使用Vim編輯器設定筆者自己的config檔。

sudo vim /etc/nginx/sites-available/demopcsetting

 

Step 13:設定Nginx HTTP自動轉址至HTTPS。

**下面的範例,請自行將『example.com』替換至你自己的域名。

server {
    listen 80;
    server_name example.com www.example.com;
    return 301 https://example.com$request_uri;
}

設定Nginx設定檔從Port 80自動301轉址至Port 443-lessl062

 

Step 14:配置剛剛申請好的SSL憑證。

**下面的範例,請自行將『root /var/www/example』替換至Nginx存放網頁的目錄,及『example.com』替換至你自己的域名。

server {
    listen 443 ssl;
    server_name example.com;
    root /var/www/example;
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    ssl_session_cache shared:SSL:50m;
    ssl_session_timeout 1440m;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
    ssl_prefer_server_ciphers on;
    ssl_dhparam /etc/ssl/certs/dhparams.pem;
    ssl_stapling on;
    ssl_stapling_verify on;
    ssl_trusted_certificate /etc/letsencrypt/live/example.com/chain.pem;
    add_header Strict-Transport-Security "max-age=31536000; preload";

    # ...

}

在Nginx配置SSL憑證-lessl063

 

Step 15:測試Nginx設定檔,查看執行有沒有錯誤及重啟Nginx伺服器。

sudo nginx -t

sudo systemctl restart nginx

測試Nginx設定檔執行會不會有錯誤及重啟Nginx伺服器-lessl064

 

Step 16:在瀏覽器網址列輸入你自己網站的域名,就可以看到如下圖所示網址列已有綠色小鎖頭,則代表你網站已成功配置好HTTPS加密協定。

網站已經成功啟用HTTPS安全通訊協定了-lessl065

 

Step 17:接下來我們可以使用Qualys SSL Labs所提供的SSL Server Test線上服務來檢測網站的HTTPS配置,在Hostname欄位輸入你要檢測網站的域名,可以打勾『Do not show the results on the boards』不要將測試結果的網域顯示在欄位上,點擊『Submit』開始測試吧。

使用Qualys SSL Labs網站所提供的線上SSL憑證檢測服務-lessl071

 

Step 18:大概稍等一下,就可以看到測試結果了,如下圖所示可以看到筆者剛剛配置好的網站獲得A+級別的評分。

可以看到網站獲得A+評分的檢測結果-lessl072

 

Step 19:使用Qualys SSL Labs線上檢測服務也可以看到你網站在使用HTTPS加密協定後,在其他不同系統或瀏覽器是否也能順利開啟你的網站,如下圖所示Windows XP的IE 8瀏覽器也可以開啟Let's Encrypt所簽發憑證的網站。Let's Encrypt憑證相容性方面比其他憑證認證機構好很多,幾乎支援市面上常見的系統及瀏覽器。

在Qualys SSL Labs也可以查看自己網站在不同的瀏覽器是否可以開啟您的網站-lessl073

 

2)配置好shell script及設定好cronjob排程,以可以自動更新Let's Encrypt憑證。

Step 1:編輯Nginx config檔,請自行輸入你主機原有的config檔路徑位置,以下指令為筆者使用Vim編輯器設定筆者自己的config檔。

sudo vim /etc/nginx/sites-available/demopcsetting

 

Step 2:在Nginx config檔中加入如下圖所示的『/.well-known』設定。

server {

    #...

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

    #...

}

在Nginx設定檔加入well-known-lessl091

 

Step 3:測試Nginx設定檔,查看執行有沒有錯誤及重啟Nginx伺服器。

sudo nginx -t

sudo systemctl restart nginx

 

Step 4:安裝bc工具。

**shell script會用到bc工具,主要是計算憑證多少天到期,如果你不想要在主機安裝bc工具也是可以的,但要修改shell script,才不會出現錯誤,等下在下面Step 9的額外補充,筆者會教如何修改shell script。

sudo apt-get install bc

安裝bc-lessl092

 

Step 5:要自動更新憑證,我們需要用到webroot plugin,cd至/opt/letsencrypt目錄位置,複製letsencrypt目錄下的examples/cli.ini範例設定檔至/usr/local/etc/,並更名為le-renew-webroot.ini,複製好後直接編輯le-renew-webroot.ini設定檔。

sudo cp examples/cli.ini /usr/local/etc/le-renew-webroot.ini

sudo vim /usr/local/etc/le-renew-webroot.ini

建立webroot設定檔-lessl093

 

Step 6:在le-renew-webroot.ini設定檔,需更改的地方就如下圖所示:

**記得將前面的#號刪掉,以取消註解。

**筆者之後使用webroot plugin時,發現裡面的domain被移掉了,假如你也是遇到這個問題,那你需要自己補上『domains = 』。

rsa-key-size = 4096   #這個使用預設的,不用改
email = you@example.com   #改成自己的電子郵件
domains = example.com, www.example.com   #改成要自動更新的域名
webroot-path = /usr/share/nginx/html   #改成Nginx存放網頁的目錄,例如筆者是:『/var/www/demopcsetting』

編輯webroot設定檔-lessl094

 

Step 7:測試le-renew-webroot.ini設定檔是否可以自動更新憑證,如能更新憑證,會出現如下圖所示的憑證更新成功訊息。

./letsencrypt-auto certonly -a webroot --agree-tos --renew-by-default --config /usr/local/etc/le-renew-webroot.ini

執行並測試是否可以成功自動更新新的SSL憑證-lessl095

 

Step 8:從GitHub下載別人寫好的shell script,並將shell script權限設定為可執行的檔案。

sudo wget -O /usr/local/sbin/le-renew-webroot https://gist.githubusercontent.com/thisismitch/e1b603165523df66d5cc/raw/fbffbf358e96110d5566f13677d9bd5f4f65794c/le-renew-webroot

sudo chmod +x /usr/local/sbin/le-renew-webroot

下載憑證更新的Script,並修改權限以讓Script可以被執行-lessl096

 

Step 9:可以輸入指令『vim /usr/local/sbin/le-renew-webroot』查看shell script內容,可自定修改的像是『le_path』和『exp_limit』,『le_path』是我們下載Let's Encrypt套件的路徑位置,如果是跟著本教學設定的,使用預設就好,而『exp_limit』預設值為30,就是說憑證有效期還有30天以上就不會更新憑證,假如少於30天就會更新憑證。

**此步驟可以忽略。

在更新的Script內容中,可以自定的參數為le_path和exp_limit-lessl097

額外補充:就如筆者上面Step 4所說的,如果不想要安裝bc工具,那就要修改shell script,修改的好處就是不用在為主機額外安裝bc工具來計算憑證到期天數,而是直接使用shell內建的運算函數來計算憑證到期天數。

sudo vim /usr/local/sbin/le-renew-webroot

大概在23行左右,可以看到如下面的原始碼:

days_exp=$(echo \( $exp - $datenow \) / 86400 |bc)

將其替代為:

days_exp=$(( ($exp-$datenow)/86400 )) 

 

Step 10:可以使用shell script來測試執行更新憑證。

sudo le-renew-webroot

應該可以看到如下圖所示的返回結果訊息:

Checking expiration date for example.com...
The certificate is up to date, no need for renewal (89 days left).

輸入le-renew-webroot試看Script是否可以成功執行-lessl098

 

Step 11:編輯crontab排程,以可以讓主機日後進行SSL憑證的檢查及更新。

sudo crontab -e

 

Step 12:如下圖所示筆者設定每週星期天凌晨3點執行一次憑證的檢查(時間以主機時間為準),並將執行結果輸出至『/var/log/le-renewal.log』。

**關於Cron的時間設定可以查看維基百科。

0 3 * * 0 /usr/local/sbin/le-renew-webroot >> /var/log/le-renewal.log 2>&1

新增crontab排程,讓Script可以定時自動更新SSL憑證-lessl111

 

3)在Nginx伺服器上啟用HTTP/2傳輸協定。

**啟用HTTPS加密傳輸協定後,當然我們可以進一步啟用HTTP/2傳輸協定,主要好處是可以加快網頁的載入,尤其是有啟用HTTPS加密傳送協定後的網站特別明顯,如果你還想要進一步了解HTTP/2傳輸協定是什麼,可以自行搜尋一下網路資料。

**本文教學下面會以Google Chrome瀏覽器來檢查網站目前使用的HTTP傳輸協定版本。

Step 1:按鍵盤的『F12』鍵或者按鍵盤的『Ctrl+Shift+C』開啟Chrome開發人員工具,使用開發人員工具可以協助我們檢查網站目前使用的HTTP傳輸協定版本,首先先要在上面的功能列選擇『Network』功能,就可以看到如下圖所示的畫面,Protocol在預設中是不會勾選的,所以你可以跟著如下圖方式勾選Protocol,才能查看網站目前使用的HTTP傳輸協定版本,滑鼠右鍵點選如下圖所示『Type』的那一列任何一個位置,就可以勾選你要查看的HTTP headers欄位,因為我們要查看HTTP傳輸協定版本,所以就勾選『Protocol』,勾選好後,就可以按鍵盤『F5』刷新網頁,可以在Protocol欄位看到網頁目前使用的HTTP傳輸協定版本為『http/1.1』。

使用Crome開發人員工具查看網站目前使用的HTTP傳輸協定版本-lessl131

 

Step 2:當然要啟用HTTP/2,你主機的網頁伺服器才是主要關鍵,像Nginx網頁伺服器在版本1.9.5以上才支援HTTP/2傳輸協定,所以一定要先檢查你的網頁伺服器是否支援了HTTP/2,如下圖所示筆者的Nginx版本為『1.9.15』也就有支援HTTP/2傳輸協定。

**Google Chrome從51版開始,已正式移除NPN(Next Protocol Negotiation)協定的支援,僅支援ALPN(Application-Layer Protocol Negotiation)協定,而被伺服器廣泛使用的OpenSSL函式庫在1.0.2版本才開始支援ALPN協定,但目前市面上主流伺服器的作業系統內建的OpenSSL函式庫幾乎都在1.0.1版本(更新-Ubuntu 16.04 LTS與Debian 9內建的OpenSSL函式庫都為1.0.2的版本了),如果你要讓Chrome瀏覽器支援HTTP/2傳輸協定,除了需要網頁伺服器支援HTTP/2之外,OpenSSL函式庫也是其中一個重要的關鍵,你可以使用『openssl version』指令來查看伺服器上的OpenSSL版本。

sudo nginx -v

檢查Nginx伺服器版本-lessl132

 

Step 3:在Nginx啟用HTTP/2傳輸協定十分簡單,只需要編輯Nginx config檔,並跟著如下圖方式加上『http2』,就可以啟用HTTP/2傳輸協定了。

listen 443 ssl http2;

在Nginx設定檔中啟用HTTP/2協定-lessl133

 

Step 4:Nginx config檔編輯完成後,先測試Nginx設定檔,查看執行有沒有錯誤及重啟Nginx伺服器。

sudo nginx -t

sudo systemctl restart nginx

 

Step 5:接下來我們就可以檢查網站是否啟用了HTTP/2傳輸協定,以下筆者列出檢查HTTP/2傳輸協定各種不同的方式。

檢查HTTP/2傳輸協定方法一:使用Chrome開發人員工具方式,按鍵盤『F5』刷新網頁後,在Protocol欄位看到如下圖所示的『h2』,也就表示你網站目前使用的傳輸協定為HTTP/2版本。

網站已使用HTTP/2傳輸協定-lessl134

 

檢查HTTP/2傳輸協定方法二:可以使用第三方線上檢測服務來檢查網站是否啟用HTTP/2傳輸協定,如下圖所示筆者使用的是KeyCDN-HTTP/2 Test來檢查網站是否啟用HTTP/2傳輸協定,有啟用HTTP/2傳輸協定的網站會出現如下圖所示的『Yeah! example.com supports HTTP/2.0』已支援HTTP/2.0版本。

使用KeyCDN所提供的HTTP/2線上測試工具來檢測網站是否有啟用HTTP/2傳輸協定--lessl141

 

檢查HTTP/2傳輸協定方法三:安裝瀏覽器擴充套件,如你是使用Google Chrome瀏覽器,那可以在Chrome瀏覽器上安裝HTTP/2 and SPDY indicator;如你是使用Firefox瀏覽器,那可以在Firefox瀏覽器上安裝HTTP/2 Indicator,此擴充套件很輕易可以看到網站是否支援HTTP/2傳輸協定,如網站有支援HTTP/2,會出現藍色小雷電,滑鼠滑過去看會出現『HTTP/2-enabled(h2)』訊息;如出現綠色小雷電,那就表示該網站使用SPDY傳輸協定;如出現灰色小雷電,也就表示該網站沒有啟用HTTP/2或者SPDY傳輸協定。

 

檢查HTTP/2傳輸協定方法四:使用Google Chrome瀏覽器,也可以在網址列輸入『chrome://net-internals/#http2』來查看網站是否支援HTTP/2傳輸協定。

 

Step 6:另外補充一下Mozilla有提供Mozilla SSL Configuration Generator線上的SSL範例配置產生器,有提供不同的網頁伺服器配置SSL方法,如有興趣可以自行查看一下。

參考Mozilla所提供的線上SSL配置產生器來設定SSL憑證--lessl161