為NGINX for Windows設定HTTPS的SSL/TLS憑證

為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_certificatessl_certificate_key 它怎麼知道要去那裡找到你的憑證與金鑰檔案?

以我上面的組態來說,在沒有特別指定的情況下,它會到 conf 目錄下尋找,也就是跟 nginx.conf 同一目錄。

# 它會到 conf 目錄下尋找
ssl_certificate      server.crt;
ssl_certificate_key  server.key;

因此,記得在啟動之前,把剛剛轉好 server.crtserver.key 檔案複製到 conf 目錄下後,利用上面的 HTTPS server 組態啟動 nginx 來測試。

啟動前,建議先把 error_log logs/error.log; 打開以方便偵錯。

為了未來移回 NGINX (Linux),我沒特別去試 c:\server.crt 之類的 Windows 路徑怎麼設,讓 nginx.conf 保持能直接帶走的狀態是最好的。

沒有留言:

張貼留言

感謝您的留言,如果我的文章你喜歡或對你有幫助,按個「讚」或「分享」它,我會很高興的。