Instalar SSL Let’s Encrypt usando Lego

SSL / TLS (Secure Socket Layer / Transport Layer Security) son protocolos criptográficos que permiten establecer un canal de comunicación segura en Internet: web, correo, fax y mensajería instantánea

CA (Certificate Authoritative): entidad reconocida a nivel mundial encargada de generar certificados de seguridad para terceros.

CSR (Certificate Signing Request): es una solicitud de firmado de certificado a una CA.

Let’s Encrypt: es una autoridad de certificación (CA) gratuita, automatizada y abierta, disponible para beneficio público. Es un servicio proporcionado por Internet Security Research Group (ISRG).

Proporciona a las personas los certificados digitales que necesitan para habilitar HTTPS (SSL/TLS) en sus sitios web, de forma gratuita, de la manera más fácil de usar posible.

Principales características:

  • Gratis: cualquier persona que posea un dominio puede usar Let’s Encrypt para obtener un certificado de seguridad gratuito.
  • Automático: el proceso de obtención y renovación del certificado se puede realizar de forma automática.
  • Seguro: Let’s Encrypt promueve las mejores prácticas de seguridad TLS y garantizando una protección adecuada de los datos que se intercambian entre un dispositivo y otro.
  • Transparente: todos los certificados emitidos o revocados se registrarán públicamente y estarán disponibles para que cualquiera pueda inspeccionarlos.
  • Abierto: el protocolo de emisión y renovación automática se publica como un estándar abierto que otros pueden adoptar.
  • Cooperativo: al igual que los propios protocolos de Internet subyacentes, Let’s Encrypt es un esfuerzo conjunto para beneficiar a la comunidad, más allá del control de cualquier organización.

Lego: es un cliente/librería Let’s Encrypt que permite obtener y renovar certificados Let’s Encrypt. Las principales características de lego son:

  • Renovar certificados
  • Revocar certificados
  • Robusta implementación de todos los métodos ACME: HTTP (http-01), DNS (dns-01), TLS (tls-alpn-01)
  • Soporta certificados SAM

Para ver todas las características consulte:

Le puede interesar:

Nota: El siguiente procedimiento ha sido ejecutado en la distribución Alpine Linux.

1 – Descargar

Ir a Releases seleccione el binario de acuerdo a su arquitectura, en el momento de escribir este post la última versión es la 4.4.0.

$ curl -LO -# https://github.com/go-acme/lego/releases/download/v4.4.0/lego_v4.4.0_linux_amd64.tar.gz

2 – Descompactar

$ tar xzvf lego_v4.4.0_linux_amd64.tar.gz

3 – Instalar

$ sudo install lego /usr/local/bin/

4 – Ver versión

$ lego -v
lego version 4.4.0 linux/amd64

5 – Obtener ayuda

lego -h
NAME:
   lego - Let's Encrypt client written in Go

USAGE:
   lego [global options] command [command options] [arguments...]

VERSION:
   4.4.0

COMMANDS:
   run      Register an account, then create and install a certificate
   revoke   Revoke a certificate
   renew    Renew a certificate
   dnshelp  Shows additional help for the '--dns' global option
   list     Display certificates and accounts information.
   help, h  Shows a list of commands or help for one command

