nginx - Cómo evitar el procesamiento de solicitudes con nombres de servidor no definidos con HTTPS

15

¿Cómo evito que nginx procese una solicitud con un nombre de servidor no definido utilizando el protocolo https?

La siguiente configuración hace que esto funcione para solicitudes http normales. Restablece la conexión para solicitudes con host headers vacío que es igual a server_name en la configuración nginx:

server {
    listen      80;
    server_name "";
    return      444;
}

Actualizado para mayor claridad:

Sin embargo, el servidor sirve html del bloqueo del servidor que soporta ssl predeterminado cuando se envía una solicitud a través de https con un host header vacío. ¿Cómo se puede evitar esto?

Me gustaría lograr el comportamiento exacto como para las solicitudes http con un host header - sin html servido, restablecimiento de la conexión (retorno 444).

¿Cuál sería la forma correcta de bloquear dichas solicitudes https y lograr también el comportamiento mencionado para las conexiones https? (Me gustaría evitar el uso del certificado SSL adecuado para esto, ya que esto puede simplemente indicar a los spammers en el dominio del servidor real).

Actualización 13.03.2015

Poner un haproxy delante de nginx con la configuración

strict-sni

solucioné mi problema completamente.

    
pregunta binaryanomaly 14.04.2014 - 23:15
fuente

4 respuestas

11

Lo resolví generando un certificado falso que no revela el nombre de dominio y lo agregué como predeterminado al inicio de la configuración:

server {
    listen 443 default;
    server_name     _;

    ssl     on;
    ssl_certificate         /path/to/fake.crt;
    ssl_certificate_key     /path/to/fake.key;

    return 403;
}

Y sí, requiere un nginx con soporte SNI (verifique nginx -V ).

Seguir en: Cómo crear un certificado SSL autofirmado para fines de prueba     
respondido por el int_ua 12.12.2015 - 08:13
fuente
9

Debido a la naturaleza de cómo funciona SSL, el protocolo de enlace SSL / TLS se realiza antes de que el nombre de host deseado se entregue al servidor web. Esto significa que el certificado predeterminado (primero) se usa cuando se intenta acceder al sitio, independientemente del nombre de dominio utilizado.

Esto es cierto tanto con Apache como con nginx.

De la Apache Wiki :

  

Como regla general, es imposible alojar más de un host virtual SSL en   La misma dirección IP y puerto. Esto es porque Apache necesita saber el   Nombre del host para elegir el certificado correcto para la configuración.   La capa de cifrado. Pero el nombre del host que se solicita es   contenida solo en los encabezados de solicitud HTTP, que forman parte de la   contenido encriptado Por lo tanto, no está disponible hasta después de la   El cifrado ya está negociado. Esto significa que la correcta   no se puede seleccionar el certificado y los clientes recibirán el certificado   advertencias de falta de coincidencia y ser vulnerables a los ataques de intermediarios.

De la documentación de nginx :

  

Con esta configuración, un navegador recibe el servidor predeterminado   Certificado, es decir, www.example.com independientemente del servidor solicitado   nombre. Esto es causado por el comportamiento del protocolo SSL. La conexión SSL es   establecido antes de que el navegador envíe una solicitud HTTP y nginx hace   No se conoce el nombre del servidor solicitado. Por lo tanto, sólo puede   ofrece el certificado del servidor predeterminado.

¿Cómo puedes resolver este problema?

La solución más sencilla es usar direcciones IP separadas para cada sitio que desee proteger.

Si esto no es posible, podría ser posible resolver el problema utilizando Indicación del nombre del servidor (SNI, RFC 6066 ). Esto permite que un navegador pase el nombre de dominio al servidor durante el protocolo de enlace.

Tanto Nginx como Apache admiten SNI. Puede encontrar más información sobre nginx SNI en la documentación .

