1. 程式人生 > 實用技巧 >HTTPS和SSL優化使用心得之:減少等待時間與降低Https效能損耗(Apache/Nginx)

HTTPS和SSL優化使用心得之:減少等待時間與降低Https效能損耗(Apache/Nginx)

轉載:HTTPS和SSL優化使用心得之:減少等待時間與降低Https效能損耗(Apache/Nginx)

隨著大家上網安全意識的增強,以及各大主要網際網路公司對Https普及工作的推動,HTTPS SSL現在基本上成了建站的標配了。得益於Let’s Encrypt、Digicert、TrustAsia、Symantec等提供的免費SSL證書,現在不管是個人建站還是企業建站,上Https的成本可以忽略不計了。

為了安全,我們要上Https,但是開啟 SSL 會增加記憶體、CPU、網路頻寬的開銷。相對於http,使用TCP 三次握手建立連線,客戶端和伺服器需要交換3個包,https除了 TCP 的三個包,還要加上 ssl握手需要的9個包,一共是12個包。所以,HTTPS優化得不少反而容易出現效能慢的問題。

當然,有人可能為會認為HTTPS與SSL增加的伺服器開銷基本上沒有感覺到,這是因為網站的流量比較少,加上伺服器的效能配置足以支撐起當前的流量。但是對於大型的網站,例如百度、Google以及熱門APP,優化Https效能,減少資源消耗還是非常有用的。

展開索引

一、如何選擇免費SSL證書?

建議選擇Let’s Encrypt。Let’s Encrypt免費SSL證書雖然只有90天,但是可以無限期續期,並且支援手動和自動續期。Let’s Encrypt SSL在各大瀏覽器上都得到認可,是免費SSL證書的首選。(當然,如果你選擇阿里雲的話,證書是免費發放的有效期一年可以無限續期)

Let’s Encrypt適用於VPS等有獨立IP的主機上,否則只能使用一些利用Let’s Encrypt API開發的線上SSL證書申請。當然,有一定的經濟實力的話自然選擇付費的SSL證書更為可行,想要獲取其他免費SSL證書,可以參考文章《免費SSL證書收集整理彙總》

二、伺服器開啟HSTS

採用 HSTS 協議的網站將保證瀏覽器始終連線到網站的HTTPS版本,而不需要使用者手動在URL位址列中輸入包含https://的加密地址。我用的是Nginx 伺服器,只需要編輯 Nginx 配置檔案(如:/usr/local/nginx/conf/nginx.conf)將下面行新增到 HTTPS 配置的 server 塊中即可:

add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";

Apache、Lighttpd等啟用HSTS詳細的方法見:《Nginx中的Https安全與相容性配置詳細指南》。

三、域名加入HSTS preload list計劃

上面雖然是啟用了HSTS 協議保證了使用者訪問的始終是Https連線,但是一般地首次訪問網站使用者都會習慣性地輸入非https域名,這就導致了第一次訪問網站容易出現http劫持的問題。HSTS preload list計劃就是為了解決這個問題的,它是chrome\Firefox\Edge等瀏覽器內建的列表。

加入HSTS Preload List的方法:開啟HSTS功能並加入Preload List讓網站Https訪問更加安全(附代刪除HSTS方法)。目前本站已經成功加入到了HSTS preload list,如果你用的是Chrome或者Firefox,第一次訪問本站就是預設用Https連線的。

四、開啟HTTP/2和OCSP Stapling

HTTP/2 相比於之前的HTTP/1.1 在效能上的大幅度提升,所以只要你啟用了Https,記得一定要開啟HTTP/2,檢查一下你的配置檔案是否有:listen 443 ssl http2;

OCSP Stapling 伺服器事先模擬瀏覽器對證書鏈進行驗證,然後將 OCSP 驗證結果快取到本地。這樣,當瀏覽器訪問站點時,在握手階段,可以直接拿到 OCSP 響應結果和證書鏈,對訪問速度有明顯提升。

