很久以前介紹過使用 OpenSSL 建立 CA 並簽發 SSL 憑證, 相較於自我簽署憑證,客戶端可安裝自訂 CA 憑證避免程式因不信任自製憑證無法連線

但隨著時代演進,需求有點變化:

  1. HTTPS 已成資安基本要求,即使企業內部通訊也常被要求走 HTTPS,製作憑證的需求大增
  2. 2017 年 Chrome 58 / Firefox 48 開始要求憑證必須改用 SubjectAltName 欄位提供主機名稱 ,否則將顯示為不安全

第一點增加了需要製作憑證的頻率,每新增一台伺服器就需簽發一張憑證有點費事, 萬用字元憑證能讓我們省點力氣。 傳統憑證簽發對象只能指定特定網域名稱,例如:www.darkthread.net、api.darkthread.net。 而萬用字元憑證將適用對象擴大為特定網域下的任何網域名稱,例如:只要製作一張 *.darkthread.net 憑證, 即可安裝在 www.darkthread.net、blog.darkthread.net、api.darkthread.net、store.darkthread.net 等多個網站, 都視為有效。

第二點屬於憑證標準改變,導致過去做法製作的憑證,現在會被瀏覽器或客戶端視為不安全。

有鑑於此,2019 年版「使用 OpenSSL 製作萬用字元 SSL 憑證」食譜來了。

以下示範如何在 Windows 主機使用 OpenSSL 建立 CA 憑證並簽發萬用字元憑證。

  1. 第一步是要取得 OpenSSL。在 Windows 上過去需自行下載安裝,若為 Windows 10, 可考慮使用 Windows 上 Ubuntu 的 Bash, 但我最建議的做法是使用 Windows 工程師必備神器 Cmder 最省事, 下面也會以 Cmder 此示範。(還沒用過 Cmder 的同學可以試試,相信你也會愛上它的)
  2. 準備一個目錄放置產生的憑證,在此以 D:\SSL 示範
  3. 執行openssl genrsa -des3 -out rootCA.key 4096產生 rootCA.key,過程需設定密碼,稍後會用到
  4. 執行openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 36500 -out rootCA.crt 產生 CA 憑證 rootCA.crt
    題外話:days 參數為有效期限,之前遇過系統上線時隨手設了某個有效期限十年心想綽綽有餘,某天系統壞了,調查半天才驚覺程式已 默默跑了十年沒改版,這才悔恨自己看得不夠遠...
    所以,憑證有效期限怒抓 100 年(36500)好了 XD 這是玩笑話,依硬體能力增強的速度,資安防護相關機制估計撐不了多久就必須升級。
    建立憑證時要用到步驟 3. 設定密碼,接著要回答一串問題,若為內部使用,輸入內容不重要,程序完成後會得到 rootCA.crt。
  5. 這樣 CA 根憑證就做好了,應用時記得要安裝到客戶端。參考:憑證儲存區的選擇
  6. 接著要決定萬用字元憑證的域名,在這裡以 *.darkthread.net 為例
  7. 先產生萬用字元的憑證金鑰 openssl genrsa -out darkthread-net.key 2048
  8. 準備憑證要求的設定檔 darkthread-net.cnf 如下:
    [req]
    default_bits = 2048
    prompt = no
    default_md = sha256
    distinguished_name = dn
    
    [dn]
    C=TW
    ST=Taiwan
    L=Taipei
    O=Darkthread
    OU=Darkthread CA
    emailAddress=nobody@darkthread.net
    CN=*.darkthread.net
    
  9. 執行openssl req -new -sha256 -nodes -key darkthread-net.key -out darkthread-net.csr -config darkthread-net.cnf建立憑證請求darkthread-net.csr
  10. 準備 V3 設定檔 darkthread-net-v3.ext
    authorityKeyIdentifier=keyid,issuer
    basicConstraints=CA:FALSE
    keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
    subjectAltName = @alt_names
    
    [alt_names]
    DNS.1 = *.darkthread.net
    
  11. 執行openssl x509 -req -in darkthread-net.csr -CA rootCA.crt -CAkey rootCA.key -CAcreateserial -out darkthread-net.crt -days 36500 -sha256 -extfile darkthread-net-v3.ext,建立憑證 darkhread-net.crt,過程需要使用步驟 3 設定的密碼
  12. 要使用於 IIS,需將 .crt 轉為包含私鑰的 .pfx 格式,指令為openssl pkcs12 -export -out darkthread-net.pfx -inkey darkthread-net.key -in darkthread-net.crt -certfile rootCA.crt,執行後得到 darkthread-net.pfx,過程需要設定一組密碼,稍後在 IIS 安裝憑證時會用到。
  13. 開啟 IIS 管理介面,找到「伺服器憑證」,使用匯入功能匯入 darkthread-net.pfx

  14. 設定 HTTPS 繫結時就可以選取新做好的憑證
  15. 使用 Chrome 實測,完全符合安全要求,大功告成!

