Lenta pero inexorablemente el protocolo HTTPS se está convirtiendo en un nuevo estándar mínimo a cumplir para la mayoría de webs. Los principales navegadores y buscadores como Firefox o Chrome ya vienen anunciándolo hace tiempo. Se trata de una evolución que no sólo afectará a webs de medios de pago, sino también a blogs, periódicos online, etc…
Por suerte, actualmente contamos con Let’s Encrypt como Autoridad Certificadora abierta, gratuita y fruto del trabajo conjunto de organizaciones como Mozilla, Cisco o la EFF.
El proceso de certificación SSL con Let’s Encrypt constará principalmente de dos fases:
- Validación (challenge) contra la CA de Let’s Encrypt para verificar que somos los propietarios del dominio del que se va a generar un certificado SSL.
- Instalación del certificado en el servidor web Apache.
Posteriormente, también debemos tener en cuenta cómo renovar nuestro certificado.
Instalación de Certbot
La gestión de certificados de Let’s Encrypt se realiza con un programa llamado certbot. Dada la gran cantidad de distribuciones y casuísticas posibles, os recomiendo visitar la web de certbot y seguir los pasos de instalación correspondientes en cada caso.
Para el caso que nos ocupa, en Debian o derivada instalaremos con:
apt-get install python-certbot-apache
Validación y generación del certificado
A la hora de generar el certificado SSL es importante tener en cuenta el nombre de nuestro dominio con y sin www. Por motivos de seguridad tendremos que aceptar que la IP desde donde se está realizando el proceso de generación del certificado sea registrada. Procederemos a crear nuestro certificado con:
[root@jota-pc ~]# certbot certonly -d www.example.com -d example.com --manual Saving debug log to /var/log/letsencrypt/letsencrypt.log Obtaining a new certificate Performing the following challenges: http-01 challenge for www.example.com http-01 challenge for example.com ------------------------------------------------------------------------------- NOTE: The IP of this machine will be publicly logged as having requested this certificate. If you're running certbot in manual mode on a machine that is not your server, please ensure you're okay with that. Are you OK with your IP being logged? ------------------------------------------------------------------------------- (Y)es/(N)o: y -------------------------------------------------------------------------------
Una vez aceptado, tendremos que proceder a preparar nuestro entorno para la validación (challenge) que hará Let’s Encrypt de nuestro sitio web. El objetivo es probar que la persona que está intentando generar el certificado del dominio es la propietaria del sitio web.
Ya que estamos generando el certificado para nuestro dominio con y sin www, tendremos que realizar una verificación en cada caso (dos en total). Tendremos que crear un determinado FICHERO con el contenido STRING en la carpeta .well-known/acme-challenge
de nuestro DocumentRoot (ej.: para un DocumentRoot /var/www/example
, sería /var/www/example/.well-known/acme-challenge
). Si no existe dicho directorio, lo creamos. En condiciones reales FICHERO y STRING son una serie de cadenas alfanuméricas:
Make sure your web server displays the following content at http://www.example.com/.well-known/acme-challenge/FICHERO before continuing: STRING ... ------------------------------------------------------------------------------- Press Enter to Continue
Después, la siguiente verificación para el dominio sin www. Tendremos que crear otro FICHERO con el contenido STRING distintos del anterior:
Make sure your web server displays the following content at http://example.com/.well-known/acme-challenge/FICHERO before continuing: STRING ... ------------------------------------------------------------------------------- Press Enter to Continue
Una vez listo y presionado Enter
por segunda vez, se procede a la verificación:
Waiting for verification...
Si todo va bien deberías ver dos líneas en tu log de acceso access_log
donde Let’s Encrypt intenta validar. Haciendo un grep "acme" /var/log/apache2
/access_log:
outbound1.letsencrypt.org - - [09/Sep/2017:23:05:17 +0200] "GET /.well-known/acme-challenge/FICHERO HTTP/1.1" 200 430 "-" "Mozilla/5.0 (compatible; Let's Encrypt validation server; +https://www.letsencrypt.org)" outbound1.letsencrypt.org - - [09/Sep/2017:23:05:17 +0200] "GET /.well-known/acme-challenge/FICHERO HTTP/1.1" 200 430 "-" "Mozilla/5.0 (compatible; Let's Encrypt validation server; +https://www.letsencrypt.org)"
Pasada la verificación, tendremos los ficheros de certificado, clave privada y cadena en /etc/letsencrypt/live/www.example.com
[root@jota-pc www.example.com]# pwd /etc/letsencrypt/live/www.example.com [root@jota-pc www.example.com]# ls -l total 4 lrwxrwxrwx 1 root root 45 Nov 19 01:02 cert.pem -> ../../archive/www.example.com/cert2.pem lrwxrwxrwx 1 root root 46 Nov 19 01:02 chain.pem -> ../../archive/www.example.com/chain2.pem lrwxrwxrwx 1 root root 50 Nov 19 01:02 fullchain.pem -> ../../archive/www.example.com/fullchain2.pem lrwxrwxrwx 1 root root 48 Nov 19 01:02 privkey.pem -> ../../archive/www.example.com/privkey2.pem -rw-r--r-- 1 root root 543 Sep 9 23:04 README
Copiamos los ficheros en el directorio de Apache que corresponda y configuramos las directivas correspondientes en nuestro VirtualHost HTTPS, por ejemplo:
SSLCertificateFile /opt/apache/certs/example.com/cert.pem SSLCertificateKeyFile /opt/apache/certs/example.com/privkey.pem SSLCertificateChainFile /opt/apache/certs/example.com/chain.pem
Securizamos el directorio donde guardamos certificados:
chmod -R 400 /opt/apache/certs
Reiniciamos Apache:
systemctl restart apache2.service
Configuraciones adicionales
Para nuestra primera puesta en marcha de HTTPS tendremos que hacer modificaciones adicionales:
- Para nuestro blog de WordPress, en el fichero
wp-config.php
modificamos las variablesWP_SITEURL
yWP_HOME
:define('WP_SITEURL', 'https://www.example.com'); define('WP_HOME', 'https://www.example.com');
- Si queremos que todo el tráfico HTTP se redirija a HTTPS, ponemos en nuestro VirtualHost HTTP la siguiente directiva:
Redirect permanent / https://www.example.com/
- Opcionalmente, podemos incluir también HSTS sólo en caso de que toda nuestra web funcione sin problemas por HTTPS:
# HSTS (mod_headers is required) (604800 seconds = 1 week) Header always set Strict-Transport-Security "max-age=604800"
- Debemos actualizar la sección de nuestro
robots.txt
donde se especifica la localización del sitemap. Sustituimos:Sitemap: http://www.example.com/sitemap.xml
Por:
Sitemap: https://www.example.com/sitemap.xml
- Posiblemente tengamos links que sigan apuntando a direcciones HTTP. Las imágenes suelen ser un clásico en este sentido. Tendremos que sustituir dichos links antiguos por los nuevos HTTPS. Un plugin que te será de gran ayuda es Better Search Replace. Tendrás que sustituir, por ejemplo, todas las ocurrencias de http://www.example.com por https://www.example.com
- Si utilizas Google Webmaster Tools tendrás que añadir dos nuevas propiedades (una para https://example.com y otra para https://www.example.com) para que Google sepa de la existencia de tu sitio con protocolo HTTPS.
Renovación del certificado
Actualmente el certificado de Let’s Encrypt tiene una validez de 90 días. Es recomendable renovarlo unos días antes de que caduque en caso de que pudieran presentarse imprevistos de último momento.
Podemos comprobar el período de validez de nuestros certificados con certbot certificates
:
[root@jota-pc ~]# certbot certificates Saving debug log to /var/log/letsencrypt/letsencrypt.log ------------------------------------------------------------------------------- Found the following certs: Certificate Name: www.example.com Domains: www.example.com example.com Expiry Date: 2017-12-08 20:05:00+00:00 (VALID: 19 days) Certificate Path: /etc/letsencrypt/live/www.example.com/fullchain.pem Private Key Path: /etc/letsencrypt/live/www.example.com/privkey.pem -------------------------------------------------------------------------------
Cuando se aproxime la fecha de caducidad, podemos renovar con:
[root@jota-pc ~]# certbot certonly -d www.example.com -d example.com --manual Saving debug log to /var/log/letsencrypt/letsencrypt.log Cert is due for renewal, auto-renewing... Renewing an existing certificate Performing the following challenges: http-01 challenge for www.example.com http-01 challenge for example.com ------------------------------------------------------------------------------- NOTE: The IP of this machine will be publicly logged as having requested this certificate. If you're running certbot in manual mode on a machine that is not your server, please ensure you're okay with that. Are you OK with your IP being logged? ------------------------------------------------------------------------------- (Y)es/(N)o:
Seguimos los mismos pasos que al generar el certificado SSL por primera vez.
Si todo va bien:
Cleaning up challenges Generating key (2048 bits): /etc/letsencrypt/keys/0001_key-certbot.pem Creating CSR: /etc/letsencrypt/csr/0001_csr-certbot.pem IMPORTANT NOTES: - Congratulations! Your certificate and chain have been saved at /etc/letsencrypt/live/www.example.com/fullchain.pem. Your cert will expire on 2018-02-16. To obtain a new or tweaked version of this certificate in the future, simply run certbot again. To non-interactively renew *all* of your certificates, run "certbot renew" - If you like Certbot, please consider supporting our work by: Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate Donating to EFF: https://eff.org/donate-le
El certificado estará en la misma localización que antes (/etc/letsencrypt/live/www.example.com
) y podremos actualizarlo en nuestro Apache.
Si comprobamos con certbot certificates
veremos la nueva fecha de expiración:
[root@jota-pc ~]# certbot certificates Saving debug log to /var/log/letsencrypt/letsencrypt.log ------------------------------------------------------------------------------- Found the following certs: Certificate Name: www.example.com Domains: www.example.com example.com Expiry Date: 2018-02-16 23:03:16+00:00 (VALID: 89 days) Certificate Path: /etc/letsencrypt/live/www.example.com/fullchain.pem Private Key Path: /etc/letsencrypt/live/www.example.com/privkey.pem -------------------------------------------------------------------------------
Recordad que para configuraciones TLS/SSL es muy útil la herramienta Mozilla SSL Configuration Generator
Para todo lo demás, la ayuda de certbot es nuestra amiga:
[root@jota-pc ~]# certbot --help certbot [SUBCOMMAND] [options] [-d DOMAIN] [-d DOMAIN] ... Certbot can obtain and install HTTPS/TLS/SSL certificates. By default, it will attempt to use a webserver both for obtaining and installing the cert. The most common SUBCOMMANDS and flags are: obtain, install, and renew certificates: (default) run Obtain & install a cert in your current webserver certonly Obtain or renew a cert, but do not install it renew Renew all previously obtained certs that are near expiry -d DOMAINS Comma-separated list of domains to obtain a cert for (the cerbot apache plugin is not installed) --standalone Run a standalone webserver for authentication (the certbot nginx plugin is not installed) --webroot Place files in a server's webroot folder for authentication --manual Obtain certs interactively, or using shell script hooks -n Run non-interactively --test-cert Obtain a test cert from a staging server --dry-run Test "renew" or "certonly" without saving any certs to disk manage certificates: certificates Display information about certs you have from Certbot revoke Revoke a certificate (supply --cert-path) delete Delete a certificate manage your account with Let's Encrypt: register Create a Let's Encrypt ACME account --agree-tos Agree to the ACME server's Subscriber Agreement -m EMAIL Email address for important account notifications More detailed help: -h, --help [TOPIC] print this message, or detailed help on a topic; the available TOPICS are: all, automation, commands, paths, security, testing, or any of the subcommands or plugins (certonly, renew, install, register, nginx, apache, standalone, webroot, etc.)
😉