Certificados (https)

Este post es una respuesta argumentada a un cliente a razón de que pedía un instalador para una aplicación web, con soporte https. Está aquí pegado en crudo, sin estilo y pendiente de revisar, reescribir y añadir otros servidores web alternativos (nginx, pound, ligthttpd):

Instaladores con soporte https

Hay información que por seguridad debe ir cifrada por la red. Sin embargo, consideramos que es el administrador de sistemas quien debe garantizar la seguridad de la información en los servidores y no el desarrollador/empaquetador. Si echamos un vistazo al instalador de algunos conocidos paquetes web, vemos que no fuerzan una configuración HTTPS, en todo caso la recomiendan, pero es el administrador quien debe velar y garantizar en última instancia la seguridad del sistema. Por ejemplo si instalamos en un sistema Debian o Ubuntu el paquete de phpmyadmin, phpldapadmin, squirrelmail, mediawiki o el horde framework, la configuración por defecto será http.

No es sólo una cuestión de ámbitos (el desarrollador programa, el administrador configura) sino sobretodo una cuestión de limitaciones prácticas. En efecto, configurar virtual hosts ssl conlleva varios inconvenientes que trataremos a continuación. Entre ellos:

  • Se necesita un certificado ssl.
  • Se debe integrar con la configuración que ya exista en el sistema destino.
  • El estado del arte del https presenta ciertos inconvenientes que no es evidente sortear.

Descripción del problema con los name-based virtualhosts

En una conexión HTTPS el servidor recibe una petición SSL en un socket IP:puerto. Entonces se inicia una sesión SSL. La sesión SSL es una transacción separada que tiene lugar antes de que empiece la sesión HTTP. La sesión SSL no incluye una cabecera "Host" (propia del protocolo HTTP) por lo que el servidor web no tiene manera de saber qué virtual host debe usar para la petición actual. Por ello, en la documentación de apache se indica claramente que no se puede tener más de un virtualhost ssl para la misma ip y puerto. En distintas IPs o puertos sí es posible ya que se puede discriminar qué virtual host atienda a ese par IP:puerto, pero no se puede discriminar por "Host", esto es, no es posible más de un virtual host ssl para una misma combinación ip:puerto.

Usar distintas IPs es inviable ya que normalmente no contamos más que con una dirección IP.

Usar distintos puertos es confuso para los usuarios pues tendrán que usar urls del tipo https://dominio.tld:puerto.

Si investigamos el problema más de cerca, la cuestión exacta es que sí pueden existir varios virtualhosts ssl en un servidor pero todos usarán el mismo certificado: el del virtualhost ssl que tenga más prioridad y apache considere "el primero".

Más información sobre la limitación de los name-based virtualhosts:

Descripción del problema con los certificados

Algunos paquetes al ser instalados generan un certificado autofirmado para que puedan funcionar sus opciones ssl (ej: courier-mta). Otros traen un certificado de prueba que se recomienda no usar en producción (ej: apache).

Un certificado digital debe autenticar a una entidad, y debe ser validado por una autoridad certificadora para que existan garantías de que el certificado es correcto y la entidad es quien dice ser. Cuando no ocurre alguno de estos supuestos el navegador web alerta de un fallo de seguridad. Los posibles fallos son:

  • Autoridad certificadora no reconocida
  • El certificado no es válido para el dominio
  • Certificado caducado

Nos centraremos en los dos primeros problemas.

Autoridad certificadora (CA) no reconocida

Usar certificados autofirmados siempre nos dará este problema. Para evitarlo el usuario tiene que importar nuestra CA en su navegador. El problema en general existe para CAs no reconocidas por el navegador.

El certificado no es válido para el dominio

Usemos o no una CA reconocida por el navegador, si el certificado no incluye exactamente el dominio al que queremos conectar obtendremos este mensaje de error.

Como usuarios, este error lo solemos ver a diario y estamos más que acostumbrados a añadir excepciones en el navegador para poder consultar webs tan importantes como puedan ser las relacionadas con servicios online de la Administración del Estado: agencia tributaria, seguridad social...

