¿Por qué escuchar 443 default_server; anulación de regla nginx regla ya configurada (reglas http funcionan de manera normal)?

9

Tengo un nginx y diferentes subdominios:

a.mydomain.com
b.mydomain.com
c.mydomain.com

Nginx tiene 4 reglas:

1) regla de reescritura:

server {
  listen 80
  server_name gl.udesk.org;

  root /nowhere;
  rewrite ^ https://a.mydomain.com$request_uri permanent;
}

2) regla https:

server {

  listen 443;
  server_name a.mydomain.com;

  root /home/a/a/public;

  ssl on;
  ssl_certificate conf.d/ssl/a.crt;
  ssl_certificate_key conf.d/ssl/a.key;
  ssl_protocols ...
  ssl_ciphers ...
  ssl_prefer_server_ciphers on;

  location ...
}

3) regla predeterminada de http:

server {
  listen 80 default_server;
  return 444;
}

4) regla predeterminada de https:

server {
  listen 443 default_server;
  return 444;
}

Entonces, si comienzo nginx y:

  • si voy en el navegador a http://a.mydomain.com , redirige a https://a.mydomain.com y luego devuelve un error 107 (net :: ERR_SSL_PROTOCOL_ERROR): error de protocolo SSL.
  • si voy en el navegador a https://b.mydomain.com , espero que devuelva el error 444. Pero en su lugar, devuelve el mismo error 107 (net :: ERR_SSL_PROTOCOL_ERROR): error de protocolo SSL.
  • y para todos los registrados por el proveedor de DNS CNAME (es decir, a, b, c)
  • Todas las versiones http (p. ej., regla 3) funcionan como se esperaba:

Entonces, ¿por qué las reglas https en nginx son tan difíciles de configurar y cómo debo configurarlas correctamente para obtener el mismo comportamiento que con la versión http?

Actualizar:

Crear un nuevo certificado y agregar:

ssl on;
ssl_certificate conf.d/ssl/default.crt;
ssl_certificate_key conf.d/ssl/default.key;

funciona ahora, pero tendría una solución sin ningún certificado SSL necesario. Simplemente restablezca todas las conexiones para todos los subdominios https (puerto 443) excepto https://a.mydomain.com sin proporcionar un certificado.

estático
fuente
2
No puedes SSL requiere un certificado antes de que el servidor web sepa qué dominio desea . Tiene que tener un certificado para enviar, o no puede establecer la conexión para hablar con el cliente.
Darth Android
2
@DarthAndroid: La magia se llama SNI - en.wikipedia.org/wiki/Server_Name_Indication .
Shi
@Shi Soy consciente de SNI: eso permite que el servidor web elija qué certificado enviar, pero aún debe elegir un certificado. nginxno es lo suficientemente inteligente como para darse cuenta de que no necesita un certificado para lo que el usuario quiere hacer.
Darth Android

Respuestas:

3

¡No mezcle el puerto 443 con ssl! Nginx es completamente independiente del puerto. También puede ofrecer https a través del puerto 80. Las versiones modernas de nginx permiten

listen 1234 ssl;

y no necesitas la ssl on;línea entonces.

Pero si desea servir https, debe especificar un certificado. Su servidor ingresa https cuando reescribe la solicitud http en una solicitud https.

Obtiene el PROTOCOL ERROR, ya que SSL Handshake se realiza antes que nada. Entonces return 444no se alcanza. Y cualquier protocolo de enlace SSL necesitará un certificado y una clave privada para alimentar los algoritmos de cifrado con el par certificado / clave privada.

ikrabbe
fuente
3

La returndirectiva es parte del módulo de reescritura. Si revisa la documentación , puede ver que funciona con solicitudes. En HTTPS, las solicitudes solo se pueden realizar una vez finalizado el protocolo de enlace.

Hay una solicitud de función: https://trac.nginx.org/nginx/ticket/195 y se proporciona una solución alternativa.

server {
    listen 443 ssl;
    server_name bbb.example.com;
    ssl_ciphers aNULL;
    ssl_certificate /path/to/dummy.crt;
    ssl_certificate_key /path/to/dummy.key;
    return 444;
}
VBart
fuente
Tenga en cuenta que esto romper clientes HTTPS no-SNI capaces (como la propia nginx proxy_pass, a menos que establezca proxy_ssl_server_name on;) lleguen a cualquier otra server_names(lo que en esencia romper los legítimos server_names que no quiere dejar pasar). Vea trac.nginx.org/nginx/ticket/195#comment:11 para más detalles.
nh2