Aprende a proteger Nginx con Let’s Encrypt en CentOS 7

04 Abr 2017

Aprende a proteger Nginx con Let’s Encrypt en CentOS 7

Sistemas

El uso de certificados SSL es una práctica muy utilizada en portales web donde la información debe ir encriptado para evitar problemas de seguridad. En el mercado, nos podemos encontrar un gran número de autoridades certificadoras que nos proporcionan este tipo de certificados de seguridad, aunque la mayoría de ellos son de pago. Hoy lo que haremos, será explicaros el proceso para generar un SSL gratuito para utilizarlo en vuestro servidor Nginx. Para ello utilizaremos Let’s Encrypt.

Para aquellos que no hayan escuchado hablar sobre Let’s Encrypt, decir que se trata de una autoridad certificadora que proporciona una manera sencilla de obtener e instalar certificados TLS/SSL gratuitos. Si te interesa utilizar este tipo de certificados, sigue leyendo y descubre cómo hacerlo.

Prerrequisitos

Antes de empezar con este tutorial, será necesario que conozcas algunos requisitos previos.

  • Disponer de un servidor CentOS 7 con usuario root que tenga todos los privilegios.
  • Administrar el nombre del dominio sobre el que deseas utilizar el certificado.
  • Asegurarse de que la zona de DNS del dominio cuenta con un registro A que apunte a la dirección IP pública del servidor. Esto es necesario, ya que Let’s Encrypt lo utilizará para realizar la validación.

Una vez que cumplamos estos requisitos, será el momento de instalar el software del cliente Let’s Encrypt.

Paso 1 – Instalar el software de Let’s Encrypt

Para obtener el certificado SSL, lo primero será instalar el software que nos permitirá hacer esto en nuestra máquina. La mejor forma de hacerlo es a través del repositorio EPEL. Para ello, lo primero será habilitar el acceso a ese repositorio ejecutando lo siguiente:

sudo yum install epel-release

Una vez habilitado, podemos obtener el paquete escribiendo:

sudo yum install certbot

De esta forma, el cliente certbot estará instalado y listo para ser utilizado.

Paso 2 – Obtener el certificado

Let’s Encrypt ofrece varias opciones para crear el certificado a través de varios complementos. Nosotros nos centraremos en el uso del plugin Webroot.

¿Cómo utilizamos el plugin Webroot?

Este complemento funciona colocando un archivo especial en el directorio /.well-known dentro de nuestro raíz. Dependiendo de nuestra configuración, puede ser que sea necesario darles permisos para que Let’s Encrypt pueda acceder a él.

Si no tiene instalado Nginx, lo puede hacer ahora ejecutando la siguiente instrucción.

sudo yum install nginx

Para asegurarnos de que ese directorio estará accesible para Let’s Encrypt, vamos a realizar un cambio rápido en la configuración predeterminada de Nginx. Si estamos utilizando la configuración predeterminada, lo que haremos será crear un archivo que le pondremos de nombre le-well-known.conf. Lo editaremos con el siguiente comando.

sudo vi /etc/nginx/default.d/le-well-known.conf

A continuación, en su interior colocaremos las siguientes líneas:

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

Guardaremos y saldremos de la edición. También chequearemos que no hemos cometido ningún tipo de error en la sintaxis utilizada. Lo podemos revisar ejecutando:

sudo nginx -t

Si no hay ningún error, reiniciaremos el servidor Nginx con esta instrucción.

sudo systemctl restart nginx

También será necesario que nos aseguremos de que están abiertos los puertos 80 y 443. Si estamos utilizando un cortafuegos, podemos abrirlos ejecutando los siguientes comandos:

sudo firewall-cmd –add-service=http
sudo firewall-cmd –add-service=https
sudo firewall-cmd –runtime-to-permanent

Si por el contrario, estamos utilizando IP Tables, las instrucciones que deberemos utilizar dependerán de nuestras actuales reglas. En el caso de estar utilizando reglas básicas, con estas dos instrucciones deberían ser suficientes.

sudo iptables -I INPUT -p tcp -m tcp –dport 80 -j ACCEPT
sudo iptables -I INPUT -p tcp -m tcp –dport 443 -j ACCEPT

Una vez realizados los anteriores pasos, ya podremos utilizar el plugins Webroot para solicitar el certificado SSL utilizando el siguiente comando.

sudo certbot certonly -a webroot –webroot-path=/usr/share/nginx/html -d example.com -d www.example.com

Hay que utilizar la opción –d para indicar el nombre del dominio sobre el que se instalará el certificado. En caso de utilizar más de un dominio, habrá que indicarlo de forma separada incluyendo delante de cada uno de ellos esta opción. También hay que tener en cuenta, que un dominio con y sin www es considerado diferente.

Cuando Certbot se inicie, nos pedirá una serie de datos. Esto dependerá de si ya lo hemos utilizado anteriormente o si es la primera vez. Nosotros supondremos que nunca antes lo habíamos utilizado. De esta forma, en la primera pantalla que nos aparecerá, introduciremos nuestro correo electrónico. Aquí será donde recibamos los avisos y recuperación de claves perdidas.