最後提醒一點,若想共用該 CA 憑證簽發其他伺服器憑證,記得妥善保存相關檔案及密碼。

Tutorial of wildcard certificate creation with OpenSSL on Windows and how to install it to IIS.


Comments

# by 無所不在

我執行到第4步驟 openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 36500 -out rootCA.crt 時出現錯誤: Can't open C:\Program Files (x86)\Common Files\SSL/openssl.cnf for reading, No such file or directory 2876:error:02001003:system library:fopen:No such process:crypto\bio\bss_file.c:69:fopen('C:\Program Files (x86)\Common Files\SSL/openssl.cnf','r') 2876:error:2006D080:BIO routines:BIO_new_file:no such file:crypto\bio\bss_file.c:76:

# by Jeffrey

to 無所不在,你的 OpenSSL 是另外安裝的嗎?會不會你安裝的 OpenSSL 版本需要額外設定步驟?我建議改用 Cmder 試試,環境設定問題較少。

# by 無所不在

我的 OpenSSL 是去你提供的官網下載的 還是出錯, 看起來應該是[Common Files\SSL/openssl.cnf]中間的那個"/"在作怪,但我不知道要如何改? $ openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 36500 -out rootCA.crt Can't open C:\Program Files (x86)\Common Files\SSL/openssl.cnf for reading, No such file or directory 1948:error:02001003:system library:fopen:No such process:crypto\bio\bss_file.c:69:fopen('C:\Program Files (x86)\Common Files\SSL/openssl.cnf','r') 1948:error:2006D080:BIO routines:BIO_new_file:no such file:crypto\bio\bss_file.c:76: Enter pass phrase for rootCA.key: unable to find 'distinguished_name' in config problems making Certificate Request 1948:error:0E06D06A:configuration file routines:NCONF_get_string:no conf or environment variable:crypto\conf\conf_lib.c:270:

# by Jeffrey

to 無所不在,https://stackoverflow.com/a/15416214/288936 試試加上 -config 參數。不過,我還是推薦用 Cmder 較省事。

# by 無所不在

我昨天就已經安裝 cmder,然後使用他來執行。 另外openssl 我下載的是 Win32OpenSSL-1_1_1d.msi。 可以了,謝謝。 等等有空再繼續往下研究。 參數改成如下: openssl req -config "c:\Program Files\OpenSSL-Win32\bin\openssl.cfg" -x509 -new -nodes -key rootCA.key -sha256 -days 36500 -out rootCA.crt

# by perasa

請問 我執行到 8.準備憑證要求的設定檔 darkthread-net.cnf 如下: 請問cnf該如何產生呢? 是否是新增一個文字文件格式來修改成cnf檔呢? 謝謝

# by Jeffrey

to perasa, 用文字編輯器Notepad/Notepad++新開文字檔,參考第8點下方的文字範例修改貼入文字檔存成your-domain-name.cnf檔即可。

# by timhsiao

您好 我依照您的教學文件做到步驟11.出現下列錯誤,請問可能是那邊做錯造成的呢? Error Loading extension section default 12188:error:2206E068:X509 V3 routines:X509V3_get_value_bool:invalid boolean string:crypto\x509v3\v3_utl.c:263:section:<NULL>,name:CA,value:FALES 12188:error:22098080:X509 V3 routines:X509V3_EXT_nconf:error in extension:crypto\x509v3\v3_conf.c:47:name=basicConstraints, value=CA:FALES

# by Jeffrey

to timhsiao, basicConstraints=CA:FALSE <= 是不是誤打成 CA:FAL**ES**?

# by timhsiao

to Jeffrey, 感謝您的幫助真的是我手誤打錯,看半天沒看出來,謝謝您的幫忙。

# by Roy

您好, 按照您的步驟建立SSL憑證後匯入Windows Server 2012 R2 Standard (IIS Server) 在Server端使用Chrome正常,但使用Windows 10 專業版 Chrome連接網站時,顯示NET::ERR_CERT_AUTHORITY_INVALID 是憑證問題嗎?

# by Jeffrey

to Roy, 建議檢查一下是否漏了第五步 「這樣 CA 根憑證就做好了,應用時記得要安裝到客戶端。」

# by Roy

您好, 感謝您的幫助將rootCA.crt安裝到客戶端即可正常運作 所以客戶端每台電腦也必須安裝rootCA.crt?

# by Jeffrey

to Roy, 是的,客戶端必須先信任 CA 根憑證,使用該 CA 簽發憑證的網站安全連線才會被視為安全。

