1. 程式人生 > >nginx上搭建https服務

nginx上搭建https服務

參考連結:https://www.cnblogs.com/dreamingodd/p/7357029.html

Https、OpenSSL自建CA證書及簽發證書、nginx單向認證、雙向認證及使用Java訪問

0.環境

本文的相關原始碼位於 https://github.com/dreamingodd/CA-generation-demo 

必須安裝nginx,必須安裝openssl,(用apt-get update, apt-get install來安裝比較簡單)

1.配置和指令碼

先建立一個demo目錄(位置自己選擇,我選擇建在nginx的目錄下):

mkdir /etc/nginx/ca-demo

cd /etc/nginx/ca-demo

修改SSL配置openssl.cnf(也可能是openssl.conf,不知道在哪可以用find -name / openssl.cnf查詢)

將dir屬性改成你上一步自建的目錄,不要用相對路徑,會踩坑,儲存,如圖:

我喜歡自動化,所以寫了三個如下指令碼,可以直接使用:

ca.sh

#!/bin/bash

#Create directory hierarchy.建立目錄結構
touch index.txt serial
chmod 666 index.txt serial
echo 01 >  serial
mkdir -p newcerts private

#生成RSA金鑰對
openssl genrsa -des3 -out ./private/cakey.pem 2048
#openssl req -new -days 365 -key ./private/cakey.pem -out ca.csr
#openssl ca -selfsign -in ca.csr -out ca.crt
# one step.一步生成csr,crt,直接10年使用期
openssl req -new -x509 -days 3650 -key ./private/cakey.pem -out ca.crt

server.sh

#!/bin/bash
# 簽發伺服器證書
mkdir server
openssl genrsa -out ./server/server.key
openssl req -new -key ./server/server.key -out ./server/server.csr
openssl ca -in ./server/server.csr -cert ./ca.crt -keyfile ./private/cakey.pem -out ./server/server.crt -days 3650

client.sh:

#!/bin/bash
# 簽發client證書
mkdir client
openssl genrsa -des3 -out ./client/client.key 2048
openssl req -new -key ./client/client.key -out ./client/client.csr
openssl ca -in ./client/client.csr -cert ./ca.crt -keyfile ./private/cakey.pem -out ./client/client.crt -config "/etc/ssl/openssl.cnf"
openssl pkcs12 -export -clcerts -in ./client/client.crt -inkey ./client/client.key -out ./client/client.p12

以上三個指令碼都可以在 https://github.com/dreamingodd/CA-generation-demo  找到

將以上三個指令碼複製到自建demo目錄中,如下所示:

加入執行許可權:

chmod +x *.sh

結果如下:

2.自建CA證書

執行指令碼ca.sh,效果如下:

a.輸入密碼短語:(隨便,記住就行,我填的是"demo",需要填3次)

b.生成證書需要填入一些資訊:Country Name(國家),State or Province Name(省),Locality Name(市),Organizational Name(組織名,隨便填,我填的是Choosefine Ltd),Common Name(一般填域名),其他可以不填。

 這樣證書就生成並自簽名了:

其中,newcerts目錄用於存放CA簽署(頒發)過的數字證書(證書備份目錄)。private目錄用於存放CA的私鑰。 檔案serial和index.txt分別用於存放下一個證書的序列號和證書資訊資料庫。 檔案serial填寫第一個證書序列號(如10000001),之後每前一張證書,序列號自動加1。

可以把ca.crt下載到你的windows系統的PC機上,後面會用到。 

3.簽發服務端證書

執行指令碼server.sh,效果如下:

最後一句是Data Base Updated,就表示成功了,要填的東西跟上一步非常相似,需要注意的是:

a.國家和省份必須和上一步一樣。

b.Organizational Name必須和上一步一樣。

c.Common Name,如果你的測試伺服器有域名的話,填入域名,沒有的話隨便填一個網址,windows訪問測試時配置一下hosts就好,我這裡填的是ssl.demo.com。

d.challenge password隨便填,記住就行,我填的demo。

e.pass phrase密碼短語是CA證書的的,我生成的時候用的也是demo。

生成結果:

4.Nginx配置Https單向認證

 這一步我要使用上面我們生成的證書s來配置一個安全的Https單向訪問資源連結。

