為NGINX for Windows設定HTTPS的SSL/TLS憑證
故事是這樣,我們需要為NGINX(for Windows)服務加上 HTTPS 的 SSL/TLS 憑證。公司提供的是 .pfx
檔(PFX容器形式的憑證,PKCS#12格式),通常在 Windows Server/IIS Server 上使用沒什麼難度,一、匯入 .pfx
到 Windows Server;二、到 IIS Server 設定匯入 SSL/TLS 憑證。後來研究發現,NGINX 無法直接使用 .pfx
檔來設定,也是說需要轉換格式後才能提供 Linux Based 的應用程式來使用。
OpenSSL for Windows
先說結果:不要用 OpenSSL for Windows。(晚一點點就解釋)
Win32OpenSSL 下載:https://slproweb.com/products/Win32OpenSSL.html
注意,安裝後無法直接使用,還需要設定環境變數,安裝程式不會順便設定。
在 Path
變數加上 C:\Program Files\OpenSSL-Win64\bin
。
不要用 OpenSSL for Windows 的原因,是因為我在轉換格式時會用到一個 -legacy
參數,會現出以會錯誤訊息。
pkcs12: unable to load provider legacy
Hint: use -provider-path option or OPENSSL_MODULES environment variable.
E05B0000:error:12800067:DSO support routines:win32_load:could not load the shared library:crypto\dso\dso_win32.c:108:filename(C:\Program Files\OpenSSL\lib\ossl-modules\legacy.dll)
E05B0000:error:12800067:DSO support routines:DSO_load:could not load the shared library:crypto\dso\dso_lib.c:147:
E05B0000:error:07880025:common libcrypto routines:provider_init:reason(37):crypto\provider_core.c:1019:name=legacy`
我已經安裝 Win64 OpenSSL v3.5.0 280MB Installer,應該已經是最完整的版本了。這部份我不想再找自己麻煩了,請改用 WSL。
使用 OpenSSL 轉換 .pfx 到 .crt
開啟 WSL 視窗,我的 OS 是 Ubuntu 預設含有 OpenSSL,我們可以透過以下兩個指令來取得 .crt
憑證檔案與 .key
金鑰檔案。
$ openssl pkcs12 -in kkbruce.pfx -clcerts -nokeys -out server.crt
Enter Import Password:
$ openssl pkcs12 -in kkbruce.pfx -nocerts -nodes -out server.key
Enter Import Password:
副檔名不重要,重要的是它轉換後的內容。我也有看到用
cert.pem
/key.pem
僅用.pem
副檔名來區分憑證與金鑰。單純就 Windows 與 Linux 的習慣不同。
在指令可以看到它會跟我要 .pfx
檔的密碼,這部分非常合理,在 Windows 上匯入 .pfx
檔時也是需要密碼,但用手 key-in 不太合理。找了一下官方文件,有看到 -password
參數。
$ openssl pkcs12 -in kkbruce.pfx -clcerts -nokeys -password 123:abc -out server.crt
Invalid password argument, missing ':' within the first 5 chars
Error getting passwords
我被這段 OpenSSL 錯誤卡了好久。中間要帶密碼進去,結果一直說我密碼有問題。官方文件也只有 -password
也沒多說什麼。一開始因為不知道問題點,因此關鍵字或 AI 工具都有點不怎麼查或問,一直在鑽它提供給我的錯誤訊息,因為密碼裡有個剛好有個「:」字元(範例密碼不是亂給的),想說,不會吧,只是個密碼也能碰到官方連文件都沒有的雷區!!!
讓我在這裡繞了好久。最後終於查到,OpenSSL 只要是密碼的都必須用「pass:password」格式來帶入你的密碼,也就是密碼最前面都必須帶「pass:」5個字,也就是「Invalid password argument, missing ':' within the first 5 chars」想表達的事!舉例來說,密碼應該是:
-password pass:123:abc
靠x啦!只能在心裡大聲說聲,暗!(我的青春小鳥呀)
官方文件其實有說,只是放在一個獨立的小節:openssl-passphrase-options。
$ openssl pkcs12 -in kkbruce.pfx -clcerts -nokeys -password 'pass:123:abc' -out server.crt
Error outputting keys and certificates
40E75A41AA7F0000:error:0308010C:digital envelope routines:inner_evp_generic_fetch:unsupported:../crypto/evp/evp_fetch.c:349:Global default library context, Algorithm (RC2-40-CBC : 0), Properties ()
由錯誤訊息很快速定位到問題,新版的 OpenSSL 不支援舊式演算法,如訊息中的 RC2-40-CBC,解決辦法也很簡單,加上一個 -legacy
參數,用相容舊版演算法模式來運作。
$ openssl pkcs12 -in kkbruce.pfx -clcerts -nokeys -legacy -password 'pass:123:abc' -out server.crt
$ openssl pkcs12 -in kkbruce.pfx -nocerts -nodes -legacy -password 'pass:123:abc' -out server.key
本來怕 Linux 的 OpenSSL 轉出來的東西在 Windows 上不能用,因此才在 Windows 上去安裝 OpenSSL for Windows,結果到了
-legacy
這一步就出錯無法再往下進行了。後來證明,是我想太多,多花了那個不必要的時間,Linux 專長的事讓 WSL 代勞就對了。
到這步,終於順利產出我們需要檔案格式了。
設定 NGINX 的 SSL/TLS 憑證
開啟 nginx.conf 組態檔,預預裡面應該有段注解的 HTTPS server
組態,移除預設注解。
server {
listen 443 ssl;
server_name www.kkbruce.net;
ssl_certificate server.crt;
ssl_certificate_key server.key;
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;
}
}
在 NGINX for Windows 設定 HTTPS 的 SSL/TLS 憑證,有個小地方要注意。ssl_certificate
與 ssl_certificate_key
它怎麼知道要去那裡找到你的憑證與金鑰檔案?
以我上面的組態來說,在沒有特別指定的情況下,它會到 conf
目錄下尋找,也就是跟 nginx.conf 同一目錄。
# 它會到 conf 目錄下尋找
ssl_certificate server.crt;
ssl_certificate_key server.key;
因此,記得在啟動之前,把剛剛轉好 server.crt
與 server.key
檔案複製到 conf
目錄下後,利用上面的 HTTPS server 組態啟動 nginx 來測試。
啟動前,建議先把
error_log logs/error.log;
打開以方便偵錯。
為了未來移回 NGINX (Linux),我沒特別去試 c:\server.crt
之類的 Windows 路徑怎麼設,讓 nginx.conf 保持能直接帶走的狀態是最好的。
沒有留言:
張貼留言
感謝您的留言,如果我的文章你喜歡或對你有幫助,按個「讚」或「分享」它,我會很高興的。