Está en la página 1de 21

q

CASO PRÁCTICO 9
Seguridad en IoT

Gabriel Adolfo Díaz Guzmán


ingabrieldiaz@gmail.com
Ejercicio:

R1:
Arbol Jerarquico
Inicialmente, debemos conocer la forma en la que están dispuestos los
dispositivos planteados en el ejercicio. En este caso, sabemos que se trata de una
(1) casa inteligente con cuatro (4) ambientes y cada uno de los ambientes
contiene varios dispositivos particulares.
Podemos apoyarnos de los directorios de Linux para ver este
planteamiento de forma más gráfica y de esta forma determinar los tópicos que
serán utilizados en la comunicación MQTT:
Figura 1: Generación de los tópicos en forma de directorios Linux
En Unix, podemos utilizar el comando “tree” para listar directorios y su
contenido en forma de árbol. De manera que, los tópicos que dispondremos para
el ejercicio estarían dispuestos de la siguiente forma:
Figura 2: Árbol topológico del ejercicio utilizando el comando “tree” de linux

Esta jerarquía, la podemos observar de forma aún más intuitiva, si


elaboramos una topología simple, que transmita la manera en la que se
comunican los dispositivos de la casa inteligente, tal y como la siguiente:
Figura 3: Topología del ejercicio y posibles tópicos (Fuente Propia)
R2:
Instalación del Broker (Test without Auth)
Con la intención de sostener un ambiente de pruebas aislado y
centralizado, realizaremos el despliegue inicial del caso práctico en contenedores
mediante docker-compose. Para ello nos apoyaremos de la siguiente
documentación:
● Sukesh-Ak. (s. f.). GitHub - Sukesh-ak/setup-mosquitto-with-docker: How
to setup Mosquitto MQTT broker using Docker. GitHub.
https://github.com/sukesh-ak/setup-mosquitto-with-docker
Definimos la carpeta, donde almacenaremos los archivos del ambiente:
Figura 4: Generación de carpeta del proyecto “docker-mosquitto”

Generamos las carpetas que corresponden a los volúmenes del sistema


(config, data y log) y creamos un archivo docker-compose.yml para generar la
configuración de nuestro environment docker.
Figura 5: Generación de subcarpetas y yml de configuración

Creamos un archivo de configuración “mosquitto.conf” en la ruta


/config/mosquitto.conf con los atributos de nuestro broker, en este caso,
permitiendo acceso anónimo al mismo.
Figura 6: Composición del archivo mosquitto.conf para conexión sin
autenticación

Procedemos a definir la estructura de nuestro docker-compose,


definiendo la configuración de nuestro broker (imagen, nombre del contenedor,
puertos y volúmenes), aunado a esto, creamos una red particular denominada
“mosquitto-network” con la intención de tener un ambiente aislado.
Figura 7: Composición del archivo docker-compose.yml

Antes de ejecutar el compose, validamos los contenedores que tenemos


creados de momento:
Figura 8: Listado de contenedores del host

Procedemos a ejecutar nuestro compose, con la intención de levantar el


environment docker del broker y realizar pruebas con clientes MQTT:
Figura 9: Corrida del compose (docker-compose up)

En este punto, en teoría, el ambiente está levantado y funcional. Esto lo


podemos comprobar validando el estatus del contenedor:
Figura 10: Contenedor “mosquitto-broker” up and running

Antes de comenzar las pruebas, es necesario validar si disponemos de los


paquetes linux necesarios para simular clientes MQTT (Suscriptores y
Publicadores).
Figura 11: Validación de la comanderia de las
herramientas“mosquitto-clients”para las pruebas

Podemos realizar una prueba simple conectando un suscriptor al tópico


“test” y enviando por ese mismo tópico un mensaje para validar la comunicación:
Figura 12: Comunicación exitosa entre publicador y suscriptor

Validamos si queda traza de la comunicación en el broker, en el volumen


/log/mosquitto.log
Figura 13: Validamos los logs del broker en tiempo real

Figura 14: Traza de la comunicación en los logs


