透過 Certbot 安裝 Let's Encrypt 證書,來實現全站的 HTTPS 訪問

Vick發表於2018-11-20

HTTP/HTTPS 是什麼?

簡單來說,HTTP 是一個傳輸網頁內容的協議,比如我們瀏覽一個網頁,網頁上的文字、圖片、 CSS 、 JS 等檔案都是透過 HTTP 協議傳輸到我們的瀏覽器,然後被我們看到。因為 HTTP 是明文傳輸的,透過 HTTP 協議傳輸的內容很容易被偷看和篡改,為了安全(你肯定不想被人偷看或者篡改網頁內容吧,比如網站銀行密碼什麼的。)就為 HTTP 協議再加上了一層 SSL/TLS 安全協議,所以就有了 HTTPS 。

SSL/TLS 是什麼?

SSL 是指安全套接字層(Secure Sockets Layer),內心純潔的同學也可以理解為「帶安全套的 HTTP」,因為帶了安全套,所以當然會比較安全。TLS 是 傳輸層安全協議(Transport Layer Security),SSL 和 TLS 是同一個東西的不同階段,理解為同一個東西也行,都是安全協議就對了。

為什麼要部署 HTTPS?

說到底,就是 HTTPS 更安全。甚至為了安全,一個專業可靠的網站, HTTPS 是必須的。 Firefox 和 Chrome 都計劃將沒有配置 SSL 加密的 HTTP 網站標記為不安全,目前它們也正在聯合其他相關的基金會與公司推動整個網際網路 HTTPS 化,現在大家訪問的一些主要的網站。如 Google 多年前就已經全部啟用 HTTPS ,國內的淘寶、搜狗、知乎、百度等等也全面 HTTPS 了。甚至 Google 和百度的搜尋結果也正在給予 HTTPS 的網站更高的排名和優先收錄權。

怎麼部署 HTTPS 呢?

你只需要有一張被信任的 CA ( Certificate Authority )也就是證照授權中心頒發的 SSL 安全證照,並且將它部署到你的網站伺服器上。一旦部署成功後,當使用者訪問你的網站時,瀏覽器會在顯示的網址前加一把小綠鎖,表明這個網站是安全的,當然同時你也會看到網址前的字首變成了 HTTPS ,不再是 HTTP 了。

怎麼獲得 SSL 安全證照呢?

理論上,我們自己也可以簽發 SSL 安全證照,但是我們自己簽發的安全證照不會被主流的瀏覽器信任,所以我們需要被信任的證照授權中心( CA )簽發的安全證照。而一般的 SSL 安全證照籤發服務都比較貴,比如 Godaddy 、 GlobalSign 等機構簽發的證照一般都需要20美金一年甚至更貴,不過為了加快推廣 HTTPS 的普及, EEF 電子前哨基金會、 Mozilla 基金會和美國密歇根大學成立了一個公益組織叫 ISRG ( Internet Security Research Group ),這個組織從 2015 年開始推出了 Let’s Encrypt 免費證照。這個免費證照不僅免費,而且還相當好用,所以我們就可以利用 Let’s Encrypt 提供的免費證照部署 HTTPS 了。

Let’s Encrypt 簡介

前面已經介紹過, Let’s Encrypt 是 一個叫 ISRG ( Internet Security Research Group ,網際網路安全研究小組)的組織推出的免費安全證照計劃。參與這個計劃的組織和公司可以說是網際網路頂頂重要的先驅,除了前文提到的三個牛氣哄哄的發起單位外,後來又有思科(全球網路裝置製造商執牛耳者)、 Akamai 加入,甚至連 Linux 基金會也加入了合作,這些大牌組織的加入保證了這個專案的可信度和可持續性。

Certbot 簡介

ISRG 的發起者 EFF (電子前哨基金會)為 Let’s Encrypt 專案釋出了一個官方的客戶端 Certbot ,利用它可以完全自動化的獲取、部署和更新安全證照。雖然第三方工具也可以使用,但是官方工具更權威,風險也更小,而且遇到問題也更容易解決,畢竟有官方的支援。

