HTTPS 是在 HTTP 基礎之上新增 SSL/TLS 使網路通訊加密,進而確保通訊安全。可簡記為 HTTPS = HTTP + SSL/TLS
本文件主要講解常規SSL格式、Nginx 與 Tomcat 的 SSL 配置方法 及 通過 OpenSSL 轉換證照格式的內容。
1. SSL 證照主流格式說明
SSL 及 TLS(新版SSL)統稱 SSL 證照(又稱 CA 證照、數字證照),用於資料傳輸過程的加密。
本質上 SSL 證照是一個 X.509 證照,是定義證照資料結構的標準。在 X.509 標準下,包含 Base64 ASCII 文字與二進位制兩種檔案儲存方式,根據使用的格式和編碼,證照檔案具有不同的副檔名。
下圖展示了 X.509 主流證照的編碼格式和副檔名。
對於 Nginx 和 Tomcat 最常使用的是 PEM (Nginx) 與 PKCS#12(Tomcat),除此之外 Tomcat還支援基於JDK keytool 加密的 JKS 格式。
PEM 格式
大多數 CA (證照頒發機構) 提供 PEM 格式的證照,儲存在 Base64 ASCII 編碼的檔案中。證照檔案型別可以是 .pem
、.crt
、.cer
或 .key
。因為是文字型別,所以對檔案字尾名不敏感。PEM 檔案可以在單個檔案中包含伺服器證照、中間證照和私鑰。伺服器證照和中間證照也可以放在單獨的 .crt
或 .cer
檔案中,私鑰可以放在 .key
檔案中。
PEM 檔案使用 ASCII 編碼,可以使用文字編輯器開啟,文字內容中公鑰、私鑰都有兩種形式。X.509 規定,取 ----
開頭的下一行首開始,到下一個 ----
開頭的上一行尾結束。
----BEGIN CERTIFICATE----
公鑰加密串
----END CERTIFICATE----
-----BEGIN PUBLIC KEY-----
公鑰加密串
-----END PUBLIC KEY-----
---- BEGIN RSA PRIVATE KEY-----
私鑰加密串
-----END RSA PRIVATE KEY-----
-----BEGIN PRIVATE KEY-----
私鑰加密串
-----END PRIVATE KEY-----
-----BEGIN CERTIFICATE REQUEST-----
CSR加密串
-----END CERTIFICATE REQUEST-----
PKCS#7 格式
PKCS#7 格式是一種“加密訊息語法標準”。PKCS#7證照使用 Base64 ASCII 編碼,副檔名為 .p7b
或 .p7c
,這種格式只能儲存證照,不能儲存私鑰。一般主要用來做數字信封。格式如下:
-----BEGIN PKCS7-----
公鑰加密串
-----END PKCS7-----
DER 格式
DER 證照採用二進位制格式,只含有證照資訊,不包含私鑰。副檔名為 .der
或 .cer
。這些證照主要用於Java Web伺服器。
PKCS12 格式
PKCS#12證照採用二進位制格式,副檔名為 .pfx
或 .p12
,支援將 伺服器證照
、中間證照
和 私鑰
儲存在一個具有密碼保護的檔案中,主要用於Windows平臺。
2. Nginx SSL證照配置
Nginx 支援所有 PEM 格式的證照,包含 .pem
、.crt
、.cer
、.key
,其中 .key
常用於私鑰字尾名。
server {
listen 443 ssl;
server_name www.example.com;
ssl_certificate /path/to/path/public.pem;
ssl_certificate_key /path/to/path/private.key;
ssl_session_timeout 5m;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
location / {
root html;
index index.html index.htm;
}
}
引數說明:
- server_name :域名(不含https://)
- ssl_certificate :【必填】 公鑰檔案位置
- ssl_certificate_key :【必填】 私鑰檔案位置
- ssl_session_timeout :客戶端可複用會話的時間
- ssl_ciphers:指定啟用的加密器型別,必須是OpenSSL庫支援的型別,預設 ssl_ciphers HIGH:!aNULL:!MD5;
- ssl_protocols:表示使用的TLS協議的型別,預設是TLSv1 TLSv1.1 TLSv1.2,可選引數為SSLv2、SSLv3、TLSv1、TLSv1.1、TLSv1.2、TLSv1.3
- ssl_prefer_server_ciphers:指定服務端加密器優先,引數為on開啟,預設off關閉;
官方文件參考:
- https://nginx.org/en/docs/http/configuring_https_servers.html
- https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_certificate
3. Tomcat SSL證照配置
Tomcat 支援 JKS、PKCS11 和 PKCS12 格式的金鑰庫,JKS 格式是 Java 的標準格式,由 JDK 的 keytool 生成;PKCS11/12 是網路標準,由 OpenSSL 生成。
對於證照格式轉換,JKS 一般是由 PKCS12 轉換而來,Tomcat 又支援 PKCS12 所以只要將 PEM 格式轉換成 PKCS12 (.pfx 或 .p12) 即可。參考 [#PEM 格式 轉 PKCS#12](#PEM 格式 轉 PKCS#12)
server.xml 配置
<Connector
protocol="org.apache.coyote.http11.Http11NioProtocol"
port="8443" maxThreads="200"
scheme="https" secure="true" SSLEnabled="true"
keystoreFile="<keystoreFile>" keystorePass="<passvalue>"
clientAuth="false" sslProtocol="TLS"/>
引數說明:
- port :HTTPS 協議埠,可以設定為 443
- protocol :連線協議,由
HTTP/1.1
改為org.apache.coyote.http11.Http11NioProtocol
- keystoreFile :證照檔案絕對路徑,可以是 JKS 或 PKCS12
- keystorePass :證照的密碼
- 未說明的引數除
maxThreads
根據實際情況調整,其餘均按照上面的配置即可。
官方文件參考:https://tomcat.apache.org/tomcat-8.5-doc/ssl-howto.html#Configuration
4. 主流證照轉換方法
一般來說,阿里雲、騰訊雲直接提供不同伺服器型別的證照,以下證照轉換僅當無備選型別時使用。
PEM 格式 轉 PKCS#12
PEM 格式的公私鑰字尾名不影響轉換,可以是 .crt
/.pem
/ .key
/.cer
。
openssl pkcs12 -export -in public.pem -inkey private.key -out keystore.p12 -passout pass:<passvalue>
引數說明:
- -in : 指定PEM 公鑰檔案
- -inkey:指定 PEM 私鑰檔案
- -out:指定輸出 PKCS#12 格式的證照,常以
.p12
或.pfx
副檔名。 - -passout:指定 PKCS#12 證照的密碼
PKCS#12 轉 PEM
當提供PKCS#12證照,則需要轉換為PEM證照,命令如下:
#匯出私鑰
openssl pkcs12 -in keystore.p12 -out private.key -nocerts -nodes -password pass:<passvalue>
#匯出公鑰
openssl pkcs12 -in keystore.p12 -out public.pem -clcerts -nokeys -password pass:<passvalue>
引數說明:
- -in :輸入檔案,本命令中是 PKCS#12 證照
- -out:輸出檔案,根據上邊兩種搭配,分別輸出私鑰與公鑰
- -nocerts:無公鑰
- -nodes:不加密私鑰。目前在 OpenSSL 3.0 中廢棄,使用
-noenc
代替,Git Bash 自帶的版本目前還沒升到 3.0 - -clcerts:只輸出客戶端證照
- -nokeys:無私鑰
- -password:PKCS#12證照的密碼,需要接
pass:<實際密碼>
官方文件參考:https://www.openssl.org/docs/manmaster/man1/openssl-pkcs12.html
5. [擴充套件] 自簽發SSL證照與CA數字證照
自簽發 SSL 證照
通過 openssl
生成自簽發證照,自簽發證照不包含CSR中間證照,直接生成公鑰。自簽發的證照在網路上是不可信的,但是 內網測試與使用,也是可以的。
命令如下:
#生成RSA私鑰
openssl genrsa -out private.key 2048
#自簽發公鑰
openssl req -new -x509 -key private.key -out public.pem -days 1095 #3年有效期
CA 數字證照
CA 數字證照是由建立者提供 CSR(Centificate Signing Request)給CA機構簽發下來的公鑰。
一般來講,SSL運營商(如阿里雲等)已經提供了直接下載指定伺服器型別的公私鑰功能,以下僅是過程簡單描述。
CA 機構的處理方式一般不需要建立者關心,命令:
#生成RSA私鑰
openssl genrsa -out private.key 2048
#使用私鑰生成CSR
openssl req -new -key privkey.key -out cert.csr
將此CSR交給 CA機構 ,由CA簽名後獲得公鑰,使用公鑰和私鑰就可以部署 HTTPS 服務了。
寫文過程難免有錯漏,如有指正感激不盡!