Ahora que vemos que el ambiente docker es funcional, podemos realizar
una prueba más robusta, utilizando los publicadores y los suscriptores reales del
ejercicio (Figura 3). Para ello ejecutaremos dos (2) pruebas de comunicación:
1. Status Request: El panel envía un mensaje “Send Status” a los dispositivos
del LRoom, y dichos dispositivos lo reciben)
Figura 15A: Dispositivos en correcta comunicación (prueba 1)

2. Status Response: Los dispositivos del LRoom responden con algunos


datos en una trama y el panel los recibe)
Figura 15B: Dispositivos en correcta comunicación (prueba 2)

Se aprecia claramente, que la comunicación entre dispositivos es


funcional. Este handshake entre dispositivos y el panel, podría ser uno de los
posibles procesos que serían ejecutados en una arquitectura similar a la
planteada en la figura 3, donde el panel le pide estatus a los dispositivos de un
área y estos le responden.
De igual forma, si queremos validar en tiempo la traza de las
comunicaciones de la prueba en nuestro broker, podríamos tener los logs del
mosquitto server abiertos con un “tail -f” para ver los registros en caliente:
Figura 16: Traza de la comunicación de las pruebas desde los logs del broker

R3:
Securización básica del Broker mediante creación de usuarios y contraseñas
para los dispositivos (Test with Auth)
En este punto, nuestro ambiente MQTT es funcional, sin embargo, puesto
a que no hemos securizado el broker, cualquier dispositivo que mande solicitudes
de conexión anónimas por el protocolo en dicha red tendrá acceso al broker y
por consiguiente podrá visualizar información sensible como las estadísticas del
broker:
Figura 17: Acceso a estadísticas del broker desde un dispositivo anónimo
Para evitar esto, procederemos a agregar una capa de seguridad
adicional, directamente desde el broker. Indicandole, que no acepte conexiones
anónimas, de manera que, solo luego de autenticarse, un dispositivo puede
integrarse al broker como subscriptor o como publicador.
Lo primero que haremos, es reestructurar el archivo de configuración de
nuestro broker, es decir, editaremos el archivo de la Figura 6 de la siguiente
forma:
Figura 18: Edición del archivo mosquitto.conf

Colocamos como “false” el boolean que identifica si se permite o no el


acceso anónimo al broker y agregamos el path de nuestro password_file. Este
último archivo, nos permitirá almacenar los usuarios y el hash de sus respectivas
contraseñas, para que de esta forma el broker pueda autenticar la legitimidad de
los intentos de conexión.
En este punto, es necesario generar los usuarios que creamos
convenientes. Para efectos prácticos del ejercicio, generaremos tres (3) usuarios,
todos con acceso al broker MQTT (admin, sub y pub):
Para generar dichos usuarios y sus credenciales, es necesario ingresar al
contenedor de la siguiente forma:
Figura 19: Ingreso al contenedor para generar archivo pwfile
Una vez dentro, generamos el archivo que hemos nombrado en el
mosquitto.conf, y agregamos los usuarios y contraseñas respectivas siguiendo la
sintaxis “user:password”, tal y como se ilustra a continuación:
Figura 20: Contenido del archivo “pwfile”

Cuando el archivo está listo, es necesario encriptar los passwords. Para


ello, utilizamos el comando mosquitto_passwd, esta herramienta nos permite
crear y gestionar credenciales de cara al Broker. El flag “-U”, nos da la posibilidad
de convertir un archivo con un conjunto de passwords en texto plano a hashed
password.
Figura 21: Archivo “pwfile” con los passwords encriptados en el container

Como nuestro environment es docker, es necesario que el archivo que


contiene los hashes posea un volumen, para que exista persistencia de dichas
credenciales. En este caso, como el path “config” que alberga el pwfile ya posee
un volumen en nuestro despliegue, validaremos si los ajustes realizados en el
contenedor, persisten en el host:
Figura 22: Archivo “pwfile” con los passwords encriptados en el host

Finalmente, luego de estas configuraciones, estamos listos para


