https單向驗證應用普遍想必你們都很熟悉,我已經在一篇博文中分享過,此次來看看Nginx如何實現雙向驗證。
php
單向驗證與雙向驗證的區別:css
單向驗證: 指客戶端驗證服務器端證書,服務器並不須要驗證客戶端證書。html
雙向驗證:指客戶端驗證服務器端證書,而服務器也須要經過CA的公鑰證書來驗證客戶端證書。node
詳細的握手過程:nginx
單向驗證web
瀏覽器發送一個鏈接請求給安全服務器。算法
一、服務器將本身的證書,以及同證書相關的信息發送給客戶瀏覽器。apache
二、客戶瀏覽器檢查服務器送過來的證書是不是由本身信賴的CA中心所簽發的。若是是,就繼續執行協議;若是不是,客戶瀏覽器就給客戶一個警告消息:警告客戶這個證書不是能夠信賴的詢問客戶是否須要繼續。vim
三、接着客戶瀏覽器比較證書裏的消息,例如域名和公鑰,與服務器剛剛發送的相關消息是否一致,若是是一致的,客戶瀏覽器承認這個服務器的合法身份。windows
四、瀏覽器隨機產生一個用於後面通信的「通話密鑰」,而後用服務器的公鑰對其加密,而後將加密後的「預主密碼」傳給服務器。
五、服務器從客戶發送過來的密碼方案中,選擇一種加密程度最高的密碼方案,用服務器的私鑰加密後通知瀏覽器。
六、瀏覽器針對這個密碼方案,接着用服務器的公鑰加過密後發送給服務器。
七、服務器接收到瀏覽器送過來的消息,用本身的私鑰解密,得到。
八、服務器、瀏覽器接下來的通信都是用對稱密碼方案,使用相同的對稱密鑰。
雙向驗證
一、瀏覽器發送一個鏈接請求給安全服務器。
二、服務器將本身的證書,以及同證書相關的信息發送給客戶瀏覽器。
三、客戶瀏覽器檢查服務器送過來的證書是不是由本身信賴的CA中心所簽發的。若是是,就繼續執行協議;若是不是,客戶瀏覽器就給客戶一個警告消息:警告客戶這個證書不是能夠信賴的詢問客戶是否須要繼續。
四、接着客戶瀏覽器比較證書裏的消息,例如域名和公鑰,與服務器剛剛發送的相關消息是否一致,若是是一致的,客戶瀏覽器承認這個服務器的合法身份。
五、服務器要求客戶的身份認證,用戶能夠創建一個隨機數而後對其進行數字簽名,將這個含有簽名的隨機數和客戶本身的證書以及加密過的「預主密碼」一塊兒傳給服務器。
六、服務器必須檢驗客戶證書和簽名隨機數的合法性,具體的合法性驗證過程包括:客戶的證書使用日期是否有效,爲客戶提供證書的CA 是否可靠,發行CA 的公鑰可否正確解開客戶證書的發行CA的數字簽名,檢查客戶的證書是否在證書廢止列表(CRL)中。檢驗若是沒有經過,通信馬上中斷;若是驗證經過,服務器將用本身的私鑰解開加密的「預主密碼」,而後執行一系列步驟來產生主通信密碼(客戶端也將經過一樣的方法產生相同的主通信密碼)。
七、客戶瀏覽器告訴服務器本身所可以支持的通信對稱密碼方案。
八、服務器從客戶發送過來的密碼方案中,選擇一種加密程度最高的密碼方案,用客戶的公鑰加過密後通知瀏覽器。
九、瀏覽器針對這個密碼方案,選擇一個通話密鑰,接着用服務器的公鑰加過密後發送給服務器。
十、服務器接收到瀏覽器送過來的消息,用本身的私鑰解密,得到通話密鑰。
十一、服務器、瀏覽器接下來的通信都是用對稱密碼方案,使用相同的對稱密鑰。
1、自建CA,簽署證書
# openssl 配置文件路徑 vim /etc/pki/tls/openssl.cnf # 下面只列出配置文件中和自建CA有關的幾個關鍵指令 dir = /etc/pki/CA # CA的工做目錄 database = $dir/index.txt # 簽署證書的數據記錄文件 new_certs_dir = $dir/newcerts # 存放新簽署證書的目錄 serial = $dir/serial # 新證書籤署號記錄文件 certificate = $dir/ca.crt # CA的證書路徑 private_key = $dir/private/cakey.pem # CA的私鑰路徑
使用openssl製做CA的自簽名證書
# 切換到CA的工做目錄 cd /etc/pki/CA # 製做CA私鑰 (umask 077; openssl genrsa -out private/cakey.pem 2048) # 製做自簽名證書 openssl req -new -x509 -key private/cakey.pem -out ca.crt # 生成數據記錄文件,生成簽署號記錄文件,給文件一個初始號。 touch index.txt touch serial echo '01'> serial # 自建CA完成
準備服務器端證書
# 製做服務器端私鑰 (umask 077; openssl genrsa -out server.key 1024) # 製做服務器端證書申請指定使用sha512算法簽名 (默認使用sha1算法) openssl req -new -key server.key -sha512 -out server.csr # 簽署證書 openssl ca -in server.csr -out server.crt -days 3650
準備客戶端證書
# 製做客戶端私鑰 (umask 077; openssl genrsa -out kehuduan.key 1024) # 製做客戶端證書申請 openssl req -new -key kehuduan.key -out kehuduan.csr # 簽署證書 openssl ca -in kehuduan.csr -out kehuduan.crt -days 3650
注意事項:
一、製做證書時會提示輸入密碼,設置密碼可選,服務器證書和客戶端證書密碼能夠不相同。
二、服務器證書和客戶端證書製做時提示輸入省份、城市、域名信息等,需保持一致。
三、如下信息根證書須要和客戶端證書匹配,不然可能出現簽署問題。
countryName = match
stateOrProvinceName = match
organizationName = match
organizationalUnitName = match
如何指定簽署證書的簽名算法
openssl req xx -[digest] Digest to sign with (see openssl dgst -h for list)
查看使用的簽名算法:
# 使用-sha256指定算法 openssl req -new -key server.key -sha256 -out server.csr
2、提供Nginx配置文件
server { listen 443; server_name pro.server.com; ssi on; ssi_silent_errors on; ssi_types text/shtml; ssl on; ssl_certificate /data/server/nginx/ssl/self/server.crt; ssl_certificate_key /data/server/nginx/ssl/self/server.key; ssl_client_certificate /data/server/nginx/ssl/self/ca/ca.crt; ssl_verify_client on; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-RC4-SHA:!ECDHE-RSA-RC4-SHA:ECDH-ECDSA-RC4-SHA:ECDH-RSA-RC4-SHA:ECDHE-RSA-AES256-SHA:!RC4-SHA:HIGH:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!CBC:!EDH:!kEDH:!PSK:!SRP:!kECDH; ssl_prefer_server_ciphers On; index index.html index.htm index.php; root /data/www; location ~ .*\.(php|php5)?$ { #fastcgi_pass unix:/tmp/php-cgi.sock; fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; include fastcgi.conf; } location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ { expires 30d; } location ~ .*\.(js|css)?$ { expires 1h; } ###this is to use open website lianjie like on apache## location / { if (!-e $request_filename) { rewrite ^(.*)$ /index.php?s=$1 last; break; } keepalive_timeout 0; } location ~ /.svn/ { deny all; } ###end## include /data/server/nginx/conf/rewrite/test.conf; access_log /log/nginx/access/access.log; }
客戶端證書格式轉換
# 將文本格式的證書轉換成能夠導入瀏覽器的證書 openssl pkcs12 -export -clcerts -in client.crt -inkey client.key -out client.p12
3、將證書導入瀏覽器,這裏以Chrome爲例
一、在瀏覽器窗口右上角找到設置
二、在設置窗口中找到高級設置
三、找到管理證書
四、點擊導入證書,而後選擇證書路徑就能夠了
五、在導入證書以後就能夠正常訪問到服務器數據了
六、若是沒有成功導入客戶端證書就訪問服務器的話,那麼服務器驗證客戶端證書這步就會失敗,而後返回以下錯誤
因爲用的是自簽證書不被公有CA信任,因此https那裏會有紅叉。
附加內容: 如何配置級聯證書鏈
(2016/11/08)
爲何我以前寫這篇的時候沒有寫上,而是以後加上這塊呢?
由於以前作的實驗用的是自簽名證書,所謂的自簽名證書就是CA也是本身作,本身給本身發證。
那麼咱們在簽發服務端證書和客戶端證書的時候,是由本身所建立的根級CA下發的。 不存在一級、二級代理CA的概念。在Nginx上配置校驗客戶端證書時,只須要制定根級CA的證書就夠了。
可是在實際運用過程當中,咱們極可能會在CA代理機構,申請受信任的證書,這個機構極可能就會是代理CA,也就是由根級CA受權的下級CA,有數字證書的簽發資格。
舉個例子,假若有一個二級代理CA簽發了一個證書,那麼當須要校驗這個證書的合法性時,須要用到簽發這個證書的二級代理CA的證書來校驗。 那麼二級代理CA的證書是否又可信呢? 那麼就須要給二級代理CA發證的,一級代理CA的證書來校驗,層層遞進,直到根CA證書。這就是級聯證書的校驗模式。
這時候在配置Nginx校驗客戶端證書時,只指定給發證的二級代理CA的證書就不行了。 還須要跟上能校驗二級代理CA證書的根CA證書。
在HTTPS雙向驗證中,指定CA證書來校驗客戶端證書時,是用於校驗整個信任域。 好比: 你的頂級域名是 baidu.com。 那麼任何 xxx.baidu.com 的證書均可以被信任。
假設在startSSL申請了一個SSL證書
使用者: test.baidu.com
頒發者: StartCom Class 1 DV Server CA
打開這個CA證書能夠看到,它上面還有一級,它的頒發者是 StartCom Certification Authority
而後再打開這個CA的證書,查看頒發者和使用者都相同,那它應該就是根級CA了。
test.baidu.com 做爲客戶端證書,Nginx配置校驗:
一、打開代理CA和根級CA的證書,複製代理CA證書中的內容,貼到根CA證書內容的下方,保存;
二、提供Nginx配置文件
server { listen 443; server_name test.baidu.com; ssl on; ssl_certificate /alidata/server/nginx/ssl/server.baidu.com.crt; ssl_certificate_key /alidata/server/nginx/ssl/server.key; ssl_verify_depth 2; ssl_client_certificate /alidata/server/nginx/ssl/ca/ca_and_proxyca.crt; ssl_verify_client on; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-RC4-SHA:!ECDHE-RSA-RC4-SHA:ECDH-ECDSA-RC4-SHA:ECDH-RSA-RC4-SHA:ECDHE-RSA-AES256-SHA:!RC4-SHA:HIGH:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!CBC:!EDH:!kEDH:!PSK:!SRP:!kECDH; ssl_prefer_server_ciphers on; index index.html index.htm index.php; root /alidata/www/default; }
部分重點配置解釋:
ssl_verify_client on 開啓客戶端身份校驗
ssl_client_certificate 指定用於校驗客戶端證書的CA的證書,若是是代理級CA,那麼須要把內容並在一塊兒。
ssl_verify_depth 指定校驗深度
證書常見的三種格式,pem、der、pkcs12
pem 格式也就是文本格式,能夠直接用文本編輯器打開看到證書內容的,這也是最多見的格式。
der 這種格式沒法直接經過文本編輯器打開查看內容,一般用在JAVA環境。
pkcs12 用於導入瀏覽器的格式
格式轉換:
# pem 轉 der openssl x509 -inform pem -in certificate.crt -out certificate.cer -outform DER # pem 格式的證書有含私鑰的,和不含私鑰的。 # der 轉 pem openssl x509 -inform der -in certificate.cer -out certificate.pem # 私鑰轉化 der 轉 pem openssl rsa -inform DER -outform PEM -in privatekey.der -out privatekey.pem # pem 轉 pkcs12 openssl pkcs12 -export -in Cert.pem -out Cert.p12 -inkey key.pem # pkcs12 轉 pem openssl pkcs12 -nocerts -nodes -in cert.p12 -out private.pem openssl pkcs12 -clcerts -nokeys -in cert.p12 -out cert.pem # P7B 轉換爲 PEM (P7B格式通常出如今windows server和tomcat中,無私鑰) openssl pkcs7 -print_certs -in incertificat.p7b -out outcertificate.cer # PFX 轉換爲PEM (PFX格式通常出如今windows server中) #提取私鑰 openssl pkcs12 -in certname.pfx -nocerts -out key.pem -nodes #提取證書 openssl pkcs12 -in certname.pfx -nokeys -out cert.pem # 從pem私鑰中提取公鑰 openssl rsa -in rsa_private_key.pem -pubout -out rsa_public_key.pem