首先修改nginx配置檔案,

vi /etc/nginx/nginx.conf

在http中加入以下內容:

server {

    server_name ssl.demo.com;

    listen 443;

    ssl on;

    ssl_certificate ca-demo/server/server.crt;

    ssl_certificate_key ca-demo/server/server.key;

    location / {

        root html;

        index index.html index.html;

    }

}

執行以下命令檢查和重啟nginx:

/usr/sbin/nginx -t
service nginx restart

使用IP訪問一下:

成功了,會顯示證書不安全。一般來說,如果花錢使用證書公司簽發的server.crt和server.key不會有這個問題。

這裡想解決這個問題的話需要windows本地信任我們自己的CA證書。如果對這個問題不感興趣可以直接跳過。

首先,將我們第二步生成的CA證書下載到windows系統本地,雙擊開啟

點選安裝:

點選下一步:

選擇自定義證書集合,點選瀏覽:

選擇第二個,受信任的證書列表,一直下一步/完成/是的等,就可以了。

 成功後效果如圖:

一開始那個X已經沒有了。

Status顯示OK。

如果你想看到證書集合的情況,可以WIN+R -> certmgr.msc檢視

名字是CA證書的Common Name。

最後(如果沒有域名),修改以下hosts檔案模擬一下域名:

使用域名訪問,風險提示就消失了:

5.簽發客戶端證書

簽發客戶端證書,用於服務端開啟了ssl的客戶端驗證時,要求客戶端對請求做加密。 

執行指令碼client.sh

所有密碼處我填的全是demo。

結果如下:

到此為止,證書的生成已經全部講完了。

6.Nginx配置Https雙向認證

Https雙向認證不僅驗證服務端的證書,服務端也要驗證客戶端的證書;不僅對客戶端的請求進行了加密,並且服務端使用的加密方案也是使用客戶端公鑰加密後傳送給客戶端的。比單項認證更加安全。

我個人的理解是,單項認證防止請求被篡改,雙向認證防止請求被模擬。

題外話,Https使用了對稱加密+非對稱加密,由於非對稱加密的效率低,不適合傳輸的資料量大的時候。所以Https的客戶端將對稱加密的金鑰用服務端的公鑰進行加密再發送給服務端,服務端用私鑰進行解密(非對稱加密),對傳輸資料本身的加密使用的金鑰是一樣的(對稱加密)。

進入正題,首先開啟服務端nginx的客戶端ssl認證,將之前加入的配置刪除,貼入新的一份:

server {
                server_name ssl.demo.com;
                listen 443;
                ssl on;
                ssl_certificate                 ca-demo/server/server.crt;
                ssl_certificate_key             ca-demo/server/server.key;

                ssl_client_certificate          ca-demo/ca.crt;
                ssl_verify_client               on;

                ssl_session_cache               shared:SSL:1m;
                ssl_session_timeout             5m;
                ssl_ciphers                     HIGH:!aNULL:!MD5;
                ssl_prefer_server_ciphers       on;

                location / {
                        root html;
                        index index.html index.htm;
               }
        }

檢查並重啟,再次訪問:

顯示未傳送客戶端證書。

下載client.p12檔案到本地,雙擊安裝,這次安裝到個人:

關閉瀏覽器再次訪問,就有了證書選擇的介面,選擇後正常訪問。

 之前有不少網銀都是使用這種方式進行交易的。

在上述的操作之後,發現在ie8中訪問是ok的,但是在chrome中訪問還是不安全的提示。所以繼續參考下面連結:

https://blog.csdn.net/dotalee/article/details/78041691

OpenSSL建立帶SAN擴充套件的證書並進行CA自籤

什麼是 SAN

SAN(Subject Alternative Name) 是 SSL 標準 x509 中定義的一個擴充套件。使用了 SAN 欄位的 SSL 證書,可以擴充套件此證書支援的域名,使得一個證書可以支援多個不同域名的解析。

來看看百度的證書,百度證書的擴充套件域名有這麼多,其中還有了*.hao123.com,那我們再看看www.hao123.com的證書

發現的確是用的前面的百度證書

