Curl

openssl 命令通過 ip 而不是主機名查詢 NGINX

  • February 18, 2021

這是我很難理解的情況。我有兩個用於主機的 nginx 設置,如下所示

server {
   server_name _;
   listen *:443 default_server deferred;
   return 444;
}
server {
   listen      443 ssl http2;
   listen [::]:443 ssl http2;
   server_name www.example.ca;

}

包羅萬像有一個自行生成的 ssl 證書,我的應用程序的塊有一個有效的 SSL 證書。此設置適用於 Web 瀏覽器。如果一個網路瀏覽器去https://www.example.com然後他們去我的應用程序,但如果他們去htpps://123.123.123.123然後它什麼也不會返回。但是現在我遇到了一個非常奇怪的情況。我收到了一些失敗的域請求(來自腳本),所以我嘗試調試。首先我嘗試捲曲網址:

$ curl https://www.example.ca
curl: (60) server certificate verification failed. CAfile: /etc/ssl/certs/ca-certificates.crt CRLfile: none

我認為這很奇怪,因為瀏覽器都顯示證書有效,並且 www.ssllabs.com 顯示它有效。我嘗試的下一步是在命令行上查看 SSL 證書:

echo | openssl s_client -showcerts -connect www.example.ca:443

這個命令實際上顯示了我的擷取所有伺服器塊而不是塊的 SSL 證書example.ca。如果我將 ip 地址添加到第二個 nginx 塊,那麼我會看到example.ca. 所以現在我知道 openssl 和 curl 得到了錯誤的 ssl 證書,因為他們得到了錯誤的證書,但我不明白為什麼?

我對 openssl 了解不多,但我能想到的只是 openssl/curl 錯誤地將主機名轉換為 IP 地址,或者他們忘記添加正確的標頭?這非常奇怪,如果有人知道更多,我將不勝感激。

像 nginx 這樣的具有多個證書(和密鑰)的虛擬主機伺服器使用伺服器名稱指示 (SNI) 擴展來選擇正確的(虛擬主機和)證書,但預設情況下openssl s_client不發送 SNI,因此您將獲得預設證書;-servername $hostname按照手冊頁中的說明添加(在 之後-connect)。這部分在其他幾個堆棧上有很多重複,但我在這裡找不到。(更新:2018 年的 OpenSSL 1.1.1 修復了此問題;SNI 現在是預設設置,除非您指定-noservername.)

OTOHcurl確實會自動發送 SNI(瀏覽器和 ssllab 也是如此),除非您擁有 curl 本身或其使用的中間件的真正舊版本(並不總是 OpenSSL;檢查curl -V大寫)。嘗試添加-v以獲取有關它正在做什麼和獲取的更多詳細資訊,如果這還不夠,請使用 tcpdump/Wireshark/etc 獲取線路跟踪。

引用自:https://unix.stackexchange.com/questions/404888