Vale la pena señalar que SNI solo se puede usar para nombres de dominio y no para direcciones IP. Debe tomar precauciones adicionales al configurar sus servidores web para abordar este problema, por lo que cualquier solicitud a la IP se gestiona correctamente.

  

Solo los nombres de dominio pueden pasarse en SNI, sin embargo, algunos navegadores pueden   Pasar erróneamente una dirección IP del servidor como su nombre si una solicitud   Incluye la dirección IP literal. Uno no debe confiar en esto.

El Wiki de Apache tiene más información sobre la implementación de SNI . Pero incluso su documentación informa que esta solución no es perfecta.

  

El uso de hosts virtuales basados en nombres con SSL agrega otra capa de   complicación. Sin la extensión SNI, generalmente no es posible   (aunque un subconjunto de host virtual podría funcionar). Con SNI, es necesario.   considerar la configuración cuidadosamente para garantizar la seguridad es   mantenido.

Dicho esto, puedes ver cómo esta configuración no es tan simple como los hosts virtuales normales. Para poder encontrar una solución a su problema, deberíamos conocer más detalles sobre su configuración y el comportamiento esperado cuando se envía una solicitud de IP.

En general, para "bloquear" un dominio no configurado o una solicitud de IP, debe configurarlo como el sitio predeterminado y luego mostrar un error, redirigir, salir, etc.

    
respondido por el David Houde 26.04.2014 - 12:21
fuente
4

Si entiendo que desea rechazar las solicitudes HTTP, que no contienen un encabezado de host, incluso si estas solicitudes están dentro de una conexión SSL (por ejemplo, solicitudes https). Estas son solicitudes HTTP / 1.0 de estilo antiguo, HTTP / 1.1 requiere un encabezado de Host, pero también la mayoría de los clientes HTTP / 1.0 ya envían uno. El bloqueo de estos clientes se puede hacer con:

    if ( $http_host = '' ) {
            return 444;
    }

Pero esto no ayuda si el cliente utiliza un encabezado de host con correo no deseado o la dirección IP en él. Por lo tanto, sería mejor verificar que el encabezado del host contenga los valores esperados (como beneficio adicional, esto también ayuda contra los ataques de reencuadernación de DNS), por ejemplo,

    if ( $http_host !~* ^(example\.com|www\.example\.com)$ ) {
            return 444;
    }
    
respondido por el Steffen Ullrich 26.04.2014 - 16:51
fuente
0

Usé el método similar al que se menciona @int_ua, pero un poco complicado.

Configuré mi nginx para usar RSA y ECDSA como método de autenticación TLS, pero emití un certificado DSA para el servidor predeterminado.
Como no hay una suite de cifrado disponible, el protocolo de enlace TLS fallaría antes de servir cualquier página.
Creo que tendría el mismo resultado que lo que configuró (HAproxy strict-sni) y creo que mi método tendría un mejor rendimiento.

Puedes ver el resultado de mi configuración:

  

SNI no válido: enlace
  (Puede configurar sus hosts a esta dirección IP y ver el resultado también)
  SNI válido: enlace
  El enlace SNI válido apunta a la misma dirección IP que la anterior

Daría mi configuración aquí:

Configuración de SSL
(Utilicé un parche igual a openssl para que los cifrados sean un poco extraños ... También puedes mantener tu configuración , pero recuerde que no contiene ningún cifrado DSS!)

    #Protocols
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; # Dropping SSLv3, ref: POODLE
    #
    #Key Exchange
    ssl_ecdh_curve X25519:P-256:P-384:P-224:P-521;
    ssl_dhparam /var/SSL/DH-param.pem;
    #
    #Cipher Suites
    ssl_ciphers "[TLS_AES_128_GCM_SHA256|TLS_CHACHA20_POLY1305_SHA256]:[TLS_AES_256_GCM_SHA384|TLS_AES_128_CCM_8_SHA256|TLS_AES_128_CCM_SHA256]:[ECDHE-ECDSA-CHACHA20-POLY1305|ECDHE-ECDSA-AES128-GCM-SHA256|ECDHE-RSA-CHACHA20-POLY1305|ECDHE-RSA-AES128-GCM-SHA256|DHE-RSA-CHACHA20-POLY1305]:[ECDHE-ECDSA-AES256-GCM-SHA384|ECDHE-RSA-AES256-GCM-SHA384]:[ECDHE-ECDSA-AES128-SHA|ECDHE-RSA-AES128-SHA]:[ECDHE-ECDSA-AES256-SHA|ECDHE-RSA-AES256-SHA]:DHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA";
    ssl_prefer_server_ciphers on;