GLOBAL OPTIONS:
   --domains value, -d value    Add a domain to the process. Can be specified multiple times.
   --server value, -s value     CA hostname (and optionally :port). The server certificate must be trusted in order to avoid further modifications to the client. (default: "https://acme-v02.api.letsencrypt.org/directory")
   --accept-tos, -a             By setting this flag to true you indicate that you accept the current Let's Encrypt terms of service.
   --email value, -m value      Email used for registration and recovery contact.
   --csr value, -c value        Certificate signing request filename, if an external CSR is to be used.
   --eab                        Use External Account Binding for account registration. Requires --kid and --hmac.
   --kid value                  Key identifier from External CA. Used for External Account Binding.
   --hmac value                 MAC key from External CA. Should be in Base64 URL Encoding without padding format. Used for External Account Binding.
   --key-type value, -k value   Key type to use for private keys. Supported: rsa2048, rsa4096, rsa8192, ec256, ec384. (default: "ec256")
   --filename value             (deprecated) Filename of the generated certificate.
   --path value                 Directory to use for storing the data. (default: "/root/.lego") [$LEGO_PATH]
   --http                       Use the HTTP challenge to solve challenges. Can be mixed with other types of challenges.
   --http.port value            Set the port and interface to use for HTTP based challenges to listen on.Supported: interface:port or :port. (default: ":80")
   --http.proxy-header value    Validate against this HTTP header when solving HTTP based challenges behind a reverse proxy. (default: "Host")
   --http.webroot value         Set the webroot folder to use for HTTP based challenges to write directly in a file in .well-known/acme-challenge. This disables the built-in server and expects the given directory to be publicly served with access to .well-known/acme-challenge
   --http.memcached-host value  Set the memcached host(s) to use for HTTP based challenges. Challenges will be written to all specified hosts.
   --tls                        Use the TLS challenge to solve challenges. Can be mixed with other types of challenges.
   --tls.port value             Set the port and interface to use for TLS based challenges to listen on. Supported: interface:port or :port. (default: ":443")
   --dns value                  Solve a DNS challenge using the specified provider. Can be mixed with other types of challenges. Run 'lego dnshelp' for help on usage.
   --dns.disable-cp             By setting this flag to true, disables the need to wait the propagation of the TXT record to all authoritative name servers.
   --dns.resolvers value        Set the resolvers to use for performing recursive DNS queries. Supported: host:port. The default is to use the system resolvers, or Google's DNS resolvers if the system's cannot be determined.
   --http-timeout value         Set the HTTP timeout value to a specific value in seconds. (default: 0)
   --dns-timeout value          Set the DNS timeout value to a specific value in seconds. Used only when performing authoritative name servers queries. (default: 10)
   --pem                        Generate a .pem file by concatenating the .key and .crt files together.
   --cert.timeout value         Set the certificate timeout value to a specific value in seconds. Only used when obtaining certificates. (default: 30)
   --help, -h                   show help
   --version, -v                print the version

6 – Obtener certificado

6.1 – Crear DIR /var/www/letsencrypt

En el DIR /var/www/letsencrypt/.well-known/acme-challenge lego guardará el fichero que nos servirá para validar nuestro domino o sea utilizaremos el desafío/respuesta http-01 para comprobar que el dominio es nuestro, por tanto debemos creamos el DIR con el siguiente comando.

$ sudo mkdir -p /var/www/letsencrypt/.well-known/acme-challenge

6.2 – Creamos un virtual host para el NGINX con la siguiente configuración

server {
    listen 80;
    server_name midominio.com; 
    
    location / {
        return 301 https://$host$request_uri;
    }
    
    location /.well-known/acme-challenge/ {
        root /var/www/letsencrypt/;
    }
}

Creamos un fichero de txt dentro de /var/www/letsencrypt/.well-known/acme-challenge/ para probar la configuración del NGINX

$ sudo echo OK > /var/www/letsencrypt/.well-known/acme-challenge/ok.txt

Recargamos la configuración del NGINX con:

$ sudo service nginx reload

Ahora trate de acceder al fichero ok.txt desde el navegador con http://midominio.com/.well-known/acme-challenge/ok.txt si accedió de manera exisota entonces podemos pasar al siguiente paso que es obtener un certificado de prueba.

6.3 – Obtener certificado usando ambiente de prueba Let’s encrypt

$ sudo lego --server=https://acme-staging-v02.api.letsencrypt.org/directory --accept-tos -m micorreo@midomnio.com -d midominio.com -d www.midominio.comm --http --http.webroot /var/www/letsencrypt --pem --path /etc/lego/ run

Como puede notar en el comando anterior la opcion –server está apuntando al ambiente de prueba Let’s Encrypt.

  • –accept-tos: aceptar los términos del servicio de forma automática.
  • -m: correo electrónico donde se reciben notificaciones Let’s Encrypt por ejemplo: fecha de expiración del certificado.
  • -d: El dominio al cual se se le desea obtener un certificado SSL/TLS (Se puede especificar varias veces para un obtener un certificado SAN: varios dominios en un mismo certificado)
  • –http: Usar el método HTTP para validar el dominio.
  • –http.webroot: DIR donde se guarda los ficheros a usar en el desafío/respuesta, se necesita un servidor web que permita acceder a estos ficheros (Ver 6.2)
  • –pem: Concatena el fichero .key y .crt en un solo fichero.