Nginx 中開啟 OCSP Stapling。(如果 ssl_certificate 指令指定了完整的證書鏈,則 ssl_trusted_certificate 可省略)

ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /path/to/certs/chained.pem;

Apache 中開啟 OCSP Stapling:

<VirtualHost></VirtualHost>中新增:

SSLUseStapling on

<VirtualHost></VirtualHost>外新增:

SSLStaplingCache shmcb:/tmp/stapling_cache(128000)

五、使用ECC和RSA雙證書

預設的我們都會使用RSA證書,因為RSA證書的相容性最為廣泛。但是ECC 證書擁有體積小、運算速度快、安全性高(256位ECC key就能起到相當於3072位的RSA key的安全性)等特點,可以在一定程度上提供Https效能。

Let’s Encrypt已經支援生成ECC 證書了,使用 acme.sh 簽發SSL證書, 指定--keylength ec-256就可以將證書型別改為 ECC:

acme.sh --issue -w /data/wwwroot/andyx.net -d andyx.net -d www.andyx.net --keylength ec-256

需要注意的是ECC在Windows XP上不相容,這個時候我們就會想到用雙證書了,即當不支援ECC證書時Nginx自動將RSA證書展示給使用者。如果nginx 的版本大於1.11,直接就可以在配置檔案中寫上ECC和RSA雙證書的路徑了,andyx.net演示如下:

#ECC
ssl_certificate /root/.acme.sh/andyx.net_ecc/fullchain.cer;
ssl_certificate_key /root/.acme.sh/andyx.net_ecc/andyx.net.key;
#RSA
ssl_certificate /usr/local/nginx/conf/ssl/andyx.net.crt;
ssl_certificate_key /usr/local/nginx/conf/ssl/andyx.net.key;

重啟Nginx,當XP等不支援ECC證書的使用者訪問網站時,顯示的是RSA證書。

而其它的使用者則優先使用ECC證書。

如果你發現ECC沒有優先顯示,檢查一下ssl_prefer_server_ciphers是否開啟,同時ssl_ciphers有沒有配置好,以下是andyx.net當用的配置:

ssl_prefer_server_ciphers on;
ssl_ciphers EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+ECDSA+AES128:EECDH+aRSA+AES128:RSA+AES128:EECDH+ECDSA+AES256:EECDH+aRSA+AES256:RSA+AES256:EECDH+ECDSA+3DES:EECDH+aRSA+3DES:RSA+3DES:!MD5;

另外,下面三個任選其一即可(僅供測試):

ssl_ciphers 'EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+ECDSA+AES128:EECDH+aRSA+AES128:RSA+AES128:EECDH+ECDSA+AES256:EECDH+aRSA+AES256:RSA+AES256:EECDH+ECDSA+3DES:EECDH+aRSA+3DES:RSA+3DES:!MD5';

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_ciphers 'ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA:ECDHE-ECDSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK';

六、 開啟DNS CAA

DNS CAA的作用是隻允許在記錄中列出的 CA 機構頒發針對該域名(或子域名)的證書,以防止有人偽造SSL證書,同時CAA 記錄可以控制單域名 SS L證書的發行,也可以控制萬用字元證書。

問題:開啟DNS CAA導致錯誤:Verify error:CAA record for *.andyx.netprevents issuance。解決的辦法就是增加issuewild記錄:0 issuewild "letsencrypt.org"。 另外提供兩個檢測CAA配置是否正確的網站:

  1. https://caatest.co.uk/
  2. https://dnsspy.io/labs/caa-validator

七、定期自動更新SSL證書

想手動更新方法:

# RSA
$ acme.sh --renew -d andyx.net –d www.andyx.net --force

# ECC
acme.sh --renew -d andyx.net –d www.andyx.net --force --ecc