所以SAN帶來的好處就可以看出來了,一個證書可以用在各種不同的域名下,不需要一個域名買一個證書了。

利用OpenSSL建立證書

因為是本地環境,直接用OpenSSL給自己頒發一個CA根證書用於後面給伺服器做CA簽署。 
1. 生成CA金鑰

openssl genrsa -des3 -out ca.key 2048

2.生成CA根證書

openssl req -sha256 -new -x509 -days 365 -key ca.key -out ca.crt \
    -subj "/C=CN/ST=GD/L=SZ/O=lee/OU=study/CN=testRoot"

3.生成伺服器金鑰

openssl genrsa -des3 -out server.key 2048

4.生成伺服器證書請求檔案

openssl req -new \
    -sha256 \
    -key server.key \
    -subj "/C=CN/ST=GD/L=SZ/O=lee/OU=study/CN=bdstatic.com" \
    -reqexts SAN \
    -config <(cat /etc/pki/tls/openssl.cnf \
        <(printf "[SAN]\nsubjectAltName=DNS:*.bdstatic.com,DNS:*.baidu.com")) \
    -out server.csr

5.CA簽署伺服器證書

openssl ca -in server.csr \
        -md sha256 \
        -keyfile ca.key \
    -cert ca.crt \
    -extensions SAN \
    -config <(cat /etc/pki/tls/openssl.cnf \
        <(printf "[SAN]\nsubjectAltName=DNS:*.bdstatic.com,DNS:*.baidu.com")) \
    -out server.crt

之後把生成好的伺服器證書和伺服器金鑰在伺服器(ngnix,tomcat)裡配置好,並且把ca.crt證書匯入到瀏覽器的受信任的根證書頒發機構裡,在瀏覽器訪問就不會有紅叉叉了。

注意事項

  1. -subj “/C=CN/ST=GD/L=SZ/O=lee/OU=study/CN=testRoot”這行可以不要,會有命令互動填寫相關資訊。
  2. 雜湊演算法不要使用sha1,因為Chrome瀏覽器下會提示不安全,上面都是用的sha256。 
  3.  /etc/pki/tls/openssl.cnf檔案是預設的OpenSSL配置檔案,可能環境不同路徑也不同。 
  4. 伺服器證書請求檔案的國家,省,市要和CA證書一致,這個在openssl.cnf預設配置中指定了,可以修改。

1. 關於私鑰的加密格式,因為筆者是在netty裡使用的ssl協議,而netty僅支援PKCS8格式的私鑰(見http://netty.io/wiki/sslcontextbuilder-and-private-key.html),需要對金鑰格式進行轉換

//私鑰轉成PKCS8格式
openssl pkcs8 -topk8 -nocrypt -in server.key -out server_pri.pem

程式碼如下

SslContext serverSslCtx = SslContextBuilder.forServer(new File("E:/server.crt"),new File("E:/server_pri.pem")).build();

附錄

PKCS1與PKCS8格式互轉

//預設生成PKCS1格式PEM編碼私鑰
openssl genrsa -out ca.key 2048
//轉換成PKCS8
openssl pkcs8 -topk8 -nocrypt -in ca.key -out ca_private.pem
//PKCS8轉換成PKCS1
openssl rsa -in ca_private.pem -out ca.key

PEM與DER互轉

//PEM轉DER
openssl rsa -in ca.key -outform DER -out ca_private.der
openssl pkcs8 -topk8 -nocrypt -inform PEM -outform DER -in ca.key -out ca_private.der
//DER轉PEM
openssl rsa -in ca_private.der -inform DER -outform PEM -out ca.key

PKCS7轉PKCS12(tomcat證書)

//需加密碼保護
openssl pkcs12 -export -clcerts -in server.crt -inkey server.key -name tomcat -out server.p12

//springboot SSL配置
server.port= 8443   //埠
server.ssl.key-store=classpath:server.p12   //證書路徑
server.ssl.key-store-password= 123456   //p12證書密碼

參考

OpenSSL SAN 證書 
使用OpenSSL生成多域名自簽名證書進行HTTPS開發除錯 
使用 openssl 生成證書


隨後,將兩個連結中的配置命令合併起來,也就是增加了SAN的選項,通過ssl.demo.com訪問就不會告警了。