Configurar HTTPS en nginx en Ubuntu 16.04

Configurar HTTPS en nginx en Ubuntu 16.04

SSL/TLS puede ser una tecnología engañosamente sencilla pues es fácil de desplegar, pero no es fácil de desplegar correctamente. Las configuraciones HTTPS por defecto para software en el servidor como OpenSSL a menudo soportan estándares criptográficos débiles que pueden poner en riesgo a los usuarios.

Configurando HTTPS en nginx

Antes de hacer cambios a la configuración debemos usar openssl para generar un archivo dhparams.pem, por defecto algunos servidores suelen utilizar parámetros de intercambio Diffie-Hellman muy débiles para Forward Secrecy. Con Forward Secrecy, si un atacante llegase a obtener la clave privada del servidor, no podría descifrar las comunicaciones pasadas; la clave privada solo es usada para el saludo DH inicial lo que no revela la clave pre-master.

Podemos generar los parámetros DH con el siguiente comando, y usamos -dsaparam para acelerar el proceso. Utilizar parámetros como-DSA para DH son igualmente seguros y no hay una ventaja significativa al usar números “primos fuertes”.

openssl dhparam -dsaparam -out /etc/nginx/dhparams.pem 4096

Aunque si queremos sentirnos súper seguros usaríamos este comando en su lugar (podría tomar mucho tiempo en generar):

openssl dhparam -out /etc/nginx/dhparams.pem 4096

Usando el Generador de Configuración SSL de Mozilla

Mozilla SSL Configuration Generator

Mozilla ofrece un Generador de Configuración SSL que resulta útil para obtener la suite criptográfica recomendada (perfil Modern) o una más compatible (perfiles Intermediate y Old) para las distintas versiones del servidor web y OpenSSL. Las configuraciones menos modernas son también menos seguras pero ofrecen una mejor compatibilidad con navegadores y sistemas operativos antiguos.

server {
    listen 80 default_server;
    listen [::]:80 default_server;

    # Redirect all HTTP requests to HTTPS with a 301 Moved Permanently response.
    return 301 https://$host$request_uri;
}

El primer segmento server simplemente redirige las solicitudes HTTP a HTTPS con una respuesta ‘301 Moved Permanently’

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;

Se configura el servidor para escuchar en el puerto 443, el parámetro http2 configura el puerto para aceptar conexiones HTTP/2, aunque la especificación de HTTP/2 no requiere cifrado los navegadores que lo soportan sí.

    # certs sent to the client in SERVER HELLO are concatenated in ssl_certificate
    ssl_certificate /etc/nginx/ssl/[mi-dominio.com]/chain.pem
    ssl_certificate_key /etc/nginx/ssl/[mi-dominio.com]/privkey.pem

    # certs sent to the client in SERVER HELLO are concatenated in ssl_certificate
    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:50m;
    ssl_session_tickets off;

    # Diffie-Hellman parameter for DHE ciphersuites
    ssl_dhparam /etc/nginx/dhparams.pem;

Indicamos a nginx la ubicación del certificado SSL y la clave privada, además configuramos los parámetros de la sesión SSL y los parámetros para Diffie-Hellman.

    # modern configuration. tweak to your needs.
    ssl_protocols TLSv1.2;
    ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
    ssl_prefer_server_ciphers on;

Para servicios que no necesitan compatibilidad hacia atrás, la configuración moderna recomendada solo utiliza TLSv1.2, se especifican los cifrados habilitados y que se prefieran los cifrados del servidor por encima de los cifrados del cliente.

    # HSTS (ngx_http_headers_module is required) (15768000 seconds = 6 months)
    add_header Strict-Transport-Security max-age=15768000;

Configuramos HSTS con un valor de 6 meses, esto garantiza que después de la primera visita el usuario siempre va a utilizar HTTPS para conectarse al servidor.

    # OCSP Stapling ---
    # fetch OCSP records from URL in ssl_certificate and cache them
    ssl_stapling on;
    ssl_stapling_verify on;

    ## verify chain of trust of OCSP response using Root CA and Intermediate certs
    ssl_trusted_certificate /etc/nginx/ssl/[mi-dominio.com]/fullchain.pem;

    resolver 8.8.8.8;
}

OCSP stapling, es una alternativa al Protocolo de Estado de Certificados Online para verificar el estado de revocación de un certificado digital X.509, podemos verificar el estado de OCSP con OpenSSL:

echo QUIT | openssl s_client -connect mi-dominio.com:443 -status 2> /dev/null | grep -A 17 'OCSP response:' | grep -B 17 'Next Update'

OpenSSL OCSP

Finalmente solo queda recargar nginx con la nueva configuración:

sudo nginx -t && sudo systemctl reload nginx.service

Si todo funciona correctamente al navegar a http://[dominio.com] nos redigiría a https://[dominio.com] automáticamente.

Verificando la Configuración

Usando Qualys SSL Labs

SSL Labs ofrece un servicio que realiza un análisis de la configuración SSL de cualquier servidor web público en Internet.

Qualys SSL Server Test

La calificación está determinada por la seguridad de la configuración del servidor, la validez del certificado, la detección de vulnerabilidades conocidas, uso de HSTS, etc.

Usando CipherScan

CipherScan es una herramienta simple para probar el cifrado en un objetivo dado, también extrae información de algunos certificados, opciones TLS, Engrapado OCSP y más. Está diseñado para entornos tipo unix y viene con su propia compilación de OpenSSL para Linux/64 y Darwin/64.

Una prueba básica sería:

./cipherscan [mi-dominio.com]

Y nos mostraría un resultado similar al siguiente, con información de la configuración de seguridad del servidor:

CipherScan

La motivación de CipherScan es ayudar a los administradores a configurar TLS, para ayudar a esto también incluye el script analize.py que compara los resultados de un escaneo con las guías de despliegue de TLS de Mozilla y muestra los cambios recomendados para cada nivel de seguridad:

./analyze.py -t [mi-dominio.com]

CipherScan 'analize.py'

En este caso el servidor coincide con el perfil de configuración Moderno.

¿Conclusión?

Aunque deberíamos tener un muy buen soporte SSL, la carrera armamentista nunca termina. Nuevas amenazas y vulnerabilidades pueden aparecer en cualquier momento, y avances tecnológicos eventualmente hacen que la mejor configuración se vuelva inadecuada. En temas de Seguridad la vigilancia constante no es sólo una virtud, sino un requisito de supervivencia.


Also published on Medium.

Deja una respuesta: