帶你使用Nginx實現HTTPS雙向驗證

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)

查看使用的簽名算法:

wKiom1dEXMygjao6AABWovfkDhQ536.png

# 使用-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爲例


一、在瀏覽器窗口右上角找到設置

wKiom1dFJK_iAIa0AAByQfijKWM484.png

二、在設置窗口中找到高級設置

wKioL1dFJbHSnDwQAABp-IlVvZc593.png

三、找到管理證書

wKiom1dFJMnR8d3zAACiVLwT94I491.png

四、點擊導入證書,而後選擇證書路徑就能夠了

wKioL1dFJcqz2RcgAABKRZb2kgU814.png

五、在導入證書以後就能夠正常訪問到服務器數據了

wKiom1dFJTWTqdbeAACGSlVFFqo683.png

六、若是沒有成功導入客戶端證書就訪問服務器的話,那麼服務器驗證客戶端證書這步就會失敗,而後返回以下錯誤

wKiom1dFJUPzkeUEAABN92QngcQ596.png

因爲用的是自簽證書不被公有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證書內容的下方,保存;

wKioL1ghSIOSgKT2AAAnfLDazDY834.png


二、提供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
相關文章
相關標籤/搜索