openssl 命令通過 ip 而不是主機名查詢 NGINX
這是我很難理解的情況。我有兩個用於主機的 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
.)OTOH
curl
確實會自動發送 SNI(瀏覽器和 ssllab 也是如此),除非您擁有 curl 本身或其使用的中間件的真正舊版本(並不總是 OpenSSL;檢查curl -V
大寫)。嘗試添加-v
以獲取有關它正在做什麼和獲取的更多詳細資訊,如果這還不夠,請使用 tcpdump/Wireshark/etc 獲取線路跟踪。