Certificados SSL gratuitos con Let's Encrypt

April 22, 2016

Desarrolladores  Anuncios 


Si bien ya hace bastante tiempo que Let's Encrypt está dando mucho de qué hablar por ser una nueva entidad que emite certificados SSL (En inglés es Certificate Authority, o CA) gratuitos, nosotros sólo estábamos utilizando sus servicios de forma privada, ya que estaba en un estado beta, pero hace unos días atrás dejó de serlo y sumó aún más sponsors.

Para celebrarlo, decidimos hacer un tutorial para mostrar cómo instalar un certificado en un servidor propio, en particular, utilizando la plataforma de blogging Ghost que es extremadamente sencilla y poderosa.

Manos a la obra

IMPORTANTE: Esta guia está pensada para ser instalada en un servidor CentOS 7 con NGINX, y particularmente enfocados en una instalación existente de Ghost.

1 - Instalando el cliente Let's Encrypt

El primer paso para comenzar a utilizar Let's Encrypt y obtener un certificado SSL es instalar el software letsencrypt en el servidor. En estos momentos, la mejor forma de lograr esto es clonar directamente el paquete desde el repositorio original en GitHub.

Para poder clonar el repositorio, vamos a necesitar git y bc, los instalamos con:

sudo yum -y install git bc

Una práctica común es no ejecutar estos comandos utilizando root, sino un usuario con permisos de sudo.

Una vez instalados estos paquetes, clonamos el repositorio dentro del directorio /opt:

sudo git clone https://github.com/letsencrypt/letsencrypt /opt/letsencrypt

Con esto, ya deberíamos tener una copia local del cliente en el directorio /opt/letsencrypt

2 - Obteniendo un certificado

Let's Encrypt provee una variedad de formas para obtener un certificado SSL a través de varios plugins. A diferencia del plugin de Apache, la mayoría de ellos sólo ayudan a obtener el certificado que deberemos configurar de forma manual en nuestro servidor para poder utilizarlo.

Los plugins que sólo generan un certificado, pero no los instalan, son referidos como "autentificadores" porque son utilizados para autentificar si el certificado debería ser otorgado.

En nuestro caso, utilizaremos el plugin Webroot que funciona creando un archivo especial en el directorio /.well-known dentro de la raiz de documentos del servidor (document root). Dependiendo de nuestra configuración de privacidad, es posible que debamos permitir de forma explícita el acceso a este directorio.

Editamos el archivo de configuración del sitio al que queremos agregar el certificado SSL. En general, durante la instalación de NginX nos recomiendan utilizar la estructura de sitios disponibles y habilitados, en ese caso utilizamos este comando:

sudo vim /etc/nginx/sites-available/example.com.conf

Dentro de ese archivo agregamos dentro del bloque server:

location ~ /.well-known {
    allow all;
}

Importante: En caso de que al ejecutar el comando para solicitar el certificado nos salga un error del tipo no autorizado por recibir un 404, lo más probable es que debamos agregar, dentro de ese bloque location, una línea root declarando de forma explícita dónde está la raiz de documentos del servidor.

Guardamos, salimos, y reiniciamos NginX:

sudo systemctl restart nginx

Ahora que tenemos nuestro webroot-path, podemos utilizar el plugin Webroot para solicitar un certificado SSL con los siguientes comandos. Se puede solicitar certificados para múltiples dominios utilizando el comando -d los nombres.

Recuerda reemplazar el valor de los parámetros webroot-path por el que corresponda, y agregar los sitios con el comando -d.

cd /opt/letsencrypt
./letsencrypt-auto certonly -a webroot --webroot-path=/usr/share/nginx/html/example.com -d example.com -d www.example.com

Luego de que el comando letsencrypt inicie, se solicitará cierta información al usuario. La información exacta que se solicite puede variar de acuerdo a si se ha utilizado el comando antes o no.

Si luego de ingresar la información solicitada, todo funcionó de forma correcta, se debería ver un mensaje que contiene una sección similar a esta:

Congratulations! Your certificate and chain have been saved at /etc/letsencrypt/live/example.com/fullchain.pem. Your cert will expire on 2016-04-24. To obtain a new version of the certificate in the future, simply run Let's Encrypt again.

