第零步:本文使用環境
- 阿里雲伺服器
- ubuntu 16.04
- nginx
第一步:建立 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=nfangxu.com" > 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:nfangxu.com,DNS:www.nfangxu.com")) \
> domain.csr
執行這一步時,需要指定 openssl.cnf 檔案,一般這個檔案在你的 openssl 安裝目錄底下。
第三步:配置域名驗證
CA 在簽發 DV(Domain Validation)證照時,需要驗證域名所有權。傳統 CA 的驗證方式一般是往 admin@foofish.net 發驗證郵件,而 Let's Encrypt 是在你的伺服器上生成一個隨機驗證檔案,再通過建立 CSR 時指定的域名訪問,如果可以訪問則表明你對這個域名有控制權。 首先建立用於存放驗證檔案的目錄,例如:
mkdir -p /path/to/your/web/root/.well-known/acme-challenge/
然後配置一個 HTTP 服務,以 Nginx 為例:(注意:這裡的埠是80,不是443)
server {
listen 80;
server_name nfangxu.com www.nfangxu.com;
root /path/to/your/web/root/;
index index.php;
location ^~ /.well-known/acme-challenge/ {
try_files $uri =404;
}
# 後期加的, 用於 http 向 https 的跳轉
location / {
rewrite ^(.*)$ https://nfangxu.com/$1 permanent;
}
}
這個驗證服務以後更新證照還要用到,需要一直保留。
第四步:獲取網站證照
先把 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 /path/to/your/web/root/.well-known/acme-challenge/ \
> ./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;
# ssl 配置
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;
# END
server_name nfangxu.com www.nfangxu.com;
root /path/to/your/web/root/;
index index.php index.html index.htm index.nginx-debian.html;
location / {
try_files $uri $uri/ /index.php;
}
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php7.2-fpm.sock;
}
location ~ /\.ht {
deny all;
}
}
第六步:定期更新
Let’s Encrypt 簽發的證照只有90天有效期,但可以通過指令碼定期更新。你可以建立了一個自動更新指令碼
cert_refresh.sh
,內容如下:
#!/bin/bash
# 建立CSR
python /path/to/acme_tiny.py --account-key /path/to/account.key --csr /path/to/domain.csr --acme-dir /path/to/your/web/root/.well-known/acme-challenge/ > /tmp/signed.crt || exit
# 獲取
wget -O - https://letsencrypt.org/certs/lets-encrypt-x1-cross-signed.pem > /tmp/intermediate.pem
# 合併
cat /tmp/signed.crt /tmp/intermediate.pem > /path/to/chained.pem
# 重新載入 nginx 配置檔案
service nginx restart
修改crontab配置,加入以下內容:
# 每個月執行一次
0 0 1 * * /path/to/cert_refresh.sh 2>> /var/log/acme_tiny.log
大功告成,訪問下自己的HTTPS網站是否正常,不出意外的話,網站已經正式啟用HTTPS了 !