前提
- 首先要保證你的openssl的版本高于1.0.2
? ~ openssl version
OpenSSL 1.0.2g 1 Mar 2016
- 其次您觉,你的nginx要高于1.9.5(高于此版本才能支持http2.0), Ubuntu16.04使用apt安裝時(shí)滋捶,安裝的是1.10.3版本次氨,所以O(shè)K
? ~ nginx -v
nginx version: nginx/1.10.3 (Ubuntu)
安裝驗(yàn)證SSL的證書
我使用的是Let's Encrypt的免費(fèi)證書(以下簡(jiǎn)稱LE)蠢沿,而LE組織提供一個(gè)自動(dòng)化安裝配置工具就是Certbot苛吱,因此接下來將以Certbot為例來進(jìn)行安裝和配置
安裝Certbot
最新的資料請(qǐng)查看Certbot官網(wǎng)
# 此處針對(duì)的是Ubuntu系統(tǒng)Nginx
$ sudo apt-get update
$ sudo apt-get install software-properties-common
$ sudo add-apt-repository ppa:certbot/certbot
$ sudo apt-get update
$ sudo apt-get install python-certbot-nginx
使用Certbot
Certbot主要幫助我們實(shí)現(xiàn)如下功能:
- 自動(dòng)生成證書
- 自動(dòng)配置nginx的配置文件(主要是配置證書位置)
- 驗(yàn)證網(wǎng)站(即通過webroot的方式來驗(yàn)證該域名是否確實(shí)屬于你)
通常情況下屹电,我們只需要使用如下命令夜焦,certbot就會(huì)自動(dòng)幫助我們配置nginx壳澳,并自動(dòng)獲取和驗(yàn)證證書。但是保險(xiǎn)起見在使用該命令之前最好先將nginx的配置文件備份一下茫经,然后再執(zhí)行命令:
$ sudo certbot --nginx
執(zhí)行該命令會(huì)出現(xiàn)交互式的提示界面巷波,按照提示操作即可
但是在這里會(huì)有一個(gè)坑,就是必須打開443端口卸伞,之前我在阿里云的安全組中沒有打開443端口抹镊,因此導(dǎo)致報(bào)如下錯(cuò)誤:
Obtaining a new certificate
Performing the following challenges:
tls-sni-01 challenge for www.xxx.com
Waiting for verification...
Cleaning up challenges
Failed authorization procedure. www.xxx.com (tls-sni-01): urn:acme:error:connection :: The server could not connect to the client to verify the domain :: Timeout
IMPORTANT NOTES:
- The following errors were reported by the server:
Domain: www.xxx.com
Type: connection
Detail: Timeout
To fix these errors, please make sure that your domain name was
entered correctly and the DNS A/AAAA record(s) for that domain
contain(s) the right IP address. Additionally, please check that
your computer has a publicly routable IP address and that no
firewalls are preventing the server from communicating with the
client. If you're using the webroot plugin, you should also verify
that you are serving files from the webroot path you provided.
在阿里云上添加相應(yīng)安全規(guī)則,打開端口443然后就可以認(rèn)證通過了
配置crontab自動(dòng)更新證書
之后需要在crontab上加上相應(yīng)的命令來自動(dòng)更新證書:
crontab -e
# 添加如下兩行
# 這里是設(shè)置每月的1號(hào)凌晨3點(diǎn)開始更新證書荤傲,隨后3點(diǎn)05分重新reload nginx
00 03 1 * * /usr/bin/certbot renew --quiet
05 03 1 * * /usr/sbin/nginx -s reload
nginx最佳實(shí)踐
同時(shí)垮耳,為了https有更好的性能以及更加安全的配置,可以通過Mozilla的工具來自動(dòng)生成nginx最佳實(shí)踐配置遂黍。我的實(shí)際配置如下:
## WEB
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
ssl_certificate /etc/letsencrypt/live/domainname/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/domainname/privkey.pem; # managed by Certbot
# Diffie-Hellman parameter for DHE ciphersuites, this is for key exchange
ssl_dhparam /etc/letsencrypt/live/domainname/dhparam.pem;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
# 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;
resolver dns22.hichina.com dns21.hichina.com;
server_name domainname;
set $root /home/git/projects/newton/build;
root $root;
location / {
try_files $uri /index.html;
}
location /api/ {
proxy_pass http://127.0.0.1:5000/api/;
proxy_redirect default;
}
location /page/ {
proxy_pass http://127.0.0.1:5000/page/;
proxy_redirect default;
}
}
下面分別講解下
- 使用如下代碼是為了讓web server監(jiān)聽443端口终佛,即https端口. 同時(shí)打開http2的開關(guān)。要想支持http2需要OpenSSL的版本達(dá)到1.0.2(通過
openssl version
來檢查openssel版本)且nginx版本要高于1.0.9(通過nginx -v
來查詢nginx的版本號(hào))雾家,Ubuntu16.04在通過APT安裝時(shí)自動(dòng)安裝1.10.3的版本铃彰,所以滿足條件
listen 443 ssl http2;
listen [::]:443 ssl http2;
- 下面這部分代碼是certbot自動(dòng)添加的,用于指明證書的位置
ssl_certificate /etc/letsencrypt/live/domainname/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/domainname/privkey.pem; # managed by Certbot
- 下面這段代碼是用于key exchange時(shí)DH算法的芯咧,由于Nginx默認(rèn)使用的DH秘鑰長(zhǎng)度為1024位牙捉,不足夠安全,所以如果沒有如下的配置則會(huì)在SSL Labs的安全測(cè)試中只能得到B+的得分敬飒,而要想得到A+的得分邪铲,就必須生成2048位以上長(zhǎng)度的秘鑰。關(guān)于key exchange是怎么一回事可以參考阮一峰的文章, 關(guān)于Diffie-Hellman算法是怎么回事无拗,可以參考這個(gè)Youtube視頻
# Diffie-Hellman parameter for DHE ciphersuites, this is for key exchange
ssl_dhparam /etc/letsencrypt/live/domainname/dhparam.pem;
注意這里的dhparam.pem是需要自己生成的带到,且需要跟之前證書的位置為同一個(gè)目錄。生成dhparam.pem的方法如下
$ sudo openssl dhparam -out /etc/letsencrypt/live/domainname/dhparam.pem 2048
- 下面是https的優(yōu)化參數(shù)英染,不做解釋揽惹,直接粘貼過來
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:50m;
ssl_session_tickets off;
- 另外指令
ssl_ciphers
用于指定加密套件晌纫,避免使用不安全的加密套件 - 通常在使用http請(qǐng)求網(wǎng)站的時(shí)候,我們會(huì)通過發(fā)送301來重定向到https鏈接永丝,使用443端口建立連接,但是這樣必定會(huì)使得請(qǐng)求的時(shí)間加長(zhǎng)箭养,為了避免這種情況慕嚷,我們可以通過HSTS的方式來讓瀏覽器在一段時(shí)間內(nèi)固定使用https訪問網(wǎng)站,不論其是http請(qǐng)求還是https請(qǐng)求毕泌,這就避免了重定向喝检。HSTS實(shí)際是在返回的response的頭中添加了header
Strict-Transport-Security
,其nginx配置如下:
# HSTS (ngx_http_headers_module is required) (15768000 seconds = 6 months)
add_header Strict-Transport-Security max-age=15768000;
- 我們的瀏覽器通常在https請(qǐng)求時(shí)需要檢測(cè)證書狀態(tài)撼泛,其中一種方式就是通過對(duì)OCSP Server請(qǐng)求來獲取證書的狀態(tài)挠说,因此為了減少這種不必要的請(qǐng)求,可以通過OCSP Stabling來提高性能, 關(guān)于OCSP Stapling可以參考這里
ssl_stapling on;
ssl_stapling_verify on;
resolver dns22.hichina.com dns21.hichina.com;
檢測(cè)http2是否生效
最簡(jiǎn)單的辦法是使用chrome瀏覽器inspect工具當(dāng)中愿题,選擇Network损俭,再右鍵單擊Colume header,選擇protocol潘酗,讓column可以顯示protocol杆兵,如圖
然后我們就可以看到,http請(qǐng)求使用的是否是http2.0協(xié)議仔夺,如下琐脏,顯示h2表示使用的是http2.0協(xié)議,說明配置成功