Linux: Securizar Nginx con Let´s Encrypt en CentOS 8

Después de instalar Nginx en CentOS 8 como os explique en la anterior entrada, en esta ocasión voy a explicaros como podéis securizar vuestro Nginx mediante un certificado SSL generado por Let´s Encrypt.

Prerequisitos

  • Dominio apuntando a una IP pública de vuestra propiedad.
  • En caso de disponer de un Firewall perimetral debéis permitir conexiones al puerto 80 y 443 dirigidas al servidor donde se encuentra alojado Nginx.

Instalación de Certbot

Para poder generar nuestro certificado SSL con Let´s Encrypt en primer lugar tendremos que instalar la herramienta Certbot. Esta herramienta no se encuentra en los repositorios estándar de CentOS 8 por lo que tendremos que descargárnoslo desde su web oficial.

sudo wget -P /usr/local/bin https://dl.eff.org/certbot-auto

Convertimos el script a un fichero del tipo ejecutable.

sudo chmod +x /usr/local/bin/certbot-auto

Generación claves Diffie-Hellman

Diffie-Hellman (DH) para aquellos que no lo conozcáis es un método para generar una clave privada entre dos máquinas conectadas a través de un canal inseguro.

Vamos a generar una clave DH de 2048 bits, para ello ejecutaremos el siguiente comando:

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

Obtención del certificado Let´s Encrypt

En primer lugar crearemos los directorios que nos harán falta y le daremos acceso a Nginx.

sudo mkdir -p /var/lib/letsencrypt/.well-known
sudo chgrp nginx /var/lib/letsencrypt
sudo chmod g+s /var/lib/letsencrypt
sudo mkdir /etc/nginx/snippets

Para evitar duplicar código crearemos dos fragmentos de código los cuales incluiremos en todos los archivos de bloques del servidor Nginx.

El primer fichero lo ubicaremos en la ruta /etc/nginx/snippets/letsencrypt.conf e incluiremos el siguiente código.

location ^~ /.well-known/acme-challenge/ {
  allow all;
  root /var/lib/letsencrypt/;
  default_type "text/plain";
  try_files $uri =404;
}

El segundo fichero lo ubicaremos en la ruta /etc/nginx/snippets/ssl.conf e incluiremos el siguiente código.

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

ssl_session_timeout 1d;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;

ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;

ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 30s;

add_header Strict-Transport-Security "max-age=63072000" always;
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;

Una vez tenemos creados los 2 ficheros los incluiremos en el fichero de configuración de Nginx que podremos encontrar en la ruta /etc/nginx/conf.d/default.conf

server {
  listen 80;
  server_name www.example.com;

  include snippets/letsencrypt.conf;
}

Refrescamos la configuración de Nginx para que se apliquen los cambios.

sudo systemctl reload nginx

Ejecutamos la herramienta certbot para generar nuestro certificado SSL.

sudo /usr/local/bin/certbot-auto certonly --agree-tos --email [email protected] --webroot -w /var/lib/letsencrypt/ -d www.example.com

Si todo ha ido bien nos aparecerá una pantalla como la siguiente.

Una vez generado nuestro certificado SSL lo incluiremos en Nginx. Para ello modificaremos el fichero /etc/nginx/conf.d/default.conf tal y como indico a continuación.

Nota: Tendréis que customizar el fichero cambiando el dominio example.com por el dominio que hayáis usado así como las rutas donde hayais generado el certificado con Let´s Encrypt.

server {
    listen       80;
    server_name  localhost www.example.com;

    include snippets/letsencrypt.conf;
    return 301 https://$host$request_uri;

    #charset koi8-r;
    #access_log  /var/log/nginx/host.access.log  main;

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }

    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

    # proxy the PHP scripts to Apache listening on 127.0.0.1:80
    #
    #location ~ \.php$ {
    #    proxy_pass   http://127.0.0.1;
    #}

    # pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
    #
    #location ~ \.php$ {
    #    root           html;
    #    fastcgi_pass   127.0.0.1:9000;
    #    fastcgi_index  index.php;
    #    fastcgi_param  SCRIPT_FILENAME  /scripts$fastcgi_script_name;
    #    include        fastcgi_params;
    #}

    # deny access to .htaccess files, if Apache's document root
    # concurs with nginx's one
    #
    #location ~ /\.ht {
    #    deny  all;
    #}
}
server {
    listen 443 ssl http2;
    server_name www.example.com;

    ssl_certificate /etc/letsencrypt/live/www.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/www.example.com/privkey.pem;
    ssl_trusted_certificate /etc/letsencrypt/live/www.example.com/chain.pem;
    include snippets/ssl.conf;
    include snippets/letsencrypt.conf;

    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }

    #error_page  404              /404.html;

    # redirect server error pages to the static page /50x.html
    #
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}

Para finalizar reiniciamos el servicio de Nginx

sudo systemctl reload nginx

Y ya podremos acceder a Nginx utilizando https:// con un certificado válido.

Espero os haya servido de utilidad.

Entradas relacionadas

Deja un comentario

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.