Nginx 和 https - 將 ip 地址指定為 server_name 會提供正確的網站但錯誤的證書
我想執行這個網址:https ://192.168.1.254並在地址欄中獲取一個具有正確內容和證書的網站。我正在獲取該網站,但在地址欄中出現無效證書錯誤,因為該證書取自不同的伺服器塊:預設伺服器塊000-default.conf。
有人可以向我解釋這種行為嗎?
我的客戶端瀏覽器是 Google Chrome 版本 87.0.4280.88 (Official Build) (64-bit)
我的 Nginx 伺服器是:
root@OpenWrt:/etc/nginx/conf.d# nginx -V nginx version: nginx/1.19.4 (x86_64-pc-linux-gnu) built with OpenSSL 1.1.1h 22 Sep 2020 TLS SNI support enabled
我認為這個問題與 SNI 顯然不允許將 Literal IPv4 和 IPv6 地址作為 “HostName” 的方式有關。但真的是這樣嗎?
我有一個預設伺服器塊000-default.conf,如下所示:
server { server_name _; listen 80 default_server; listen 443 ssl default_server; ## To also support IPv6, uncomment this block # listen [::]:80 default_server; # listen [::]:443 ssl default_server; ssl_certificate '/etc/nginx/conf.d/_lan.crt'; ssl_certificate_key '/etc/nginx/conf.d/_lan.key'; return 404; # or whatever }
另一個名為 luci-http.conf 的伺服器是這樣的:
server { listen 80; listen [::]:80; server_name openwrt.lan 192.168.1.254; # access_log /proc/self/fd/1 openwrt; # use logd (init forwards stdout). include conf.d/*.locations; }
當我將http://192.168.1.254放在地址欄中時,它會為我提供正確的網頁。
我也有這個 https 伺服器: luci-https.conf
server { listen 443 ssl; listen [::]:443 ssl; server_name openwrt.lan 192.168.1.254; #include '/var/lib/nginx/lan_ssl.listen.default'; ssl_certificate '/etc/nginx/conf.d/_lan.crt'; ssl_certificate_key '/etc/nginx/conf.d/_lan.key'; ssl_session_cache 'shared:SSL:32k'; ssl_session_timeout '64m'; # access_log /proc/self/fd/1 openwrt; # use logd (init forwards stdout). include conf.d/*.locations; }
當我將https://192.168.1.254放在地址欄中時,它會為我提供正確的網頁和**_lan.crt**中的證書。如您所見,我在此和預設伺服器塊中有相同的證書/密鑰對。
但是,當我從luci-https.conf中刪除該 IP 地址作為 server_name並將其添加為 server_name 時:mysite.lan.conf我沒有看到相同的行為。
server { listen 443 ssl; listen [::]:443 ssl; #listen 192.168.1.254 ssl; #include '/var/lib/nginx/lan_ssl.listen'; server_name mysite.lan www.mysite.lan fun.mysite.lan 192.168.1.254; root /www/mysite; index index.html index.htm index.nginx-debian.html; ssl_certificate '/etc/nginx/conf.d/mysite.lan.crt'; ssl_certificate_key '/etc/nginx/conf.d/mysite.lan.key'; ssl_session_cache 'shared:SSL:32k'; ssl_session_timeout '64m'; location / { try_files $uri $uri/ =404; } access_log /var/log/nginx/mysite.lan.access.log; error_log /var/log/nginx/mysite.lan.error.log; }
現在,當我將https://192.168.1.254放在地址欄中時,它會為我提供正確的網頁,但再次是**_lan.crt中的證書,而不是mysite.lan.conf中的mysite.lan.crt**。
當我放..
ssl_certificate '/etc/nginx/conf.d/mysite.lan.crt'; ssl_certificate_key '/etc/nginx/conf.d/mysite.lan.key';
在預設伺服器塊000-default.conf中,然後當我將https://192.168.1.254放在瀏覽器地址欄中時,我得到了該證書,無論 192.168.1.254 是否被指定為luci-https.conf或mysite.lan中的 server_name .conf。
因此,SNI 似乎將匹配作為 IP 地址的“主機名”,但它從預設伺服器塊獲取證書。這是為什麼?
… SNI 顯然不允許將文字 IPv4 和 IPv6 地址作為“主機名”。但真的是這樣嗎?
SNI 背後的想法是區分同一 IP 地址上的多個域。到目前為止,使用帶有 IP 地址的 SNI 並沒有真正的意義。因此,它也僅限於實際主機名。從RFC 6066引用:
“HostName”包含客戶端所理解的伺服器的完全限定DNS 主機名。… “主機名”中不允許使用文字 IPv4 和 IPv6 地址
server_name mysite.lan www.mysite.lan fun.mysite.lan 192.168.1.254;
…
因此,SNI 似乎將匹配作為 IP 地址的“主機名”,但它從預設伺服器塊獲取證書。
由於 SNI 僅用於實際主機名,因此 TLS 握手中沒有 SNI,因此使用預設的 HTTPS 配置。在 HTTPS 內部有 HTTP 協議,但它包含
Host
標頭。由於Host
標頭指定了 IP 地址(因為 URL 確實如此),它將匹配這個特定的虛擬主機。因此:錯誤的證書,正確的內容。