Let's Encrypt 給網站加 HTTPS 完全指南
29 MAY 20162017.03.27更新:
/usr/bin/letsencrypt
被/usr/bin/certbot
替代,更新文章中所用到的命令。參考:Archlinux Let's Encrypt Wiki
前段時間在北京聯通3G移動網絡下,發現自己的站點被聯通劫持注入噁心的話費充值廣告,決定讓我的網站強制使用 HTTPS,避免 ISP 劫持。
使用 HTTPS 前的一些疑惑
現在是 2016 年,使用 HTTPS 已經不像幾年前是一件昂貴的事情。當然我也是自己瞭解了一圈才消除了自己的疑惑,主要是:
- 我的網站(一個簡單的博客)可能沒必要使用 HTTPS
- HTTPS 會不會讓網站速度變慢?
- HTTPS 需要花錢吧?證書好像不便宜
- 配置和維護 HTTPS 代價很高
要回答這些問題,推薦大家去看一下 Google I/O 2016 的視頻(Youtube):Mythbusting HTTPS: Squashing security’s urban legends - Google I/O 2016
視頻裏把所有問題都詳細一一解答,強烈推薦大家把視頻看完。
我簡單總結:
- 每個網站都應該用 HTTPS,就算是全靜態站點也同樣如此,運營商劫持嚴重干擾訪問者的體驗
- 有幾項技術可以提高 HTTPS 的性能,包括 Strict Transport Security,TLS False Start 和 HTTP/2 ,這些技術讓 HTTPS 速度不慢,某些情況下會甚至更快
- HTTPS 針對個人單個(或者幾個)域名的使用來說,已經是免費的
- 配置和維護 HTTPS 異常簡單,Let's Encrypt 這個項目通過自動化把事情簡單化了
有哪些靠譜的免費 HTTPS 證書提供商?
選擇證書提供商有3個主要考量:1. 瀏覽器和操作系統支持程度 2. 證書類型 3. 維護成本
1. 瀏覽器和操作系統支持程度
基本你能查到的熱門證書提供商,支持程度都不會太差。例如 Let's Encrypt 的支持可以訪問:Which browsers and operating systems support Let’s Encrypt
可以看到,Android 2.3.6 以上,Firefox 2.0 以上,Windows Vista 以上,iOS 3.1 以上,Google Chrome全平臺都是支持的。這一點就不用太擔心了,看你你的網站受衆情況來決定。對於我來說,我完全不在乎 Windows XP 的 IE 用戶。
2. 證書類型
HTTPS 證書分爲3類, 1. DV 域名驗證證書 2. OV 組織機構驗證證書 3. EV 增強的組織機構驗證證書。每類證書在審覈和驗證方面要求嚴格程度不同,瀏覽器會在地址欄給予不同證書不一樣的展現。
一般個人使用DV證書完全夠了,瀏覽器表現爲地址欄前會有綠色的小鎖。下面聊到的免費證書都是 DV 域名驗證證書。
3. 維護成本
我調研不多,使用過 StartSSL,現在用 Let's Encrypt。StartSSL 的免費證書有效期是1年,1年後需要手動更換。配置過程還挺麻煩的。
更推薦 Let's Encrypt,雖然有效期只有3個月,但可以用 certbot 自動續期,完全不受影響。而且 Let's Encrypt 因爲有了 certbot 這樣的自動化工具,配置管理起來非常容易。
生成 Let's Encrypt 證書
Let's Encrypt 證書生成不需要手動進行,官方推薦 certbot 這套自動化工具來實現。3步輕鬆搞定:
- 下載安裝 certbot (Let’s Encrypt項目的自動化工具)
- 創建配置文件
- 執行證書自動化生成命令
下面的教程運行在 Arch Linux 上,其他操作系統也大同小異。你可以在 certbot 網站上,選擇你的 Web Server 和 操作系統,就能看到對應的安裝和配置教程。
1. 下載安裝 certbot
在 Arch Linux 上,安裝很簡單:
$ sudo pacman -Syu
$ sudo pacman -S certbot
2. 創建配置文件
先創建存放配置文件的文件夾:
$ sudo mkdir /etc/letsencrypt/configs
編輯配置文件:
$ sudo vim /etc/letsencrypt/configs/example.com.conf
把 example.com 替換成自己的域名,配置文件內容:
# 寫你的域名和郵箱
domains = example.com
rsa-key-size = 2048
email = [email protected]
text = True
# 把下面的路徑修改爲 example.com 的目錄位置
authenticator = webroot
webroot-path = /var/www/example
這裏需要解釋一下,上面配置文件用了 webroot 的驗證方法,這種方法適用於已經有一個 Web Server 運行中的情況。certbot 會自動在 /var/www/example
下面創建一個隱藏文件 .well-known/acme-challenge
,通過請求這個文件來驗證
example.com 確實屬於你。外網服務器訪問 http://www.example.com/.well-known/acme-challenge ,如果訪問成功則驗證OK。
我們不需要手動創建這個文件,certbot 會根據配置文件自動完成。
3. 執行證書自動化生成命令
一切就緒,我們現在可以運行 certbot 了。
$ sudo certbot -c /etc/letsencrypt/configs/example.com.conf certonly
## 片刻之後,看到下面內容就是成功了
IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at /etc/letsencrypt/live/example.com/fullchain.pem.
如果運行順利,所有服務器所需要的證書就已經生成好了。他們被放在了 /etc/letsencrypt/live/example.com/
下:
$ ls /etc/letsencrypt/live/example.com/
cert.pem #server cert only
privkey.pem #private key
chain.pem #intermediates
fullchain.pem #server cert + intermediates
配置 Nginx 加入證書
到這裏已經成功一大半了,只需要配置 Nginx 支持剛剛生成的證書。而且這個配置有最佳實踐可以參考,訪問:Mozilla SSL Configuration Generator,這是 Mozilla 搞得一個 HTTPS 配置文件自動生成器,支持 Apache,Nginx 等多種服務器。按照這個配置文件,選擇 Intermediate 的兼容性。這裏生成的配置文件是業界最佳實踐和結果,讓 Nginx 打開了各種增加安全性和性能的參數。
默認配置文件是這樣的:
server {
listen 80 default_server;
listen [::]:80 default_server;
# Redirect all HTTP requests to HTTPS with a 301 Moved Permanently response.
return 301 https://$host$request_uri;
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
# certs sent to the client in SERVER HELLO are concatenated in ssl_certificate
ssl_certificate /path/to/signed_cert_plus_intermediates;
ssl_certificate_key /path/to/private_key;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
# Diffie-Hellman parameter for DHE ciphersuites, recommended 2048 bits
ssl_dhparam /path/to/dhparam.pem;
# intermediate configuration. tweak to your needs.
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
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;
# HSTS (ngx_http_headers_module is required) (15768000 seconds = 6 months)
add_header Strict-Transport-Security max-age=15768000;
# OCSP Stapling ---
# fetch OCSP records from URL in ssl_certificate and cache them
ssl_stapling on;
ssl_stapling_verify on;
## verify chain of trust of OCSP response using Root CA and Intermediate certs
ssl_trusted_certificate /path/to/root_CA_cert_plus_intermediates;
resolver <IP DNS resolver>;
....
}
請根據自己的服務配置修改和添加內容,重點只需要關注6行:
server {
listen 443 ssl http2;
....
ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
ssl_dhparam /etc/nginx/ssl/dhparam.pem;
ssl_trusted_certificate /etc/letsencrypt/live/example.com/root_ca_cert_plus_intermediates;
resolver <IP DNS resolver>;
....
}
這6行中,部分文件還不存在,逐個說明。
首先是第一行 listen 443 ssl http2;
作用是啓用
Nginx 的 ngxhttpv2_module 模塊 支持 HTTP2,Nginx 版本需要高於 1.9.5,且編譯時需要設置 --with-http_v2_module
。Arch
Linux 的 Nginx 安裝包中已經編譯了這個模塊,可以直接使用。如果你的 Linux 發行版本中的 Nginx 並不支持這個模塊,可以自行 Google 如何加上。
ssl_certificate
和 ssl_certificate_key
,分別對應 fullchain.pem
和 privkey.pem
,這2個文件是之前就生成好的證書和密鑰。
ssl_dhparam
通過下面命令生成:
$ sudo mkdir /etc/nginx/ssl
$ sudo openssl dhparam -out /etc/nginx/ssl/dhparam.pem 2048
(可選)ssl_trusted_certificate
需要下載 Let's
Encrypt 的 Root Certificates,不過根據 Nginx
官方文檔 所說,ssl_certificate
如果已經包含了 intermediates
就不再需要提供 ssl_trusted_certificate
,這一步可以省略:
$ cd /etc/letsencrypt/live/example.com
$ sudo wget https://letsencrypt.org/certs/isrgrootx1.pem
$ sudo mv isrgrootx1.pem root.pem
$ sudo cat root.pem chain.pem > root_ca_cert_plus_intermediates
resolver
的作用是 “resolve
names of upstream servers into addresses”, 在這個配置中,resolver 是用來解析 OCSP 服務器的域名的,建議填寫你的 VPS 提供商的 DNS 服務器,例如我的 VPN 在 Linode,DNS服務器填寫:
resolver 106.187.90.5 106.187.93.5;
Nginx 配置完成後,重啓後,用瀏覽器測試是否一切正常。
$ sudo systemctl restart nginx
這時候你的站點應該默認強制使用了 HTTPS,並且瀏覽器地址欄左邊會有綠色的小鎖:
自動化定期更新證書
Let's Encrypt 證書有效期是3個月,我們可以通過 certbot 來自動化續期。
在 Arch Linux 上,我們通過 systemd 來自動執行證書續期任務。
$ sudo vim /etc/systemd/system/letsencrypt.service
[Unit]
Description=Let's Encrypt renewal
[Service]
Type=oneshot
ExecStart=/usr/bin/certbot renew --quiet --agree-tos
ExecStartPost=/bin/systemctl reload nginx.service
然後增加一個 systemd timer 來觸發這個服務:
$ sudo vim /etc/systemd/system/letsencrypt.timer
[Unit]
Description=Monthly renewal of Let's Encrypt's certificates
[Timer]
OnCalendar=daily
Persistent=true
[Install]
WantedBy=timers.target
啓用服務,開啓 timer:
$ sudo systemctl enable letsencrypt.timer
$ sudo systemctl start letsencrypt.timer
上面兩條命令執行完畢後,你可以通過 systemctl list-timers
列出所有
systemd 定時服務。當中可以找到 letsencrypt.timer
並看到運行時間是明天的凌晨12點。
在其他 Linux 發行版本中,可以使用 crontab 來設定定時任務,自行 Google 吧。
用專業在線工具測試你的服務器 SSL 安全性
Qualys SSL Labs 提供了全面的 SSL 安全性測試,填寫你的網站域名,給自己的 HTTPS 配置打個分。
如果你完全按照我上面教程配置,遵循了最佳實踐,你應該和我一樣得分是 A+
這意味着你啓用了HTTPS,現在足夠的安全,並且使用了最新技術,保證了性能。
爲自己鼓個掌。 (๑•̀ㅂ•́)و✧