comprobar si la autenticación de cara al broker es funcional, para ello,
probaremos dos (2) suscripciones y dos (2) publicaciones, primero sin
autenticarnos y luego utilizando las credenciales de la figura 20 para evaluar el
comportamiento del sistema:
Figura 23: Intentos de conexión sin autenticación

Figura 24: Traza de conexión sin autenticación (Logs)

Se aprecia claramente como el broker rechaza las solicitudes, tanto de


dispositivos que intentas suscribirse, como dispositivos que intentan publicar,
indiferentemente del tópico especificado.
Ahora probaremos con los usuarios que estipulamos en nuestro pwfile:
Figura 25: Intentos de conexión con autenticación
Figura 26: Traza de conexión con autenticación (Logs)

Tal y como era de esperarse, cuando es introducido un usuario y una


contraseña reconocida por el sistema, se le da acceso al dispositivo y se entabla
conexión MQTT, siguiendo la lógica convencional del protocolo.
R4:
Securización avanzada del Broker (ACL)
Supongamos que, ahora más allá de securizar la conexión directa con el
broker, lo que buscamos es restringir el acceso de ciertos dispositivos a ciertos
tópicos, tanto para suscribirse como para publicar. Esto lo podemos lograr con
listas de control de acceso.
El ejercicio nos plantea las siguientes dos premisas:
1. “El panel principal debe poder suscribirse a todos los dispositivos”
2. “El resto de los dispositivos sólo deben poder suscribirse al panel
principal”
Figura 27: Generación del archivo ACL
Figura 28: Edición del archivo mosquito.conf para agregar el path del ACL

Figura 29: Adición de dos nuevos usuarios (device y panel) para el contexto de las
premisas en el archivo pwfile

Figura 30: Definición de la lista de acceso

En este caso, realizaremos el control de acceso a partir de los usuarios


reconocidos en el broker, donde asumimos lo siguiente:
● Todos los dispositivos del Smarthome deben ingresar con el
usuario “device” y estos solo se podrán suscribir al panel.
● El panel del Smarthome debe ingresar con el usuario “panel” y
este podrá subscribirse a todos los dispositivos que existen en el
Smarthome independientemente de los subtópicos que posea.
● Los tópicos fuera de Smarthome sólo serán alcanzados por el
usuario “admin”, además este usuario también tiene acceso total a
la totalidad de los dispositivos del Smarthome, incluido el panel.
Figura 31: Encriptamiento de las credenciales para los usuarios del Broker

Figura 32: Reinicio del contenedor para aplicar el ACL

Figura 33: Prueba premisa 1 (El panel principal debe poder suscribirse a
todos los dispositivos)

Tal y como se aprecia en la figura, desde distintos tópicos se envían


mensajes al panel, mientras este se encuentra suscrito a todos los subtópicos del
Smarthome. Es decir, el usuario “panel”, tiene la capacidad de suscribirse a
cualquier tópico.
Figura 34A: Prueba premisa 2 (El resto de los dispositivos pueden
suscribirse al panel principal)

Figura 34B: Prueba premisa 2 (El resto de los dispositivos no pueden


suscribirse a otros tópicos)

Finalmente, si validamos que las suscripciones desde el usuario “device”


están restringidas únicamente al tópico del panel, puesto que con otros tópicos la
comunicación es interceptada por el ACL.

R5:
Capa de transporte seguro (SSL/TLS: 8883)
Como último objetivo, agregaremos una capa adicional de seguridad a
nivel de transporte implementando SSL/TLS mediante la herramienta de código
abierto OpenSSL, de esta forma las comunicaciones MQTT del Smarthome que
estamos planteando estarán más protegidas. Para la implementación en nuestro
proyecto se utilizará como referencia el siguiente video-tutorial, donde se
muestra de forma ilustrativa la implementación de esta capa de seguridad
adicional: ADTechKnow. (2022, 19 marzo). Use TLS-SSL with Mosquitto MQTT
Broker [Vídeo]. YouTube. https://www.youtube.com/watch?v=1Tu0tc0VHuc
Para efectos prácticos del ejercicio, se generará un step-by-step, con la
intención de tener listados todos los pasos necesarios para implementar SSL/TLS
a un sistema con un broker mosquitto desplegado en docker compose:
1. Generar carpeta “certs” donde se almacenarán los archivos necesarios
para establecer conexión segura entre el cliente y el servidor. Esta
carpeta debe generarse en uno de los volúmenes del contenedor, puesto
que la data debe tener persistencia host-contenedor.
Figura 35: Generación de carpeta “certs” en el volumen “config”