Configuración predeterminada del servidor

##
# General
##
# Listen
listen 8080 default_server;
listen 8443 ssl spdy http2 default_server;
#
# Server Name
server_name _;

##
# SSL Settings
##
#
# Certificate
#  DSA
ssl_certificate /var/SSL/certificates/DEFAULT.dsa.crt;
ssl_certificate_key /var/SSL/keys/DEFAULT.dsa.key;

root /var/www/html/nginx/;



La clave DSA se genera desde OpenSSL y el certificado se emite desde mi propia PKI. Puede utilizar este certificado si lo desea.
(Este certificado nunca se enviaría desde el servidor nginx, por lo que todo el certificado, incluso la duración de la clave y el período válido no tiene sentido)

Certificado:

-----BEGIN CERTIFICATE-----
MIIFrjCCBJagAwIBAgIUHVfGi/SP2d/B4vbxZSKSVEpSoGEwDQYJKoZIhvcNAQEL
BQAwgYExCzAJBgNVBAYTAkNOMSMwIQYDVQQKDBpKZW1teUxvdmVKZW5ueSBQS0kg
U2VydmljZTEeMBwGA1UECwwVcGtpLmplbW15bG92ZWplbm55LnRrMS0wKwYDVQQD
DCRKZW1teUxvdmVKZW5ueSBTSEEyIFNlY3VyZSBTZXJ2ZXIgQ0EwHhcNMTgwMTAx
MDAwMDAwWhcNMTkxMjMxMjM1OTU5WjAiMSAwHgYDVQQDDBdERUZBVUxUIFNTTCBD
RVJUSUZJQ0FURTCCAbcwggEsBgcqhkjOOAQBMIIBHwKBgQCVcFt4xWkIBtiN/Xay
O7Ls5EjBCFckvyBQpRJ5wmjrxepQbUK9xmiXmpkXOsEYHy14UQXswzKPBWiHsNDs
8apFoGAvjBxSg9Y07wd5VBnhBGvqd0VmD92eKAFW1sZZVoSrLwizfIde0sj9bZCD
KICt/0jdz0QGBZzXTtd4MOcjUQIVAPD9cVtRAdD6al8v/SV2YVQHZmafAoGBAI+A
tCrjcvK0PFILpwpGD/3gJI8o2oxKoPjjE3SM9b4mrN/2ixEGgGiXHOrEyZ7IgSjf
1Z6X2nuN+IgsNdJAZjNbnuacxbu4z5FmnO6i9IRXEqtKNzONeHJSG+7w7zUPfsPT
8sTxHU0Z5ynjiLz4GcnO5LVcMNbf2uEsl41fObB4A4GEAAKBgHOFoU8xns0qMFLz
h3ZiYScs2Rznw7xeo2HbM8hGI9zKWRoV49f9V2vHFjdPSLkPbzgoSqOxmGD7UZep
W0TcsSPVKIuKBw07vvJkpUG8U71mcedNN5+fNbIcgjKdTlIIbrEFYRFG6zrIcZ3/
WArPchw3RC+SRrBXW8+27T4+0PMao4IB5TCCAeEwHwYDVR0jBBgwFoAU4BPpj9H7
K19wMi69RQ9t6BLyNOcwHQYDVR0OBBYEFFrpB6sLpQwodD7KWPssHj0fkqjCMAkG
A1UdEQQCMAAwDgYDVR0PAQH/BAQDAgeAMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggr
BgEFBQcDAjBJBgNVHR8EQjBAMD6gPKA6hjhodHRwOi8vY3Jscy5wa2kuamVtbXls
b3ZlamVubnkudGsvU0hBMlNlY3VyZVNlcnZlckNBLmNybDCBggYDVR0gBHsweTBt
BglghkgBpKInAQIwYDAtBggrBgEFBQcCARYhaHR0cHM6Ly9wa2kuamVtbXlsb3Zl
amVubnkudGsvY3BzMC8GCCsGAQUFBwICMCMaIWh0dHBzOi8vcGtpLmplbW15bG92
ZWplbm55LnRrL3JwYTAIBgZngQwBAgEwgYYGCCsGAQUFBwEBBHoweDAtBggrBgEF
BQcwAYYhaHR0cDovL29jc3AucGtpLmplbW15bG92ZWplbm55LnRrMEcGCCsGAQUF
BzAChjtodHRwOi8vY2FjZXJ0cy5wa2kuamVtbXlsb3ZlamVubnkudGsvU0hBMlNl
Y3VyZVNlcnZlckNBLmNydDAMBgNVHRMBAf8EAjAAMA0GCSqGSIb3DQEBCwUAA4IB
AQCtgVPw2KLT/ntVYZE8AL71C0R1gsn9MKoqD6asaM16qK60G7YK8qC2I/5wWXAr
+zVeegvU/73qWq66DnIF333uZz3aeaXoIEfDRcfePVzWTG62cO2fPyTWyIczaPFf
NqQqoukM3UeBM0yIRSbiyRAFoyz0TWhdgSDXGrG+X5EvUnH6J+umnt/PNGaNnz1f
eXJBh79UnmCpMI6rW+7UG4F60xxQ/RQeRZZt//Ze5YzIDRjUQpXQ1a+9cHuPT8EY
Ft4xe4q5FgMVTBsu1zAfA/ViSDlHWAO8oioKkYDYHqYmLT6ERSoXNVK6WbNh4mem
AaF8T8DKQTHD5GKFBJSSkvF7
-----END CERTIFICATE-----



