localhost HTTPS 環境建置

tags: HTTP HTTPS Node.js Express
category: Front-End
description: 如何在 localhost 上建置 HTTPS 環境
created_at: 2024/11/12 22:00:00

cover image


前言

在開發網站時,有時候會需要在 local 建立一個 HTTPS 環境來測試一些功能,這篇文章將會介紹如何在 localhost 上建立一個 HTTPS 環境。

雖然說已經有一些功能可以在不安全的 localhost 上測試,但還是有些時候不得不使用 HTTPS,這篇應該可以幫助你快速建立一個 HTTPS 環境。

另外這篇會以 Windows 環境為主,如果是 MacLinux 環境可能要在自己找對應的匯入方式(不確定是否相同),但產生 SSL 憑證的方式應該是一樣的。

然後最後會以簡單的 Node.js Express 伺服器來做實驗。


前置作業

請準備好 WSL 環境,或者是相關的 Bash 環境,這邊會使用到 OpenSSL 來產生 SSL 憑證。


產生 SSL 憑證

嗯.. 其實我已經寫了一個簡單的腳本,可以直接替換變數來使用。 (當然你也可以改一些參數細節,例如我把 Organization 給留空了)

KEY_FILE=ca.key
PEM_FILE=ca.pem
PFX_FILE=ca.pfx
PFX_PASSWORD=123456
DAYS=365
DOMAIN=local-dev.app
openssl genpkey -algorithm RSA -out $KEY_FILE
openssl req -x509 -new -nodes -key $KEY_FILE -sha256 -days $DAYS -out $PEM_FILE -subj "/C=TW/ST=Taiwan/L=Taipei/O=/CN=$DOMAIN"
openssl genrsa -out $DOMAIN.key 2048
openssl req -new -key $DOMAIN.key -out $DOMAIN.csr -subj "/C=TW/ST=Taiwan/L=Taipei/O=/CN=$DOMAIN"
openssl x509 -req -in $DOMAIN.csr -CA $PEM_FILE -CAkey $KEY_FILE -CAcreateserial -out $DOMAIN.crt -days $DAYS -sha256 -extfile <(echo "subjectAltName=DNS:$DOMAIN")
openssl pkcs12 -export -out $PFX_FILE -inkey $KEY_FILE -in $PEM_FILE -passout pass:$PFX_PASSWORD

這邊會產生以下檔案:

  • ca.key:CA 金鑰
  • ca.pem:CA 憑證
  • ca.pfx:CA 匯出檔案
  • local-dev.app.key:網域金鑰
  • local-dev.app.csr:網域請求憑證
  • local-dev.app.crt:網域憑證

建立 HTTPS 伺服器

接下來我們要建立一個 Node.js Express 伺服器,並且使用 HTTPS 來啟動。

const fs = require('fs');
const https = require('https');
const express = require('express');
const app = express();

const options = {
  key: fs.readFileSync('local-dev.app.key'),
  cert: fs.readFileSync('local-dev.app.crt')
};

https.createServer(options, app).listen(443, () => {
  console.log('HTTPS Server running on port 443');
});

嗯.. 非常單純endpoint 都沒有,這邊只是簡單的建立一個 HTTPS 伺服器,並且使用 local-dev.app 這個網域。

記得也要先初始化專案,然後安裝 Express

npm init -y
npm install express

接著執行他(假設檔名是 server.js)。

node server.js

匯入 CA 憑證

  1. 從瀏覽器匯入 (以下以 Chrome 為例)
  2. 直接從 Windows 匯入
  3. Windows 直接透過 ca.pfx 匯入

瀏覽器設定

接下來我們要設定瀏覽器,讓他可以信任我們的 CA 憑證。 (以下以 Chrome 為例)

  1. 開啟瀏覽器,並且前往 chrome://settings/certificates
  2. 點選 管理從 Windows 匯入的憑證
  3. 點選 受信任的根憑證授權單位 頁籤。
  4. 點選 匯入
  5. 選擇 local-dev.app.crt 憑證。
  6. 一路到完成。

這樣瀏覽器就會信任我們的 CA 憑證了。


