1. 程式人生 > >免費HTTPS證書Let's Encrypt安裝教程

免費HTTPS證書Let's Encrypt安裝教程

HTTPS在各大網際網路站已經成為標配,就連某度也在前不久全面啟用HTTPS,很多小網站也配置了HTTPS,這是未來的一種趨勢。HTTPS的好處多多,可以防止各種攻擊劫持,運營商廣告植入,客戶傳輸資訊洩露等問題。為了讓HTTPS能夠全面普及,Let's Encrypt專案應運而生,它由網際網路安全研究小組ISRG(Internet Security Research Group)提供服務,ISRG是來自美國加利福尼亞州的一個公益組織。Let's Encrypt 得到了 Mozilla、Cisco和 Chrome 等眾多公司和機構的支援。

申請 Let's Encrypt 證書不盡免費、程式碼開源,而且配置簡單,不過每次申請只有90天的有效期,但可以通過指令碼定期更新,配置好之後一勞永逸。本教程親測有效,希望對正在尋找免費HTTPS方案的你有一定的幫助。

按照Let's Encrypt 官方提供的工具安裝HTTPS的話與過於複雜,於是有好心人提供了更為輕巧的工具安裝, acme-tiny誕生了,它的程式碼量在200行內,只需依賴Python和OpenSSL。

第一步:建立 Let's Encrypt 賬號

Let's Encrypt使用一個私鑰來進行賬號的建立與登陸,因此我們需要使用openssl建立一個account.key。

openssl genrsa 4096 > account.key

如果你已經有一個Let's Encrypt key的話,那麼只需要做一次轉換,因為Let's Encrpt 的客戶端生成的key是JWK格式,而acm-tiny使用的是PEM格式。轉換key需要使用一個

指令碼

# 下載指令碼
wget -O - "https://gist.githubusercontent.com/JonLundy/f25c99ee0770e19dc595/raw/6035c1c8938fae85810de6aad1ecf6e2db663e26/conv.py" > conv.py

# 把private key 拷貝到你的工作目錄
cp /etc/letsencrypt/accounts/acme-v01.api.letsencrypt.org/directory/<id>/private_key.json private_key.json

# 建立一個DER編碼的private key
openssl asn1parse -noout -out private_key.der -genconf <(python conv.py private_key.json)

# 轉換成PEM格式
openssl rsa -in private_key.der -inform der > account.key

第二步:建立域名的CSR(certificate signing request)

Let's Encrypt 使用的ACME協議需要一個CSR檔案,可以使用它來重新申請HTTPS證書,接下來我們就可以建立域名CSR,在建立CSR之前,我們需要給我們的域名建立一個私鑰(這個和上面的賬戶私鑰無關)。

#建立普通域名私鑰
openssl genrsa 4096 > domain.key

接下來,使用你的域名私鑰建立CSR檔案,這一步裡面是可以增加最多100個需要加密的域名的,替換下面的foofish.net即可(注意,稍後會說到,每個域名都會涉及到驗證)

#單個域名
openssl req -new -sha256 -key domain.key -subj "/CN=foofish.net" > domain.csr

#多個域名(如果你有多個域名,比如:www.foofish.net和foofish.net,使用這種方式)
openssl req -new -sha256 -key domain.key -subj "/" -reqexts SAN -config <(cat /etc/ssl/openssl.cnf <(printf "[SAN]\nsubjectAltName=DNS:foofish.net,DNS:www.foofish.net")) > domain.csr

執行這一步時,需要指定 openssl.cnf 檔案,一般這個檔案在你的 openssl 安裝目錄底下。

第三步:配置域名驗證

CA 在簽發 DV(Domain Validation)證書時,需要驗證域名所有權。傳統 CA 的驗證方式一般是往 [email protected] 發驗證郵件,而 Let's Encrypt 是在你的伺服器上生成一個隨機驗證檔案,再通過建立 CSR 時指定的域名訪問,如果可以訪問則表明你對這個域名有控制權。 首先建立用於存放驗證檔案的目錄,例如:

mkdir -p var/www/challenges

然後配置一個 HTTP 服務,以 Nginx 為例:(注意:這裡的埠是80,不是443)

server {
    listen 80;
    server_name www.foofish.net foofish.net;

    location ^~ /.well-known/acme-challenge/ {
        alias /var/www/challenges/;
        try_files $uri =404;
    }

   ...the rest of your config
}

這個驗證服務以後更新證書還要用到,需要一直保留。

第四步:獲取網站證書

先把 acme-tiny 指令碼儲存到之前的 ssl 目錄:

wget https://raw.githubusercontent.com/diafygi/acme-tiny/master/acme_tiny.py

指定賬戶私鑰、CSR 以及驗證目錄,執行指令碼:

python acme_tiny.py --account-key ./account.key --csr ./domain.csr --acme-dir /var/www/challenges/ > ./signed.crt

如果一切正常,當前目錄下就會生成一個 signed.crt,這就是申請好的證書檔案。

第五步:安裝證書

證書生成後,就可以把它配置在web 伺服器上了,需要注意的是,Nginx需要追加一個Let's Encrypt的中間證書,在 Nginx 配置中,需要把中間證書和網站證書合在一起:

wget -O - https://letsencrypt.org/certs/lets-encrypt-x1-cross-signed.pem > intermediate.pem
cat signed.crt intermediate.pem > chained.pem

最終,修改 Nginx 中有關證書的配置並 reload 服務即可:

server {
    listen 443;
    server_name foofish.net, www.foofish.net;

    ssl on;
    ssl_certificate /path/to/chained.pem;
    ssl_certificate_key /path/to/domain.key;
    ssl_session_timeout 5m;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA;
    ssl_session_cache shared:SSL:50m;
    ssl_prefer_server_ciphers on;

    ...the rest of your config
}

server {
    listen 80;
    server_name foofish.net, www.foofish.net;

    location /.well-known/acme-challenge/ {
        alias /var/www/challenges/;
        try_files $uri =404;
    }

    ...the rest of your config
}

第六步:定期更新

Let’s Encrypt 簽發的證書只有90天有效期,但可以通過指令碼定期更新。你可以建立了一個自動更新指令碼renew_cert.sh,內容如下:

1
2
3
4
5
#!/usr/bin/sh
python /path/to/acme_tiny.py --account-key /path/to/account.key --csr /path/to/domain.csr --acme-dir /var/www/challenges/ > /tmp/signed.crt || exit
wget -O - https://letsencrypt.org/certs/lets-encrypt-x1-cross-signed.pem > intermediate.pem
cat /tmp/signed.crt intermediate.pem > /path/to/chained.pem
service nginx reload

修改crontab配置,加入以下內容:

#每個月執行一次
0 0 1 * * /path/to/renew_cert.sh 2>> /var/log/acme_tiny.log

大功告成,不過先別急,訪問下自己的HTTPS網站是否正常,不出意外的話,網站正式啟用HTTPS,但是網站如果有用CDN的話,那麼需要CDN也支援HTTPS才行,否則無法正常載入CDN的資源,類似的錯誤如:

Mixed Content: The page at 'https://foofish.net/' was loaded over HTTPS, but requested an insecure script 'http://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js'. This request has been blocked; the content must be served over HTTPS.

一種解決方法就是使用七牛的雲端儲存來解決這個問題。可參考:https://blog.blahgeek.com/qiniu-cdn-serve-static/

IMPORTANT NOTES: - Congratulations! Your certificate and chain have been saved at /etc/letsencrypt/live/foofish.net/fullchain.pem. Your cert will expire on 2017-04-07. To obtain a new or tweaked version of this certificate in the future, simply run certbot-auto again. To non-interactively renew all of your certificates, run "certbot-auto renew" - If you lose your account credentials, you can recover through e-mails sent to [email protected] - Your account credentials have been saved in your Certbot 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 Certbot so making regular backups of this folder is ideal. - 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


關注公眾號「Python之禪」(id:vttalk)獲取最新文章 python之禪