Certbot 使用方法

Certbot 的官網是https://certbot.eff.org/, 我們開啟這個連結,選擇自己使用的 web server 和作業系統。選擇完之後,官網就會顯示出對應的安裝操作步驟。
以目前我所使用的伺服器為例,web server 使用Nginx(1.12),作業系統是CentOS(7.3)。因為 Certbot 打包在EPEL中,所以在安裝 Certbot 之前要先安裝EPEL

yum -y install epel-release

然後按著官網給出的步驟提示命令安裝 Certbot

yum install python2-certbot-nginx

安裝完畢後,繼續輸入官網提示命令

certbot --nginx

執行此命令會自動獲取證照,並且 Certbot 會自動編輯Nginx配置檔案配置HTTPS服務。

這邊在執行配置命令時遇到一個坑

ImportError: No module named 'requests.packages.urllib3'

可以看出是缺少一個模組包,看配置命令在命令臺的輸出,Certbot 是用 python 來寫 Nginx 配置。既然是用的 python,可以透過 pip list 命令檢視 python 的依賴包列表。但是檢視是已經存在的,這個問題很快透過 Certbot 在 github 上的一個 Issues 找到了答案(Issues連結)。目前看是包的版本依賴有問題,執行以下命令進行依賴包的重灌

pip uninstall requests
pip uninstall urllib3
yum remove python-urllib3
yum remove python-requests
yum install python-urllib3
yum install python-requests
yum install certbot

再次執行 certbot --nginx 命令成功。命令執行後首先會提示輸入一個郵箱地址,主要作用是訂閱一些通知,輸入後回車。

[root@izuf6fco0zwyipdq9485s2z ~]# certbot --nginx
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator nginx, Installer nginx

▽
Enter email address (used for urgent renewal and security notices) (Enter 'c' to
cancel): demo@mail.com // 演示郵箱
Starting new HTTPS connection (1): acme-v02.api.letsencrypt.org

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

回車後 Certbot 就會自動請求下載 Let's Encrypt 證照,並設定 Nginx 配置檔案。期間會有一些同意相關協議和選擇哪個網站配置的互動,這個看輸出文字就能明白意思。

