lunes, 24 de marzo de 2014

Configurando SSL en nginx

Informe SSL de teowaki.com por sslabs.com


La configuración básica de SSL en nginx es muy sencilla. Lo primero es tener una versión de nginx compilada con el módulo ngx_http_ssl_module. Si usas la versión estandar de tu distribución linux lo más seguro es que ya tenga soporte. Puedes comprobarlo con

$ nginx -V
...
configure arguments: --prefix=/usr/share/nginx ...--with-http_ssl_module ...

En el virtual host indicaremos que vamos a usar SSL y el path de los ficheros de certificados. El proveedor donde contrates el certificado te dirá los pasos para generar estos ficheros. Como ejemplo las instrucciones de Comodo y Linode

server {
  listen        443 ssl;

  ssl_certificate      /path_to/cert.crt;
  ssl_certificate_key  /path_to/cert.key;

}

Simplemente con estas tres líneas ya tenemos nuestro servidor con soporte SSL funcionando. Pero para que tu configuración sea óptima, hay cuantos parámetros más a tener en cuenta.


SPDY

SPDY es un protocolo creado por google para reducir el tiempo de carga de las páginas web. Está soportado en Firefox y Chrome desde hace tiempo y en IE desde la version 11.

Al igual que para tener soporte de SSL, se debe compilar nginx con el módulo correspondiente, ngx_http_spdy_module.

Como me da mucha pereza compilar nginx cada vez que lanzan una nueva versión, tenemos dos alternativas, usar binarios precompilados por Passenger o usar un ppa que incluya ese módulo

He optado por la segunda opción, usando los paquetes de Chris Lea. Están compilados usando la versión de desarrollo de nginx. Aunque es la versión de desarrollo es una versión estable que tambien usan en la web de nginx tal como explican en las FAQ.

La configuración de nuevo es tan simple como añadir spdy en la directiva listen

  listen        443 ssl spdy;


TLS

La configuración por defecto de nginx soporta SSL v3 y TLS versiones 1.0, 1.1 y 1.2.

Todos los navegadores modernos soportan TLS, y SSL v3 es un protocolo antiguo y tiene algunos problemas de seguridad, así que he decidido deshabilitarlo

  # enables TLS protocols, but not SSL which is weak and should no longer be used.
  ssl_protocols TLSv1 TLSv1.1 TLSv1.2;


Strict Transport Security (HSTS)

Si vamos a usar siempre conexión segura con nuestro servidor, añadiendo la cabecera Strict Transport Security, indicamos al navegador que aunque el usuario escriba la URL con http, siempre debe conectarse de forma segura usando https.

Es una buena práctica de seguridad y muchos servicios como Twitter o Paypal añaden esta cabecera en sus respuestas.

  # Remember this setting for 365 days
  add_header Strict-Transport-Security "max-age=31536000; includeSubDomains";

Ciphers

Hay mucha literatura sobre los algoritmos de cifrado que se deberían permitir, en nuestro caso he optado por seguir las recomendaciones de Comodo.

Actualización 23-04-2014: Basado en este post sobre SSL Ciphers, he actualizado la configuración, desactivando RC4.

Tambien he añadido otra directiva para que sea el servidor el que decida que protocolo usar entre los disponibles en lugar de dejar la elección al cliente.

  # Disables all weak ciphers
  ssl_prefer_server_ciphers on;
  ssl_ciphers ALL:!aNULL:!ADH:!eNULL:!LOW:!EXP:RC4+RSA:+HIGH:+MEDIUM;
  ssl_ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS;




OCSP Stapling

Al conectarse el navegador a una web segura, hace una petición adicional a la autoridad certificadora para asegurarse de que el certificado es válido usando OCSP (Online Certificate Status Protocol).

Por medio de OCSP Stapling, se evita esa petición adicional incluyendo la respuesta OCSP en la misma conexión SSL, con lo que reducimos el tiempo de conexión.

Puedes leer más en Cloudfare, en la Wikipedia, y comprobar si tu servidor lo soporta siguiendo las instrucciones de Unmitigated Risk.

  # enable ocsp stapling
  ssl_stapling on;


SSL Session

Por último, siguiendo las recomendaciones de nginx para reducir la carga del procesador habilitamos la caché de sesiones SSL y aumentamos el timeout

  ssl_session_cache    shared:SSL:10m;
  ssl_session_timeout  10m;



Con esta configuración conseguimos una implementación SSL robusta y eficiente. Si conoces algún truco o mejora, por favor, dejalo en los comentarios, gracias!