Esta es la sección más importante, nos informa en dónde y qué nombre contiene nuestro certificado y su fecha de caducidad.

Para incrementar aún más la seguridad, también deberíamos generar un grupo Diffie-Hellman fuerte. Para crear un grupo de 2048-bits, ejecutamos el comando:

sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048

Esto puede tomar un rato, pero una vez terminado, deberíamos tener un grupo DH fuerte en /etc/ssl/certs/dhparam.pem.

3 - Configurar renovado automático de certificados

Los certificados emitidos por Let's Encrypt son válidos por 90 días, pero es recomendable que sean renovados cada 60 días para permitir un margen de error. Por ahora, el renovado automático de certificado no está disponible como una característica del cliente en si mismo, pero se pueden renovar los certificados de forma manual al ejecutar el cliente Let's Encrypt con la opción renew.

Para iniciar el proceso de renovación de todos los dominios intalados, ejecutamos el comando:

/opt/letsencrypt/letsencrypt-auto renew

Como recién hemos instalado el certificado, el comando sólo va a controlar la fecha de expiración e imprimirá un mensaje informando que el certificado no debe ser renovado todavía.

En caso que hayamos solicitado un certificado con múltiples dominios, sólo el dominio base será mostrado en la salida, pero esto incluirá a todos los dominios incluidos en este certificado.

Una forma práctica de asegurarnos que los certificados sean actualizados automáticamente, es creando un cron job que ejecute el comando de renovación automática por nosotros. Ya que el proceso de renovación primero controla que el certificado tenga al menos 30 días de antiguedad, es seguro crear un proceso que se ejecute cada semana, o cada dia.

Como ejemplo, vamos a crear un comando en la crontab del usuario root, ejecutamos:

sudo crontab -e

Y agregamos las siguientes lineas:

30 2 * * 1 /opt/letsencrypt/letsencrypt-auto renew >> /var/log/domain-renew.log
35 2 * * 1 /usr/bin/systemctl reload nginx

Guardamos y salimos. Esto creará dos comandos, uno que se ejecutará cada lunes a las 2:30 am y renovará los certificados, y uno que se ejecutará 5 minutos después reiniciando NginX. El resultado de esta operación será guardado en /var/log/domain-renew.log.

4 - Configurar TLS/SSL en el servidor web (NginX)

Ahora que tenemos todo listo, sólo falta configurar el servidor web para que utilice el certificado SSL. Para eso, editamos el archivo .conf que tiene el bloque de servidor que vamos a usar, en nuestro caso:

sudo vim /etc/nginx/sites-available/example.com.conf

Al final del bloque server que existe, creamos uno nuevo pero que esté escuchando en el puerto 443 con lo siguiente:

server {
    listen 443 ssl;
    server_name example.com www.example.com;

    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;
    ssl_dhparam /etc/ssl/certs/dhparam.pem;
    ssl_ciphers 'ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA';
    ssl_session_timeout 1d;
    ssl_session_cache shared:SSL:50m;
    ssl_stapling on;
    ssl_stapling_verify on;
    add_header Strict-Transport-Security max-age=15768000;

    location / {
        proxy_set_header   X-Real-IP $remote_addr;
        proxy_set_header   Host      $http_host;
        proxy_pass         http://localhost:2368;
    }

    location ~ /.well-known/ {
        allow all;
        root /usr/share/nginx/html/example.com/;
    }
}

En nuestro bloque server anterior, reemplazamos lo que teníamos por:

server {
    listen 80;
    server_name example.com www.example.com;
    return 301 https://$host$request_uri;
}

Esto hará que todas las peticiones al puerto 80 sean redireccionadas al 443. Guardamos el archivo y reniciamos NginX.

sudo service nginx reload

Controlamos que todo funciona entrando en nuestro sitio, y deberíamos ser redirigidos a la versión HTTPS del mismo. ¡Voilá!

Palabras finales

Con esta nueva iniciativa, podemos expandir la seguridad de todos nuestros sitios de forma gratuita, y también mejorar nuestra posición SEO.

Como siempre, si tenés una idea o un proyecto que está dando vueltas en tu cabeza, ya sea diseño, un sitio, o una aplicación móvil, no dudes en ponerte en contacto con nosotros a contacto@cign.io.

¡Hasta la próxima!