El problema radica en que el certificado está hecho para un dominio en concreto y se intenta conectar desde otro dominio. Un caso típico es el de los certificados expedidos para *.dominio.tld que contrariamente a lo que se cree no es una manera "estándar" de generar certificados y no es reconocido por todos los navegadores. Otro caso, para el que un wildcard no sirve nunca es tener el mismo nombre de dominio con distintos tld: .coop, .net, .org,....

Este problema se puede manifiestar en dos momentos distintos, a saber:

  • Si tenemos un solo virtualhost ssl en apache y accedemos a él por varios dominios (example.coop, example.net) nos dará el error ya que el certificado típicamente se genera para un único dominio. La solución parcial *.example.coop como hemos dicho anteriormente no es una manera estándar y no funciona en todos los navegadores.
  • Si tenemos varios virtualhosts ssl en apache cada uno con su certificado "en regla", apache nos enviará el certificado del primero de ellos, que puede coincidir o no con el dominio.

Posibles soluciones

Al problema de la CA no reconocida

El problema de "CA no reconocida" es fácil de arreglar con dinero: usar certificados expedidos por Verisign u otra de las "grandes firmas" que por una cantidad económica (nada módica) deposita su confianza en la entidad pagadora y certifica por un periodo limitado para un número limitado de dominios. Una solución menos cara es usar CAs de la economía social, como gandi.net, que ofrece certificados a precios mucho más accesibles pero aún así caros.

Ser uno mismo CA permite tener control total sobre los certificados y si bien no arregla el problema de "CA no reconocida", es posible lidiar con el problema en el manual de uso de la aplicación (por ejemplo, en una página http se puede advertir al usuario de que debe primero importar nuestra CA en el navegador antes de ir a la aplicación https para evitar un mensaje de error).

Otra opción es usar CACert como autoridad certificadora. Esta CA se basa en los principios del software libre y tiene un interesante modelo comunitario de confianza mútua. Además permite generar de manera gratuita tantos certificados como queramos para un número ilimitado de dominios.

Desgraciadamente CACert no es reconocida por algunos navegadores. Sin embargo, consideramos que es la mejor opción actualmente por varios motivos:

  • Apoyo a la comunidad
  • Gratuidad frente a los precios desorbitados de las CA comerciales
  • La interacción del usuario no será peor que si usamos una CA propia (autofirmada)

Al problema de certificado no válido para este dominio

Existe dos formas de sortear este problema.

La primera de ellas es usar una librería SSL que implemente la extensión SNI (Server Name Indication) descrita en el RFC 3546. Ésta extensión del SSL incluye en las cabeceras de la conexión un parámetro que indica el hostname al que estamos conectando y por lo tanto permite al servidor web dirigir la petición al virtualhost en el momento en que se establece la conexión SSL, y no en el momento posterior en que se establece la conexión HTTP encapsulada. Actualmente la extensión SNI la implementa la librería GNUTLS, y afortunadamente existe un módulo para apache.

La segunda posible solución es usar certificados multidominio... una característica de los certificados que no es ampliamente conocida y que las CA convencionales no suelen ofrecer. La solución se basa en incluir en el certificado el dominio para el que ha sido expedido y una lista de dominios alternativos de tal manera que el navegador comprobará el dominio principal y si no coincide buscará la concidencia con la lista de dominios alternativos. Esta característica está implementada en todos los navegadores principales.

Propuesta final

Tras este largo preámbulo sobre https, certificados y autoridades certificadoras, es conveniente recapitular para poder tener una correcta visión del bosque:

Son los administradores de sistema quienes deben configurar https dado la heterogeneidad de las posibles configuraciones:

  • Para no interferir con su configuración actual de apache
  • Porque desconocemos el entorno en que se va a desplegar la aplicación (quizás sea en una red local donde existe confianza y no es necesario https)
  • Porque desconocemos si ya usan certificados, cómo los generan, cómo los usan

Por lo tanto, en todo caso, consideramos suficiente incluir en el manual de instalación información sobre las medidas de seguridad que el administrador del sistema puede tomar (https, cambio de contraseñas, fortaleza de las mismas, etc).

Además, consideramos interesante fomentar el uso de CACert y darle más visibilidad a los problemas y soluciones anteriormente expuestos:

  • Limitación de HTTP encapsulado en SSL
  • Posibilidades de la extensión SNI
  • Posibilidades de los nombres de dominio alternativos en un certificado