...
▽
server {
(A)gree/(C)ancel: a

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Would you be willing to share your email address with the Electronic Frontier
Foundation, a founding partner of the Let's Encrypt project and the non-profit
organization that develops Certbot? We'd like to send you email about our work
encrypting the web, EFF news, campaigns, and ways to support digital freedom.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
(Y)es/(N)o: y
Starting new HTTPS connection (1): supporters.eff.org

Which names would you like to activate HTTPS for?
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: kisstime.top
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate numbers separated by commas and/or spaces, or leave input
blank to select all options shown (Enter 'c' to cancel): 1
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for kisstime.top
Cleaning up challenges
...

但是這邊到 Certbot 設定 Nginx 配置檔案的時候遇到一個坑,報如下一個錯誤

An unexpected error occurred:
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe5 in position 2: ordinal not in range(128)
Please see the logfiles in /var/log/letsencrypt for more details.

熟悉 python 的同學應該對這個錯誤比較瞭解。不過博主 python 還是用的比較少,花了點時間瞭解了一下。

在解決錯誤之前,首先要了解unicode和utf-8的區別。unicode指的是萬國碼,是一種“字碼表”。而utf-8是這種字碼表儲存的編碼方法。unicode不一定要由utf-8這種方式編成bytecode儲存,也可以使用utf-16,utf-7等其他方式。目前大多都以utf-8的方式來變成bytecode。其次,Python中字串型別分為byte string 和 unicode string兩種。如果在python檔案中指定編碼方式為utf-8(#coding=utf-8),那麼所有帶中文的字串都會被認為是utf-8編碼的byte string(例如:mystr="你好"),但是在函式中所產生的字串則被認為是unicode string。問題就出在這邊,unicode string 和 byte string 是不可以混合使用的,一旦混合使用了,就會產生這樣的錯誤。例如:

self.response.out.write("你好"+self.request.get("argu"))

其中,"你好"被認為是byte string,而self.request.get("argu")的返回值被認為是unicode string。由於預設的解碼器是ascii,所以就不能識別中文byte string。然後就報錯了。

那理解了這個錯誤原因後,我這邊首先想到的就是網站的 Nginx 配置檔案中是否含有中文。開啟一看,確實存在中文註釋。將註釋去掉,重新執行命令成功不在報錯

接著命令互動會提示是否將所有HTTP重定向到HTTPS,我這邊選擇全部重定向也就是「2」。

Cleaning up challenges
Deploying Certificate to VirtualHost:  //這邊會顯示你的網站配置檔案目錄

Please choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
1: No redirect - Make no further changes to the webserver configuration.
2: Redirect - Make all requests redirect to secure HTTPS access. Choose this for
new sites, or if you're confident your site works on HTTPS. You can undo this
change by editing your web server's configuration.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Select the appropriate number [1-2] then [enter] (press 'c' to cancel): 2
Redirecting all traffic on port 80 to ssl in //這邊會顯示你的網站配置檔案目錄

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Congratulations! You have successfully enabled https://kisstime.top

You should test your configuration at:
https://www.ssllabs.com/ssltest/analyze.html?d=kisstime.top
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   .../fullchain.pem
   Your key file has been saved at:
   .../privkey.pem
   Your cert will expire on 2019-02-14. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot again
   with the "certonly" option. To non-interactively renew *all* of
   your certificates, run "certbot renew"
 - 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

OK,當完成上面最後一步後,輸入如上資訊後就表明 HTTPS 配置成功了!我們可以透過提示中的 SSL Server Test 網址來測試網站是否能夠 HTTPS 來進行訪問

You should test your configuration at:
https://www.ssllabs.com/ssltest/analyze.html?d=kisstime.top

事實證明,高興的太早了。。。透過測試網站和直接訪問域名發現網站都是訪問不了。思考了一下,確認下伺服器的443埠是否開啟,我這邊用的是阿里雲的伺服器,登入控制檯檢視安全組規則,發現確實是443埠沒有開啟,配置開啟後,重新訪問成功。

Nginx的設定說明

基本上 Certbot 會在對應的 Nginx 配置檔案加上下面的引數:

server {
    # ... other configs

    # SSL 設定
    listen 443 ssl;

    # set crt and key
    ssl_certificate .../fullchain.pem;
    ssl_certificate_key .../privkey.pem;

    # include 基本的 ssl 設定
    include .../options-ssl-nginx.conf;

    # Certbot 也會生成一把 Diffie-Hellman 金鑰
    ssl_dhparam .../ssl-dhparams.pem;

    # ... other configs
}

自動更新證照

Let’s Encrypt 免費SSL證照用起來非常方便,但每次申請只有三個月有效期,在每次到期之前都需要重新申請,Certbot 已經提供了一鍵續訂的命令

certbot renew

我們可以透過新增此條命令的cron作業(或systemd計時器)來安排證照的自動續訂

SHELL=/bin/bash
PATH=/sbin:/bin:/usr/sbin:/usr/bin

0 0,12 * * * certbot renew --quiet 

Certbot 的 log 路徑

Certbot 的 log 預設路徑在 /var/log/letsencrypt,有需要可以去確認檢視。

相關第三方

certbot-auto是對指令碼certbot的封裝,可以設定系統環境或自動升級。

牛頓曾經說過:如果說我看得比別人更遠些,那是因為我站在巨人的肩膀上。(If I have seen further, it is by standing on the shoulders of giants.)感謝。

原文連結

本作品採用《CC 協議》,轉載必須註明作者和本文連結
Kill Time, Or Kiss Time.

相關文章