Nginx e https - Especificar um endereço IP como server_name fornece o site correto, mas o certificado errado

Nginx e https - Especificar um endereço IP como server_name fornece o site correto, mas o certificado errado

Quero executar este URL:https://192.168.1.254e obtenha um site com conteúdo e certificado corretos na barra de endereço. Estou acessando o site, mas recebo um erro de certificado inválido na barra de endereço porque o certificado foi obtido de um bloco de servidor diferente: o bloco de servidor padrão000-default.conf.

Alguém pode me explicar esse comportamento, por favor?

Meu navegador cliente é o Google Chrome versão 87.0.4280.88 (versão oficial) (64 bits)

Meu servidor 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

Penso que a questão está relacionada com a forma como o SNI aparentemente não permiteendereços IPv4 e IPv6 literais como um "HostName". Mas será que esse é realmente o caso?

Eu tenho um bloco de servidor padrão000-default.confassim:

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
}

E outro servidor chamado luci-http.conf assim:

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;
}

Quando eu colocohttp://192.168.1.254na barra de endereço ele me mostra a página correta.

Eu também tenho este servidor 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;
}

Quando eu colocohttps://192.168.1.254na barra de endereço ele me mostra a página correta e o certificado em_lan.crt. Como você pode ver, tenho o mesmo par Cert/Key neste e no bloco de servidor padrão.

No entanto, quando eu removo esse endereço IP como server_name deluci-https.confe adicione-o como server_name em:meusite.lan.confNão vejo o mesmo comportamento.

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;
}

Agora quando eu colocohttps://192.168.1.254na barra de endereço, ele me mostra a página correta, mas novamente o certificado em_lan.crtnão o certificado:meusite.lan.crtdemeusite.lan.confcomo esperado.

Quando eu coloco..

ssl_certificate '/etc/nginx/conf.d/mysite.lan.crt';
ssl_certificate_key '/etc/nginx/conf.d/mysite.lan.key';

no bloco de servidor padrão000-default.confentão recebo esse certificado quando colocohttps://192.168.1.254na barra de endereço do navegador se 192.168.1.254 está especificado como server_name emluci-https.confoumeusite.lan.conf.

Portanto, parece que o SNI corresponderá a um "nome de host" que é um endereço IP, mas leva o certificado do bloco de servidor padrão. Por que é que?

Responder1

... O SNI aparentemente não permite endereços IPv4 e IPv6 literais como um "HostName". Mas será que esse é realmente o caso?

A ideia por trás do SNI é distinguir entre vários domínios no mesmo endereço IP. Na medida em que usar SNI com um endereço IP não faz sentido. Portanto, também está restrito a nomes de host reais. Para citar deRFC 6066:

"HostName" contém o nome completoNome de host DNSdo servidor, conforme entendido pelo cliente. ... Endereços IPv4 e IPv6 literais não são permitidos em "HostName"

    server_name mysite.lan www.mysite.lan fun.mysite.lan 192.168.1.254;

...
Parece que o SNI corresponderá a um "nome de host" que é um endereço IP, mas leva o certificado do bloco de servidor padrão.

Como o SNI é usado apenas para nomes de host reais, não haverá SNI dentro do handshake TLS e, portanto, a configuração HTTPS padrão será usada. Dentro do HTTPS existe o protocolo HTTP que inclui o Hostcabeçalho. Como o Hostcabeçalho especifica o endereço IP (porque o URL especifica), ele corresponderá a esse host virtual específico. Portanto: certificado errado, conteúdo certo.

informação relacionada