# by William

你好, 請教一下, 我的WebServer(lighttpd)會去驗證certificate chain, 這樣我好像無法單獨放用我用自己的CA所sign出來的certificate進去. 因為這樣certificate chain驗證會有問題. 另外請教一下, 你在產生darkthread-net certificate是要放到WebServer嗎? 如果是要放到WebServer上的話, 那DNS那邊是不是要輸入Client的IP?

# by William

你好, 請教一下, 我的WebServer(lighttpd)會去驗證certificate chain, 這樣我好像無法單獨放用我用自己的CA所sign出來的certificate進去. 因為這樣certificate chain驗證會有問題. 另外請教一下, 你在產生darkthread-net certificate是要放到WebServer嗎? 如果是要放到WebServer上的話, 那DNS那邊是不是要輸入Client的IP?

# by Jeffrey

to William, 習慣上 WebServer 跟 Client 都會安裝 RootCA 憑證,若 lighttpd 安裝憑證會檢查,那就得將 CA 根憑證裝在 WebServer 上,但 lighttpd 我沒用過,無法提供更多協助。 darkthread-net.pfx 要裝在 WebServer 上沒錯,憑證能不能發給 IP 由 CA 規定,openssl 看起來是可以接受。https://nodeployfriday.com/posts/self-signed-cert/

# by William

Hi, Jeffrey 非常感謝您這麼快的回覆. 那再請教一下, 目前我的Browser連接到我的WebServer會有NET::ERR_CERT_AUTHORITY_INVALID的提示. 如果要讓client跟Webserver Secured的通訊, 我RootCA憑證跟用RootCA sign出來的憑證的DNS要怎麼設定? 謝謝您

# by William

不好意思關於WebServer會有NET::ERR_CERT_AUTHORITY_INVALID的提示說錯. 我已經把RootCA放到Browser了但是會有ERR_CERT_COMMON_NAME_INVALID錯誤. 請問我是什麼沒設定好嗎?

# by Jeffrey

to William,Root CA 根憑證 Windows 安裝可參考這篇 https://blog.darkthread.net/blog/certificate-store-difference/ ,Linux 可參考這篇 https://blog.darkthread.net/blog/install-caroot-cert-in-linux/,用 Chrome 檢查憑證哪裡有問題可參考這篇 https://blog.darkthread.net/blog/check-ssl-cert-with-chrome/。

# by ado

您好, 我按照步驟做完全部的command, 但當要匯入pfx時所輸入的密碼是第12步驟時設定的密碼嗎? 因為匯pfx時, 輸入第12步驟的密碼, 一直出現 "指定的網路密碼錯誤" 的訊息

# by Jeffrey

to ado, 我查到一個類似案例,似乎與私鑰的加密演算法有關,有網友分享先匯入使用者憑證區再匯出來可成功裝進 IIS,或是在 openssl 產生 pfx 時加上 -macalg SHA1 -keypbe PBE-SHA1-3DES -certpbe PBE-SHA1-3DES 等參數。參考https://stackoverflow.com/a/70383251/288936 期待你的測試結果。

# by ado

to Jeffrey, 依照您提供的方法追加參數, 已可成功匯入pfx, 也持續往下設定站台的ssl, 也設定成功。 但實際以https瀏覽站台時, 仍發生 NET::ERR_CERT_AUTHORITY_INVALID 錯誤訊息, 參數過往的留言, 也參考 2019-12-24 04:47 PM by Roy, 將RootCA.crt 安裝到Client端電腦的 "受信任的根憑證授權單位" 我有可能哪個步驟沒做好嗎? 目前沒有頭緒 >"<

# by ado

to Jeffrey, 抱歉, 剛重新按Ctrl+F5, 訊息改為 ERR_SSL_OBSOLETE_VERSION

# by Jeffrey

to ado, 爬文 ERR_SSL_OBSOLETE_VERSION 可能是你的 IIS 還在使用新版瀏覽器已不支援 TLS 1.0/1.1 協定 ( https://kinsta.com/knowledgebase/err_ssl_obsolete_version/ ) 關於停用舊版 TLS 協定的相關文章 https://blog.darkthread.net/blog/disable-tls-1-0-issues/

# by ado

to jeffrey, 問題已解 我是參考這篇 http://tech.smallya.net/2020/07/26/2008r2%E5%92%8Ciis75%E5%95%9F%E7%94%A8tls12%E4%BD%A0%E7%9A%84%E9%80%A3%E7%B7%9A%E5%8F%AF%E8%83%BD%E6%9C%89%E5%AE%89%E5%85%A8%E6%BC%8F%E6%B4%9E/ 謝謝回覆

Post a comment