Clave:

-----BEGIN DSA PRIVATE KEY-----
MIIBuwIBAAKBgQCVcFt4xWkIBtiN/XayO7Ls5EjBCFckvyBQpRJ5wmjrxepQbUK9
xmiXmpkXOsEYHy14UQXswzKPBWiHsNDs8apFoGAvjBxSg9Y07wd5VBnhBGvqd0Vm
D92eKAFW1sZZVoSrLwizfIde0sj9bZCDKICt/0jdz0QGBZzXTtd4MOcjUQIVAPD9
cVtRAdD6al8v/SV2YVQHZmafAoGBAI+AtCrjcvK0PFILpwpGD/3gJI8o2oxKoPjj
E3SM9b4mrN/2ixEGgGiXHOrEyZ7IgSjf1Z6X2nuN+IgsNdJAZjNbnuacxbu4z5Fm
nO6i9IRXEqtKNzONeHJSG+7w7zUPfsPT8sTxHU0Z5ynjiLz4GcnO5LVcMNbf2uEs
l41fObB4AoGAc4WhTzGezSowUvOHdmJhJyzZHOfDvF6jYdszyEYj3MpZGhXj1/1X
a8cWN09IuQ9vOChKo7GYYPtRl6lbRNyxI9Uoi4oHDTu+8mSlQbxTvWZx5003n581
shyCMp1OUghusQVhEUbrOshxnf9YCs9yHDdEL5JGsFdbz7btPj7Q8xoCFFfXTHSl
C7tdLJO9vQFcyKMhU8TU
-----END DSA PRIVATE KEY-----
    
respondido por el JemmyLoveJenny 02.08.2018 - 10:41
fuente

Lea otras preguntas en las etiquetas