2. A continuación debemos generar el archivo ca.key. Este contiene la clave


privada asociada a la CA (autoridad de certificación). La CA es responsable
de emitir y firmar los certificados digitales utilizados por los servidores y
clientes MQTT, en este caso para nuestro cliente.
Figura 36: Generación del archivo ca.key

3. Procedemos a generar un certificado autofirmado utilizando OpenSSL,


especificamos la duracion en días del certificado y mencionamos al
archivo ca.key generado previamente. Este certificado se utilizará para
verificar la identidad del cliente ante el servidor MQTT en conexiones
seguras sobre SSL/TLS.
Figura 37: Generación del archivo ca.crt

4. En este punto, es necesario generar una clave privada ahora para el lado
del servidor.
Figura 38: Generación del archivo server.key

5. Solicitamos un certificado para el servidor a partir de la llave que


generamos previamente proporcionando como salida un archivo (.csr)
“Certificate Signing Request”. La solicitud de firma de certificado
(server.csr) incluye información sobre el servidor MQTT, como su nombre
de dominio, organización, ubicación, etc. Esta información es utilizada por
la CA para verificar y validar la identidad del servidor antes de emitir el
certificado.
Figura 39: Generación del archivo server.csr

6. Generamos el archivo que contiene el certificado digital firmado que


vincula la clave pública del servidor con su identidad (.crt) a partir de los
insumos anteriores.
Figura 40: Generación del archivo server.crt

7. Validamos que dentro del contenedor se encuentran también los


certificados y buscamos las rutas de los mismos con la intención de
posteriormente realizar modificaciones en los archivos de configuración
del sistema.
Figura 41: Validación de los certificados dentro del contenedor.

Figura 42: Validación de rutas de los certificados dentro del contenedor.

8. Ajustamos el archivo docker-compose.yml del proyecto, agregando el


puerto 8883 para comunicaciones seguras.
Figura 43: Edición archivo docker-compose.yml
9. Ajustamos el archivo mosquitto.conf, para que el broker comience a
escuchar a través del puerto 8883, colocamos la versión TLS y las rutas
que corresponden a los archivos de los certificados y llaves necesarias.
Figura 44: Edición archivo mosquitto.conf

10. Reiniciamos el environment para que se apliquen las modificaciones


realizadas en el protocolo.
Figura 45: Reinicio del environment docker (Down and Up)

11. Validamos que el broker inicialice de forma efectiva por los puertos
especificados.
Figura 46: Servidor levantando correctamente y en escucha por el puerto
8883.
12. Probar la comunicación efectiva mediante el puerto 8883 con el
certificado.
Figura 47: Prueba sin certificado (Puerto por defecto)

Figura 48: Prueba con certificado (Puerto por 8883)

Figura 49: Traza de comunicación en el log

Tal y como se aprecia en las pruebas, esta medida de seguridad garantiza


que únicamente los clientes que posean el certificado correspondiente puedan
establecer una conexión con el broker. Esta capa adicional de seguridad juega un
papel fundamental en la protección del sistema, asegurando que solo los clientes
autorizados puedan acceder y comunicarse de manera segura.

Nota Importante:
Respecto a la presentación:
A pesar de que el caso práctico estipulaba un límite máximo de 15
páginas, es importante destacar que las 26 páginas presentadas
contienen información y evidencias fundamentales para comprender la
totalidad de la implementación.
La extensión adicional del documento se debió, en parte, a la
decisión de realizar el despliegue utilizando la tecnología Docker en lugar
de una implementación directa en el host. Esta elección aumentó la
complejidad del proceso y requirió una explicación detallada para
garantizar una comprensión completa y precisa del ejercicio.

También podría gustarte