跳到主內容

【常見問題】https 使用domain 與 ip 差異

好的,以下補上:


✅ 比較 https://a.b.comhttps://168.23.1.1 的差異

這兩者協定一樣(都是 HTTPS),但主機名稱(Host)差異會影響 SSL 憑證驗證、DNS 解析、與 Nginx 的設定行為


 差異對照表

項目 https://a.b.com https://168.23.1.1
協定 HTTPS(加密) HTTPS(加密)
主機名稱 網域名稱(FQDN) IP 位址
DNS 解析 會經過 DNS 解析 → IP 不經 DNS
SSL 憑證驗證 通常需要憑證中的 CN/SAN 包含 a.b.com 需要憑證中包含 IP 位址(不常見)
Nginx server_name 配置 server_name a.b.com; server_name 168.23.1.1;(不建議)或 _
常見用法 公網、正式站、內部網域皆可 測試、開發、內網 IP 使用
風險與限制 SSL 憑證驗證容易通過 一般憑證不支援 IP → 會出現 TLS 錯誤
信任憑證 可用 Let's Encrypt、商業憑證 除非特別申請 IP 憑證,否則會有警告

 SSL 憑證驗證差異舉例

https://a.b.com

  • 若你使用 Let's Encrypt 為 a.b.com 建立憑證:
    curl https://a.b.com ➜ 成功(CN/SAN 包含 a.b.com

https://168.23.1.1

  • 若你拿 a.b.com 憑證套用到 IP 上:
    curl https://168.23.1.1 ➜ 失敗,出現 SSL: certificate subject name does not match

 解法(不建議用於正式環境):

  • 為 IP 簽發 SSL 憑證(需自簽或企業憑證)

  • curl -k 忽略憑證錯誤

curl -k https://168.23.1.1  # 跳過憑證驗證(不安全)

✅ Nginx 設定差異

a.b.com 對應設定:

server {
    listen 443 ssl;
    server_name a.b.com;

    ssl_certificate     /etc/nginx/certs/a.b.com.crt;
    ssl_certificate_key /etc/nginx/certs/a.b.com.key;

    location / {
        proxy_pass http://localhost:3000;
    }
}

IP 直接連線時,通常會用:

server {
    listen 443 ssl;
    server_name _;  # 匹配所有 hostname(或不設定)

    ssl_certificate     /etc/nginx/certs/selfsigned.crt;
    ssl_certificate_key /etc/nginx/certs/selfsigned.key;

    location / {
        proxy_pass http://localhost:3000;
    }
}

🧨 若直接用 IP,也許不會觸發 server_name 對應,取決於 Nginx 設定順序與 SNI。


✅ 小結

URL 適用時機 憑證需求 風險
https://a.b.com 公網、正常使用 CN/SAN 需含 a.b.com 正常通過憑證驗證
https://168.23.1.1 內部測試或特例 憑證需含 IP 或自簽 容易驗證失敗、跳警告

 

✅Curl Domain 與 ip 的 差異

這是一個非常關鍵的細節問題,涉及到 HTTPS、Host Header、SNI(Server Name Indication),我們來完整拆解:


你提供的兩個請求:

curl https://a.b.com
curl https://168.23.1.1 -H 'Host: a.b.com'

看起來類似,實際上在底層行為非常不同


 核心差異一覽

項目 curl https://a.b.com curl https://168.23.1.1 -H 'Host: a.b.com'
連線 IP DNS 解析 a.b.com → IP 直接指定 IP 168.23.1.1
TLS SNI 傳送內容 a.b.com(🔑 用來選擇憑證) 168.23.1.1(🚨 TLS 層不包含 a.b.com
Host Header(HTTP 層) Host: a.b.com(由 curl 自動加) Host: a.b.com(你手動加)
SSL 憑證是否驗證成功? ✅ 通常會成功 ❌ 若憑證是發給 a.b.com 則會 mismatch
Nginx 是否能進到正確的 server ✅ 通常會進到 server_name a.b.com ❌ 取決於 SNI,可能進入 default server

 為何 TLS 憑證驗證會失敗?

 SNI 是什麼?

  • TLS 層在握手階段會送出 Server Name(來自 curl--resolve 或 URL)。

  • 用來讓伺服器知道要回哪一張憑證。

在兩種情況下比較:

curl https://a.b.com

  • DNS → 168.23.1.1

  • SNI: a.b.com

  • Host header: a.b.com

  • Nginx 匹配成功,憑證也是給 a.b.com,一切正常

curl https://168.23.1.1 -H 'Host: a.b.com'

  • SNI: 168.23.1.1(預設值,非 a.b.com)

  • Host header: a.b.com(只有 HTTP 層有用)

  • 若 Nginx 用 server_name a.b.com 並綁定憑證,那會 因為 SNI 不符無法選中正確的憑證 → TLS 握手失敗


Nginx 對這兩種請求的反應

server {
    listen 443 ssl;
    server_name a.b.com;

    ssl_certificate     /etc/nginx/certs/a.b.com.crt;
    ssl_certificate_key /etc/nginx/certs/a.b.com.key;

    location / {
        return 200 "hello a.b.com\n";
    }
}

server {
    listen 443 ssl default_server;
    server_name _;

    ssl_certificate     /etc/nginx/certs/default.crt;
    ssl_certificate_key /etc/nginx/certs/default.key;

    location / {
        return 200 "default server\n";
    }
}

測試結果:

測試指令 伺服器 block 命中 回傳內容 是否 SSL 通過
curl https://a.b.com server_name a.b.com hello a.b.com ✅ 是
curl https://168.23.1.1 -H 'Host: a.b.com' server_name _(default) default server ⚠️ 通常憑證不符(或需 -k

✅ 解法:讓 IP 請求也能通過 SSL

方法一:用自簽或專門支援 IP 的憑證

但大多數公開 CA(如 Let's Encrypt)不發給 IP 憑證

方法二:用 curl 忽略 TLS 驗證

curl -k https://168.23.1.1 -H 'Host: a.b.com'

方法三:讓 curl 傳送正確的 SNI(推薦)

curl --resolve a.b.com:443:168.23.1.1 https://a.b.com
  • 這會讓 curl:

    • SNI 傳 a.b.com

    • Host header 是 a.b.com

    • 實際連到 IP 168.23.1.1

  • ✅ 完整模擬瀏覽器行為


✅ 總結

比較項目 curl https://a.b.com curl https://168.23.1.1 -H 'Host: a.b.com'
DNS 解析 ✅ 有 ❌ 無
TLS SNI a.b.com 168.23.1.1
Host Header a.b.com a.b.com
SSL 憑證驗證 ✅ 通常成功 ❌ 會失敗(除非用 -k
建議用法 ✅ 正常連線方式 ⚠️ 用於測試或模擬

如果你需要模擬真實請求又繞過 DNS,可使用:

curl --resolve a.b.com:443:168.23.1.1 https://a.b.com

這是最穩定且最貼近瀏覽器 SNI 行為的方式。