6.5 – Obtener certificado usando ambiente de producción Let’s encrypt

Una vez ejecutado satisfactoriamente el paso 6.3 procedemos a obtener un certificado válido y real usando el ambiente de producción, tenga en cuenta que para este ambiente existe un límite de validación fallida de 5 fallos por cuenta, por nombre de host y por hora por eso la necesidad de ejecutar el paso 6.3 ya que el ambiente de prueba tiene un límite mayor.

$ sudo lego --accept-tos -m micorreo@midomnio.com -d midominio.com -d www.midominio.comm --http --http.webroot /var/www/letsencrypt --pem --path /etc/lego/ run

Nótese que en el comando anterior quitamos la opción server. También es posible ejecutar determinadas acciones a través de hooks.

6.6 – Listar certificados

$ sudo lego --path /etc/lego/ list

6.7 – Renovar certificados de manera automática

Para renovar los certificados de manera automática cree una tarea en cron o podemos crear un script en /etc/periodic/daily/

#!/bin/sh
lego --accept-tos -m micorreo@midomnio.com -d midominio.com -d www.midominio.comm --http --http.webroot /var/www/letsencrypt --pem --path /etc/lego/ renew --renew-hook="rc-service nginx reload"

Ponga el contenido anterior en un fichero, por ejemplo /etc/periodic/daily/lego y dele permisos de ejecución, ahora todos los días se va a chequear si el certificado de seguridad debe renovarse en caso afirmativo se procede a la renovación del mismo y si la renovación fue exitosa se recarga la configuración del NGINX. Si desea forzar la renovación ejecute el comando anterior pasandole la opción --days N donde N debe ser mayor al número de días en que expira el certificado.

7 – Configurar el NGINX

7.1 – Reemplace o modifique las siguiente directivas

Abrir el fichero principal de configuración del NGINX (/etc/nginx/nginx.conf) y ajuste las siguiente directivas a los valores correspondientes.

ssl_protocols TLSv1.2 TLSv1.3;
ssl_session_timeout 1d;

Addicionar

# HSTS (ngx_http_headers_module is required) (63072000 seconds)
add_header Strict-Transport-Security "max-age=63072000" always;

# OCSP stapling
ssl_stapling on;
ssl_stapling_verify on;

Generar parámetros Diffie Hellman (DH)

openssl dhparam -out dhparam.pem 4096

Si ejecuta la operación anterior en un dispositivo con pocos recursos lo más probable es que tome un largo tiempo, por eso es recomendable que la realice en un CPU de última generación por ejemplo en mi desktop: Intel(R) Core(TM) i7-9700 CPU @ 3.00GHz con 32 GB de RAM tomó aproximadamente 1m en completarse el proceso.

Copie la llave generada para /etc/nginx/ y agregue al NGINX

ssl_dhparam dhparam.pem;

7.2 – Crear configuración para midominio.com

Cree el fichero /etc/nginx/midominio.conf y agregue:

server {
    listen 443 ssl http2;
    
    # SSL configuration
    ssl_certificate  /etc/lego/certificates/midominio.com.cert; 
    ssl_certificate_key /etc/lego/certificates/midominio.com.key; 

    # verify chain of trust of OCSP response using Root CA and Intermediate certs
    ssl_trusted_certificate /etc/letsencrypt/live/midominio.com.pem; 
    
    # Put here you domain
    #
    server_name midominio.com www.midominio.com;
    root /var/www/miproyecto;
    index index.php;
    
    # Max file size useful for file uploading 
    # 
    client_max_body_size 8M;

     location / {
        # This is cool because no php is touched for static content.
        # include the "?$args" part so non-default permalinks doesn't break when
        # using query string
        try_files $uri $uri/ /index.php?$args;
    }
    
    location ~ \.php$ {
    	fastcgi_pass   127.0.0.1:9000;
        fastcgi_index  index.php;
        fastcgi_param  SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include        /etc/nginx/fastcgi_params;
    }
    
    location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
        expires max;
        log_not_found off;
    }
}

7.3 – Recargar la configuración del NGINX

$ sudo service nginx reload

Enlaces de interés

YouTube video

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

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