HTTPS con Let’s Encrypt, ¡protege tus comunicaciones!

Pregunta, ¿quién no tiene hoy en día algún sistema en casa abierto al exterior para acceder a documentos, música, películas, sistema de domótica? Dos puntos clave tenemos aquí, primero que si dejamos un sistema abierto al exterior (esto es, accesible cuando no estoy conectado al WIFI de casa, si no a otras redes como la del trabajo o la de datos del móvil) será vulnerable si no lo protegemos pero, segundo, si no lo dejamos abierto al exterior no podremos acceder a todo lo que ahí tenemos. Conclusión, debemos protegerlo de alguna manera. Ya hemos hablado con anterioridad de cómo proteger aplicaciones web, configurar un router o, directamente, como atacar sistemas IoT. Hoy lo que vamos a ver es cómo proteger lo máximo posible las comunicaciones con todos esos dispositivos, empleando SSL/TLS.

SSL/TLS

¿Qué es el SSL/TLS? Veamos un ejemplo sencillo. Si yo quiero contar un secreto a una persona, no lo grito a los cuatro vientos, me acerco a ella y se lo cuento al oído. El hecho de hablar bajo hace que sea difícil que otros se enteren pero, ¿qué pasa si alguien utiliza un sistema de los que usan los espías en las películas para oírnos desde la distancia? La única solución sería hablar en clave, así por mucho que nos escuchen no nos entenderán. Pues en Internet pasa lo mismo, todas las comunicaciones pueden (y son) interceptadas (a veces por usuarios maliciosos y a veces, según lo que dicen los medios, incluso directamente por cuerpos de seguridad y gobiernos). Igual que antes, la solución es hablar en clave, cifrar nuestras comunicaciones.

Y aquí es donde entra el protocolo SSL/TLS. Su funcionamiento es sencillo, cuando voy a enviar un mensaje a un servidor seguro le pido una clave (pública) para cifrar la comunicación que después solo dicho servidor podrá descifrar con su clave (privada). Además, para dar un nivel extra de seguridad, el protocolo comprueba a quién corresponde esa clave y si es de confianza (es decir, que si yo me conecto al dominio “mibanco.com” y me invita a realizar una conexión segura, que las claves efectivamente pertenezcan a quien controla ese dominio). De esto se encarga una tercera entidad, denominada Autoridad Certificadora (CA en inglés), y aquí es dónde se encuentra la magia/problema/negocio: certificar que tú, como administrador, controlas un dominio para generar unos certificados y trabajar con SSL/TLS, cuesta dinero.

La solución gratuita pero no perfecta

Hasta ahora había generalmente dos opciones, la primera de ellas era por supuesto pagar. La segunda, generalmente utilizada por quien no se iba a lucrar con la securización de su sistema, crear una CA propia (es muy fácil hacerlo, os lo prometo) y validar con ella los certificados que se quieran generar. Ejemplo:

#Para simplificar, descargamos el siguiente fichero de configuración de CA
wget https://raw.githubusercontent.com/anders94/https-authorized-clients/master/keys/ca.cnf

#Después creamos nuestra CA
openssl req -new -x509 -days 9999 -config ca.cnf -keyout ca-key.pem -out ca-crt.pem

#Ahora generamos la clave privada del servidor (esta no se comparte con nadie)
openssl genrsa -out server-key.pem 4096

#A continuación debemos generar una petición de firma de certificado, para ello primero descargamos un fichero de configuración para simplificar
wget https://raw.githubusercontent.com/anders94/https-authorized-clients/master/keys/server.cnf

#Y posteriormente generamos la petición
openssl req -new -config server.cnf -key server-key.pem -out server-csr.pem

#Para terminar firmamos la petición con la CA y ya tenemos nuestro certificado listo para montar un servidor que soporte la comunicación segura
openssl x509 -req -extfile server.cnf -days 999 -passin "pass:password" -in server-csr.pem -CA ca-crt.pem -CAkey ca-key.pem -CAcreateserial -out server-crt.pem

Problema, cuando accedemos a un dominio que ha validado sus certificados mediante una CA no reconocida, que no tiene prestigio (¿que no cobra por ellos?), el navegador nos lanza una alerta como esta.