Luego debemos aceptar los términos de Let’s Encrypt.

Si todo ha ido bien, deberíamos ver algo parecido a lo siguiente.

IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at
 /etc/letsencrypt/live/example.com/fullchain.pem. Your
 cert will expire on 2017-01-10. To obtain a new version of the
 certificate in the future, simply run Let's Encrypt again.
 - If you lose your account credentials, you can recover through
 e-mails sent to sammy@digitalocean.com
 - Your account credentials have been saved in your Let's Encrypt
 configuration directory at /etc/letsencrypt. You should make a
 secure backup of this folder now. This configuration directory will
 also contain certificates and private keys obtained by Let's
 Encrypt so making regular backups of this folder is ideal.
 - If like Let's Encrypt, please consider supporting our work by:

Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
 Donating to EFF: https://eff.org/donate-le

En el anterior mensaje, podremos ver la fecha de expiración y la ruta de nuestro SSL.

Archivos del certificado

Una vez que hemos generado el certificado, deberíamos tener los siguientes archivos:

  • pem: Certificado de nuestro dominio
  • pem: Certificado de Let’s Encrypt
  • pem: Una combinación de los dos anteriores.
  • pem: Clave privada de nuestro certificado.

Generar un grupo fuerte Diffie-Hellman

Para aumentar aún más la seguridad, también es necesario generar un grupo Diffie-Hellman fuerte. Para generar un grupo de 2048 bits, deberemos ejecutar los siguiente:

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

Paso 3 – Configurar TLS/SSL en el servidor Nginx

El siguiente paso, será editar la configuración de Nginx para usar los archivos del certificado que hemos generado con Let’s Encrypt. Para ello, crearemos un nuevo bloque en el archivo de configuración en el que indicaremos que utiliza SSL/TLS y escucha en  el puerto 443.

Por defecto, este nuevo bloque se puede colocar en /etc/nginx/conf.d. Para ello, crearemos un nuevo archivo al que llamaremos ssl.conf. Una vez creado, lo editaremos y en su interior colocaremos el siguiente código.

server {
 listen 443 http2 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;

########################################################################
 # from https://cipherli.st/ #
 # and https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html #
 ########################################################################

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
 ssl_prefer_server_ciphers on;
 ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
 ssl_ecdh_curve secp384r1;
 ssl_session_cache shared:SSL:10m;
 ssl_session_tickets off;
 ssl_stapling on;
 ssl_stapling_verify on;
 resolver 8.8.8.8 8.8.4.4 valid=300s;
 resolver_timeout 5s;
 # Disable preloading HSTS for now. You can use the commented out header line that includes
 # the "preload" directive if you understand the implications.
 #add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
 add_header Strict-Transport-Security "max-age=63072000; includeSubdomains";
 add_header X-Frame-Options DENY;
 add_header X-Content-Type-Options nosniff;

##################################
 # END https://cipherli.st/ BLOCK #
 ##################################

ssl_dhparam /etc/ssl/certs/dhparam.pem;

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

# The rest of your server block
 root /usr/share/nginx/html;
 index index.html index.htm;

location / {
 # First attempt to serve request as file, then
 # as directory, then fall back to displaying a 404.
 try_files $uri $uri/ =404;
 }
}

En el código anterior, deberemos cambiar el nombre del dominio example.com por el que estemos utilizando. Guardamos y cerramos el archivo.

Lo siguiente será configurar Nginx para redirigir las peticiones HTTP del puerto 80 hacia HTTPS en el puerto 443, recuerda que si además tienes activo HTTP2 todo irá más rápido. Para ello, deberemos crear un archivo, al que llamaremos ssl-redirect.conf, dentro de la ruta /etc/nginx/default.d. Lo abriremos y en su interior pegaremos lo siguiente:

return 301 https://$host$request_uri;

Guardamos los cambios y salimos. Comprobamos que todo está correcto

sudo nginx -t

Y si no hay errores, reiniciamos Nginx.

sudo systemctl restart nginx

Una vez hecho todo esto, el certificado ya está activo. Solo quedaría probar que funciona correctamente, visitando nuestro dominio con el protocolo HTTPS desde un navegador web.

Paso 4 – Configurar la renovación automática

Los certificados que se genera, son válidos para 90 días, aunque se recomiendan que sean renovados cada 60 días por si ocurriera cualquier error. Para renovar todos nuestros certificados, tendremos que ejecutar los siguiente:

sudo certbot renew

Si queremos asegurarnos de que nuestros certificados se renuevan automáticamente, lo más sencillo y cómodo es programar una cron que se ejecute cada día o cada semana. De esta forma, si hubiera algún certificado a punto de vencer se renovaría. Si no fuera así, no pasaría nada.

Para ello, editaremos el crontab para crear una nueva tarea que se encargue de ejecutar este comando por el usuario root.

30 2 * * 1 /usr/bin/certbot renew >> /var/log/le-renew.log
35 2 * * 1 /usr/bin/systemctl reload nginx

Guarda los cambios y cierra el archive. De esta forma, se ejecutará la orden de renovación todos los lunes a las 2:30 horas de la mañana.