一般地acme.sh已經自動添加了定時任務了,定期更新Let’s Encrypt證書,如果你發現沒有定期更新證書,檢查一下你的Cron任務是否正確,也可以試試強制更新:

"/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" --force

八、檢測SSL證書配置

常用的檢測網站有:

  1. https://www.ssllabs.com/ssltest/analyze.html
  2. https://myssl.com/

重點推薦用ssllabs.com,檢測的結果還是非常地準確,如下:

九、綜合

綜合以上優化策略,Nginx的配置檔案具體的優化如下:

server {

listen 443 ssl http2;
#使用HTTP/2,需要Nginx1.9.7以上版本

add_header Strict-Transport-Security "max-age=6307200; includeSubdomains; preload";
#開啟HSTS,並設定有效期為“6307200秒”(6個月),包括子域名(根據情況可刪掉),預載入到瀏覽器快取(根據情況可刪掉)

add_header X-Frame-Options DENY;
#禁止被嵌入框架

add_header X-Content-Type-Options nosniff;
#防止在IE9、Chrome和Safari中的MIME型別混淆攻擊

ssl_certificate /usr/local/nginx/conf/vhost/sslkey/www.linpx.com.crt;
ssl_certificate_key /usr/local/nginx/conf/vhost/sslkey/www.linpx.com.key;
#SSL證書檔案位置

ssl_trusted_certificate /usr/local/nginx/conf/vhost/sslkey/chaine.pem;
#OCSP Stapling的證書位置

ssl_dhparam /usr/local/nginx/conf/vhost/sslkey/dhparam.pem;
#DH-Key交換金鑰檔案位置

#SSL優化配置

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
#只允許TLS協議

ssl_ciphers EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
#加密套件,這裡用了CloudFlare's Internet facing SSL cipher configuration

ssl_prefer_server_ciphers on;
#由伺服器協商最佳的加密演算法

ssl_session_cache builtin:1000 shared:SSL:10m;
#Session Cache,將Session快取到伺服器,這可能會佔用更多的伺服器資源

ssl_session_tickets on;
#開啟瀏覽器的Session Ticket快取

ssl_session_timeout 10m; 
#SSL session過期時間

ssl_stapling on; 
#OCSP Stapling開啟,OCSP是用於線上查詢證書吊銷情況的服務,使用OCSP Stapling能將證書有效狀態的資訊快取到伺服器,提高TLS握手速度

ssl_stapling_verify on;
#OCSP Stapling驗證開啟

resolver 8.8.8.8 8.8.4.4 valid=300s;
#用於查詢OCSP伺服器的DNS

resolver_timeout 5s;
#查詢域名超時時間

···

}

實際使用過程中發現個別的“優化”還得根據自身的需要來確定,以下是andyx.net正在用的Nginx配置,僅供參考:

listen 80; 
listen 443 ssl http2;
#ECC
ssl_certificate /root/.acme.sh/andyx.net_ecc/fullchain.cer;
ssl_certificate_key /root/.acme.sh/andyx.net_ecc/andyx.net.key;  
#RSA 
ssl_certificate /usr/local/nginx/conf/ssl/andyx.net.crt;
ssl_certificate_key /usr/local/nginx/conf/ssl/andyx.net.key; 
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+ECDSA+AES128:EECDH+aRSA+AES128:RSA+AES128:EECDH+ECDSA+AES256:EECDH+aRSA+AES256:RSA+AES256:EECDH+ECDSA+3DES:EECDH+aRSA+3DES:RSA+3DES:!MD5;
ssl_prefer_server_ciphers on;
ssl_session_timeout 10m;
ssl_session_cache builtin:1000 shared:SSL:10m;
ssl_buffer_size 1400;
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
ssl_stapling on; 
ssl_stapling_verify on;

PS:這裡有一個線上生成SSL配置的網站,出自Mozilla,參考性非常高:

https://mozilla.github.io/server-side-tls/ssl-config-generator/