Nginx. ¿Cómo rechazo la solicitud al servidor virtual SSL no listado?

13

Tengo un certificado SSL comodín y varios subdominios en la misma ip. Ahora quiero que mi nginx maneje solo los nombres de servidor mencionados y desconecte la conexión para otros para que parezca que nginxno se está ejecutando para nombres de servidor no listados (no responde, rechaza, muere, ni un solo byte en respuesta). Hago lo siguiente

ssl_certificate         tls/domain.crt;
ssl_certificate_key     tls/domain.key;

server {
  listen 1.2.3.4:443 ssl;
  server_name validname.domain.com;
  //
}

server {
  listen 1.2.3.4:443 ssl;
  server_name _;
  // deny all;
  // return 444;
  // return 404;
  //location {
  //  deny all;
  //}
}

He intentado casi todo en el último bloque del servidor, pero no he tenido éxito. Recibo una respuesta válida de un servidor virtual conocido o un código de error. Por favor ayuda.

andbi
fuente

Respuestas:

7

No funciona de esa manera: el protocolo de enlace SSL ocurre antes de HTTP, por lo que el nombre en el certificado se evaluará en el navegador antes de que pueda redirigir o hacer cualquier otra cosa dentro de la configuración de nginx.

cjc
fuente
esto es malo, pero tengo que admitirlo) Gracias.
andbi
3
Esto no es cierto: puede hacer algo más en el nivel inferior, como desconectar la conexión sin ninguna respuesta, como se explica en otras respuestas.
collimarco
13

La respuesta de cjc ya señaló correctamente el problema al intentar hacer coincidir los nombres de host cuando SSL está habilitado. Sin embargo, es posible hacerlo así:

server {
    ...

    if ($host !~* ^validname\.domain\.com$ ) {
        return 444;
    }
    ...
}

Nota: sí, es cierto que generalmente ifes malo , pero es seguro usarlo ifen este caso. (Lea la página vinculada si necesita convencerse).

Contrariamente a lo sugerido, simplemente agregar el siguiente bloque no funcionará:

server {
    listen 80;
    listen 443 ssl;
    return 444;
}

porque un certificado SSL que coincida validname.domain.comno coincidirá con algún nombre de dominio aleatorio. Lo probé y nginx actuó como si el bloque no estuviera presente en absoluto.

Esto tampoco funcionará:

server {
    listen       443;
    server_name    _;
    return 444; 
}

porque hará que todas las conexiones HTTPS en el puerto 443 fallen, incluso las que deberían pasar. He probado este también. wgetinformó un error de protocolo de enlace SSL.

Louis
fuente
5

La mayoría de las respuestas aquí son sobre por qué no funciona, no cómo hacerlo funcionar.

A continuación, se explica cómo: debe hacer que dicho servidor general sea un 'servidor_predeterminado' y debe proporcionar rutas a cert / key para que pueda descifrar la solicitud SSL entrante y que coincida con el encabezado Host:

server {
    listen 80 default_server;
    listen 443 ssl default_server;
    server_name _;
    ssl_certificate <path to cert>;
    ssl_certificate_key <path to key>;
    return 404;
}

Tenga en cuenta el ssl_certificate / ssl_certificate_key allí. Si no se especifican, nginx aún intenta utilizar dicho servidor predeterminado y falla, ya que no puede aceptar la conexión SSL sin un certificado / clave. Se puede usar cualquier certificado / clave, por ejemplo, autofirmado. ...

Para generar un certificado autofirmado:

openssl req -x509 -newkey rsa:4096 -nodes -out cert.pem -keyout key.pem -days 365 

Consulte también /server//a/841643/87439

andreycpp
fuente
1
¿Has probado esto? ¿Cómo se crea un certificado SSL que coincida con el nombre del servidor "_"?
Tim
Sí, esta solución me funciona. Tuve el mismo problema exacto y deduje de la documentación que nginx necesita un certificado / clave ya que no se ve en TLS SNI. Puede usar cualquier certificado / clave, por ejemplo, autofirmado.
andreycpp
1

Implementé la solución anterior hoy, y funcionó a la perfección. Todas las URL no especificadas se descartan, ahora. Colocar este código de servidor antes de que la entrada real del servidor virtual fuera clave: todas las URL mal formadas ahora van a este servidor 'predeterminado'.

... 
server {
     listen       443;
     server_name    _;
     return 444; }

server {
     listen       443;
     server_name  [URL]
David Sexton
fuente
0

Debería poder manejar esto haciendo que el servidor que maneja los elementos no listados sea el primer bloque de servidor en su configuración.

http {
    ...

    server {
        listen 80;
        listen 443 ssl;
        return 444;
    }

    server {
        server_name validname.domain.com;
        ...
    }
}

Todos los dominios no identificados específicamente serán manejados por este bloque de servidor.

Dayo
fuente
1
No funciona
AmirHossein