ssl

Esto se debe a que el navegador no tiene instalado por defecto el certificado de la CA y, por tanto, no la reconoce. Y esto, por supuesto, no genera demasiada confianza en el usuario…

Let’s Encrypt al rescate

Ya existían otras alternativas gratuitas que hacían de CA, pero su problema era el mismo que cuando generábamos una CA por nuestra cuenta: la confianza (o falta de) del navegador. Y entonces apareció Let’s Encrypt. Básicamente hacen lo mismo, pero esta vez tienen a muchos grandes de la industria apoyando la idea y han conseguido algo clave, la confianza de los navegadores. Para más información en cuanto a cómo obtienen esa confianza y cuáles son los navegadores soportados, os recomiendo visitar este post en su foro.

Si bien existen varias formas de conseguir los certificados para nuestros servidores a través de Let’s Encrypt, todas ellas bien documentadas y también explicadas a través del soporte de la comunidad, vamos a hacer una rápida prueba de concepto para securizar la comunicación con un servidor montado en una Raspberry Pi, uno de los dispositivos más populares en la actualidad con permiso de los Arduino, BeagleBoard o Teensy.

#En primer lugar, debemos asegurarnos de que los puertos 80 y 443 del router donde se encuentre la RPi están abiertos y el tráfico redirigido al servidor (la RPi). Let’s Encrypt los utiliza para validar el dominio.
#Después descargamos la última versión de Let’s Encrypt en /usr/local/src
git clone <a href="https://github.com/letsencrypt/letsencrypt" data-mce-href="https://github.com/letsencrypt/letsencrypt">https://github.com/letsencrypt/letsencrypt</a>

#Para este ejemplo utilizaremos el modo “Standalone” (más información en la documentación de Let’s Encrypt). No olvidarse de modificar el e-mail de contacto, con el que nos notificarán entre otras cosas de la caducidad de certificados (sí! caducan!) y el dominio para el que se quieren generar los certificados.
sudo ~/.local/share/letsencrypt/bin/letsencrypt certonly --agree-tos --email mymail@mail.com&nbsp; --standalone --domains midominio.com

#Los certificados se guardarán en /etc/letsencrypt (las carpetas “archive” y “keys” contienen las claves y certificados generados previamente, mientras que “live” contiene symlinks a las últimas versiones).
#Como se comentaba previamente, los certificados caducan, de hecho cada 90 días según la política de Let’s Encrypt, con lo que habrá que renovarlos, y mejor si es de forma automática.
#Para ello generamos un scrypt en /etc/letsencrypt
sudo nano auto-renewal.sh
#Con el siguiente contenido:
sudo ~/.local/share/letsencrypt/bin/letsencrypt certonly --standalone --domains claorden-home.du$
sudo cp /etc/letsencrypt/live/claorden-home.duckdns.org/fullchain.pem /var/www/rest-api/ssl/
sudo cp /etc/letsencrypt/live/claorden-home.duckdns.org/privkey.pem /var/www/rest-api/ssl/

#Aquí se podría añadir algún subscrypt que nos notifique de la renovación, por ejemplo mandando un mail o una notificación push a nuestro móvil.
#Le damos permisos de ejecución
sudo chmod +x auto-renewal.sh

#Y añadimos a crontab para que se ejecute de forma periódica
crontab -e

#el siguiente contenido:
#Run monthly, also use "@monthly"
0 0 1 * * /etc/letsencrypt/auto-renewal.sh

Con esto ya tenemos listos nuestros certificados. Ahora cuando montemos nuestro servidor en casa, debemos consultar según el sistema (Nginx, Node, Apache, IIS…) cómo realizar la comunicación mediante HTTPS y utilizarlos según las recomendaciones de cada uno. Así, al acceder a nuestro servidor podremos ver ese candado verde al lado de la URL que nos indica que la conexión es segura y quién ha verificado los certificados.

Y recordad, la próxima vez que contéis algún secreto por Internet, mejor decirlo en voz muy baja y al oído, que como diría mi compañero Iskander, el que avisa…

Carlos Laorden
Acerca de
Investigador de S3lab
Expertise: Information Retrieval, Child Protection, Spam Filtering