Windows 設定

  1. Win + R 開啟執行視窗。
  2. 輸入 certmgr.msc 並且按下 Enter
  3. 點選 受信任的根憑證授權單位
  4. 點選 動作 -> 所有工作 -> 匯入
  5. 選擇 local-dev.app.crt 憑證。
  6. 一路到完成。

這樣 Windows 就會信任我們的 CA 憑證了。


Windows 直接透過 ca.pfx 匯入

如標題,直接點開 ca.pfx 憑證,然後密碼是你上面設定的 PFX_PASSWORD,接著選擇 受信任的根憑證授權單位,然後一路到完成。


設定 hosts

最後一個步驟是設定 hosts,這樣我們的瀏覽器才能正確的導向到我們的 HTTPS 伺服器。

Windowshosts 位置在 C:\Windows\System32\drivers\etc\hosts

127.0.0.1 local-dev.app

這樣我們就可以在瀏覽器上輸入 https://local-dev.app 來存取我們的 HTTPS 伺服器了。


好像漏了什麼?

等等,好像漏了什麼,這樣並不是 https://localhost 啊,也許你想支援多個 domain 或是 ip,這樣可以多設定一些 Subject Alternative Name這樣你愛怎麼設就怎麼設

你必須準備一個檔案,格式如下:

subjectAltName = @alt_names
[alt_names]
DNS.1 = domain 1
DNS.2 = domain 2
IP.1 = ip 1
...

基本上就是 123... 一路下去,然後 DNS 就是 domainIP 就是 ip,而 ip 是可選(optional)的。

所以設定可能會像這樣:

subjectAltName = @alt_names
[alt_names]
DNS.1 = local-dev.app
DNS.2 = localhost

也可以把它整合進去我們的腳本:

KEY_FILE=ca.key
PEM_FILE=ca.pem
PFX_FILE=ca.pfx
PFX_PASSWORD=123456
DAYS=365
DOMAIN=local-dev.app5
openssl genpkey -algorithm RSA -out $KEY_FILE
openssl req -x509 -new -nodes -key $KEY_FILE -sha256 -days $DAYS -out $PEM_FILE -subj "/C=TW/ST=Taiwan/L=Taipei/O=/CN=$DOMAIN"
>$DOMAIN.ext cat <<-EOF
subjectAltName = @alt_names
[alt_names]
DNS.1 = $DOMAIN
DNS.2 = localhost
EOF
openssl genrsa -out $DOMAIN.key 2048
openssl req -new -key $DOMAIN.key -out $DOMAIN.csr -subj "/C=TW/ST=Taiwan/L=Taipei/O=/CN=$DOMAIN"
openssl x509 -req -in $DOMAIN.csr -CA $PEM_FILE -CAkey $KEY_FILE -CAcreateserial -out $DOMAIN.crt -days $DAYS -sha256 -extfile $DOMAIN.ext
openssl pkcs12 -export -out $PFX_FILE -inkey $KEY_FILE -in $PEM_FILE -passout pass:$PFX_PASSWORD

主要是多了第 9 行至第 14 行,去產生一個相應的 ext 檔案,之後讓第 17 行去讀取這個檔案。

所以其實你也可以只執行 (環境變數略)

>$DOMAIN.ext cat <<-EOF
subjectAltName = @alt_names
[alt_names]
DNS.1 = $DOMAIN
DNS.2 = localhost
EOF

openssl x509 -req -in $DOMAIN.csr -CA $PEM_FILE -CAkey $KEY_FILE -CAcreateserial -out $DOMAIN.crt -days $DAYS -sha256 -extfile $DOMAIN.ext

或者是你直接去修改 ext 檔案,接著只執行重新產生 crt 檔案。

最後重新啟動你的 HTTPS 伺服器,甚至重新啟動你的瀏覽器,應該就可以正常存取了。


總結

這篇其實算是我自己的筆記,因為未來在辦比賽時可能會需要這樣的環境,讓選手端具有純內網的 HTTPS 環境,來執行一些瀏覽器需要安全的 HTTPS 的功能,這樣就不能單純是 localhost 了。

然後也不想要未來需要每次都重新查一次,乾脆就記錄成一篇文章,幫助未來的自己




最後更新時間: 2024年11月12日.