nginx環(huán)境下配置ssl加密(單雙向認證、部分https)
nginx下配置ssl本來是很簡單的,無論是去認證中心買SSL安全證書還是自簽署證書,但最近公司OA的一個需求,得以有個機會實際折騰一番。一開始采用的是全站加密,所有訪問http:80的請求強制轉(zhuǎn)換(rewrite)到https,后來自動化測試結(jié)果說響應(yīng)速度太慢,https比http慢慢30倍,心想怎么可能,鬼知道他們怎么測的。所以就試了一下部分頁面https(不能只針對某類動態(tài)請求才加密)和雙向認證。下面分節(jié)介紹。
默認nginx是沒有安裝ssl模塊的,需要編譯安裝nginx時加入--with-http_ssl_module選項。
關(guān)于SSL/TLS原理請參考 這里,如果你只是想測試或者自簽發(fā)ssl證書,參考 這里 。
提示:nignx到后端服務(wù)器由于一般是內(nèi)網(wǎng),所以不加密。
1. 全站ssl
全站做ssl是最常見的一個使用場景,默認端口443,而且一般是單向認證。
server { listen 443; server_name example.com; root /apps/www; index index.html index.htm; ssl on; ssl_certificate ../SSL/ittest.pem; ssl_certificate_key ../SSL/ittest.key; # ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2; # ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP; # ssl_prefer_server_ciphers on; }
如果想把http的請求強制轉(zhuǎn)到https的話:
server { listen 80; server_name example.me; rewrite ^ https://$server_name$request_uri? permanent; ### 使用return的效率會更高 # return 301 https://$server_name$request_uri; }
ssl_certificate
證書其實是個公鑰,它會被發(fā)送到連接服務(wù)器的每個客戶端,ssl_certificate_key
私鑰是用來解密的,所以它的權(quán)限要得到保護但nginx的主進程能夠讀取。當(dāng)然私鑰和證書可以放在一個證書文件中,這種方式也只有公鑰證書才發(fā)送到client。
ssl_protocols
指令用于啟動特定的加密協(xié)議,nginx在1.1.13和1.0.12版本后默認是ssl_protocols
SSLv3 TLSv1 TLSv1.1 TLSv1.2,TLSv1.1
與TLSv1.2要確保OpenSSL >= 1.0.1 ,SSLv3 現(xiàn)在還有很多地方在用但有不少被攻擊的漏洞。
ssl_ciphers
選擇加密套件,不同的瀏覽器所支持的套件(和順序)可能會不同。這里指定的是OpenSSL庫能夠識別的寫法,你可以通過 openssl
(后面是你所指定的套件加密算法) 來看所支持算法。
-v cipher 'RC4:HIGH:!aNULL:!MD5'
ssl_prefer_server_ciphers on
設(shè)置協(xié)商加密算法時,優(yōu)先使用我們服務(wù)端的加密套件,而不是客戶端瀏覽器的加密套件。
https優(yōu)化參數(shù)
ssl_session_cache shared:SSL:10m;
: 設(shè)置ssl/tls會話緩存的類型和大小。如果設(shè)置了這個參數(shù)一般是shared
,buildin
可能會參數(shù)內(nèi)存碎片,默認是none
,和off
差不多,停用緩存。如shared:SSL:10m
表示我所有的nginx工作進程共享ssl會話緩存,官網(wǎng)介紹說1M可以存放約4000個sessions。 詳細參考serverfault上的問答ssl_session_cache。- ssl_session_timeout : 客戶端可以重用會話緩存中ssl參數(shù)的過期時間,內(nèi)網(wǎng)系統(tǒng)默認5分鐘太短了,可以設(shè)成30m即30分鐘甚至4h。
設(shè)置較長的keepalive_timeout
也可以減少請求ssl會話協(xié)商的開銷,但同時得考慮線程的并發(fā)數(shù)了。
提示:在生成證書請求csr文件時,如果輸入了密碼,nginx每次啟動時都會提示輸入這個密碼,可以使用私鑰來生成解密后的key來代替,效果是一樣的,達到免密碼重啟的效果:
openssl rsa -in ittest.key -out ittest_unsecure.key
導(dǎo)入證書
如果你是找一個知名的ssl證書頒發(fā)機構(gòu)如VeriSign、Wosign、StartSSL簽發(fā)的證書,瀏覽器已經(jīng)內(nèi)置并信任了這些根證書,如果你是自建C或獲得二級CA授權(quán),都需要將CA證書添加到瀏覽器,這樣在訪問站點時才不會顯示不安全連接。各個瀏覽的添加方法不在本文探討范圍內(nèi)。
2. 部分頁面ssl
一個站點并不是所有信息都是非常機密的,如網(wǎng)上商城,一般的商品瀏覽可以不通過https,而用戶登錄以及支付的時候就強制經(jīng)過https傳輸,這樣用戶訪問速度和安全性都得到兼顧。
但是請注意不要理解錯了,是對頁面加密而不能針對某個請求加密,一個頁面或地址欄的URL一般會發(fā)起許多請求的,包括css/png/js等靜態(tài)文件和動態(tài)的Java或PHP請求,所以要加密的內(nèi)容包含頁面內(nèi)的其它資源文件,否則就會出現(xiàn)http與https內(nèi)容混合的問題。在http頁面混有https內(nèi)容時,頁面排版不會發(fā)生亂排現(xiàn)象;在https頁面中包含以http方式引入的圖片、js等資源時,瀏覽器為了安全起見會阻止加載。
下面是只對example.com/account/login
登錄頁面進行加密的栗子:
root /apps/www; index index.html index.htm; server { listen 80; server_name example.com; location ^~ /account/login { rewrite ^ https://$server_name:443$request_uri? permanent; } location / { proxy_pass http://localhost:8080; ### Set headers #### proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_redirect off; } } server { listen 443 ssl; server_name example.com; ssl on; ssl_certificate ../SSL/ittest.pem; ssl_certificate_key ../SSL/ittest.key; ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP; ssl_prefer_server_ciphers on; location ^~ /account/login { proxy_pass http://localhost:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_redirect off; ### Most PHP, Python, Rails, Java App can use this header -> https ### proxy_set_header X-Forwarded-Proto $scheme; } location / { rewrite ^ http://$server_name$request_uri? permanent; } }
關(guān)于rewrite與location的寫法參考這里。當(dāng)瀏覽器訪問http://example.com/account/login.xx
時,被301到https://example.com/account/login.xx
,在這個ssl加密的虛擬主機里也匹配到/account/login,反向代理到后端服務(wù)器,后面的傳輸過程是沒有https的。這個login.xx頁面下的其它資源也是經(jīng)過https請求nginx的,登錄成功后跳轉(zhuǎn)到首頁時的鏈接使用http,這個可能需要開發(fā)代碼里面控制。
- 上面配置中使用了
proxy_set_header X-Forwarded-Proto$scheme
,在jsp頁面使用request.getScheme()
得到的是https 。如果不把請求的$scheme協(xié)議設(shè)置在header里,后端jsp頁面會一直認為是http,將導(dǎo)致響應(yīng)異常。 - ssl配置塊還有個與不加密的80端口類似的
location>/
,它的作用是當(dāng)用戶直接通過https訪問首頁時,自動跳轉(zhuǎn)到不加密端口,你可以去掉它允許用戶這樣做。
3. 實現(xiàn)雙向ssl認證
上面的兩種配置都是去認證被訪問的站點域名是否真實可信,并對傳輸過程加密,但服務(wù)器端并沒有認證客戶端是否可信。(實際上除非特別重要的場景,也沒必要去認證訪問者,除非像銀行U盾這樣的情況)
要實現(xiàn)雙向認證HTTPS,nginx服務(wù)器上必須導(dǎo)入CA證書(根證書/中間級證書),因為現(xiàn)在是由服務(wù)器端通過CA去驗證客戶端的信息。還有必須在申請服務(wù)器證書的同時,用同樣的方法生成客戶證書。取得客戶證書后,還要將它轉(zhuǎn)換成瀏覽器識別的格式(大部分瀏覽器都認識PKCS12格式):
openssl pkcs12 -export -clcerts -in client.crt -inkey client.key -out client.p12
然后把這個client.p12
發(fā)給你相信的人,讓它導(dǎo)入到瀏覽器中,訪問站點建立連接的時候nginx會要求客戶端把這個證書發(fā)給自己驗證,如果沒有這個證書就拒絕訪問。
同時別忘了在 nginx.conf 里配置信任的CA:(如果是二級CA,請把根CA放在后面,形成CA證書鏈)
proxy_ignore_client_abort on; ssl on; ... ssl_verify_client on; ssl_verify_depth 2; ssl_client_certificate ../SSL/ca-chain.pem; #在雙向location下加入: proxy_set_header X-SSL-Client-Cert $ssl_client_cert;
拓展:使用geo模塊
nginx默認安裝了一個ngx_http_geo_module
,這個geo模塊可以根據(jù)客戶端IP來創(chuàng)建變量的值,用在如來自172.29.73.0/24段的IP訪問login時使用雙向認證,其它段使用一般的單向認證。
geo $duplexing_user { default 1; include geo.conf; # 注意在0.6.7版本以后,include是相對于nginx.conf所在目錄而言的 }
語法 geo [$address] $variable { … }
,位于http段,默認地址是$reoute_addr
,假設(shè) conf/geo.conf
內(nèi)容:
127.0.0.1/32 LOCAL; # 本地
172.29.73.23/32 SEAN; # 某個IP
172.29.73.0/24 1; # IP段,可以按國家或地域定義后面的不同的值
需要配置另外一個虛擬主機server{ssl 445},里面使用上面雙向認證的寫法,然后在80或443里使用變量$duplexing_user
去判斷,如果為1就rewrite到445,否則rewrite到443。具體用法可以參考nginx geo使用方法。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
利用Nginx處理Vue開發(fā)環(huán)境的跨域的方法
這篇文章主要介紹了利用Nginx處理Vue開發(fā)環(huán)境的跨域的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2019-06-06Nginx實現(xiàn)http自動跳轉(zhuǎn)到https
本文主要介紹了Nginx實現(xiàn)http自動跳轉(zhuǎn)到https,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-01-01Nginx?location和proxy_pass配置示例詳解
這篇文章主要介紹了Nginx?location和proxy_pass配置的相關(guān)資料,本文詳細探討了Nginx配置中`location`和`proxy_pass`指令的不同組合方式及其對請求轉(zhuǎn)發(fā)路徑的影響,通過列舉多種組合,展示了`location`匹配目錄與`proxy_pass`地址路徑如何相互作用,需要的朋友可以參考下2024-11-11Windows?Server?Nginx?反向代理Spring?Boot配置無效報404未找到的問題
一個Spring?Boot的系統(tǒng),開發(fā)完成發(fā)布到Windows服務(wù)器里,使用nginx作為反向代理,修改刷新配置文件,nginx.conf,總是報錯404,這篇文章主要介紹了Windows?Server?Nginx?反向代理Spring?Boot配置無效?404?未找到的問題及解決方案2024-01-01nginx中proxy_set_header參數(shù)的實現(xiàn)
本文詳細介紹了Nginx中proxy_set_header指令的用法,通過設(shè)置不同的請求頭信息,可以實現(xiàn)更靈活的反向代理功能,具有一定的參考價值,感興趣的可以了解一下2024-12-12nginx的keepalive相關(guān)參數(shù)使用源碼解讀
這篇文章主要為大家介紹了nginx的keepalive相關(guān)參數(shù)使用源碼解讀,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-12-12Nginx結(jié)合Openresty通過Lua+Redis實現(xiàn)動態(tài)封禁IP
為了封禁某些爬蟲或者惡意用戶對服務(wù)器的請求,我們需要建立一個動態(tài)的 IP 黑名單,本文主要介紹了Nginx結(jié)合Openresty通過Lua+Redis實現(xiàn)動態(tài)封禁IP,感興趣的可以了解一下2023-11-11