¿Qué aprenderá?
¿Qué hará?
¿Cuáles son los prerrequisitos?
Este tutorial ha sido construido para que el estudiante se familiarice con el funcionamiento de un sistema de mensajería MQTT, uno de los protocolos de mensajería IoT más ampliamente utilizado en la industria. El tutorial lo guiará para realizar el montaje y configuración de su propio sistema de mensajería el cuál se va a integrar tanto con la Capa de Dispositivos como con la Capa de Aplicación. En primer lugar se realizará el despliegue de la infraestructura de nube requerida, con ayuda de un script de Cloudformation (IAC) y comprobará su correcto funcionamiento; posteriormente, se configurará el bróker de manera que realice restricciones de acceso a tópicos definidos y solo permita el acceso a usuarios autorizados. Por último, se realizará la validación del funcionamiento del sistema de mensajería implementado utilizando dos scripts - uno publicador y uno suscriptor - que le permitirá experimentar con diferentes escenarios de prueba.
En este punto es importante resaltar que el software utilizado puede cambiar, por tanto no se puede garantizar que al desarrollar esta práctica todo estará exactamente igual a cuando se elaboró el tutorial. Esta es una realidad que se vive en el desarrollo de los proyectos de IoT y es muy importante desarrollar la habilidad de adaptarse a estos posibles cambios; así que los invitamos a que estén preparados para buscar información adicional que les permita llevar a buen término el trabajo propuesto. El equipo docente estará pendiente para ayudarlos.
MQTT es un protocolo de mensajería que se usa en la industria de los dispositivos IoT. El protocolo funciona bajo un esquema de comunicación publicación - suscripción, sobre temas, los cuales son una forma para clasificar y controlar los mensajes dentro del sistema. En este esquema de mensajería existen agentes que publican datos bajo un tema específico y agentes que se suscriben a estos temas y por ende pueden consultar los datos recibidos en el sistema. Es importante resaltar que los datos enviados pueden ser de cualquier tipo, sin embargo se recomienda que sean lo más livianos posible.
Aunque existen múltiples implementaciones para brokers MQTT, Mosquitto es una de las más ampliamente difundidas. Mosquitto es un sistema de código abierto que en su implementación presenta tres (3) diferentes módulos: el broker, el publicador y el suscriptor. El broker es el programa que se encarga de procesar los mensajes del sistema: recibe de los publicadores y envía a los suscriptores. El publicador y el suscriptor son programas para enviar y recibir mensajes al broker, respectivamente.
Dentro del protocolo se definen códigos de error que serán útiles al momento de integrar todas las capas del curso juntas (Dispositivo, Sesión, Aplicación). Los código de conexión básicos definidos para MQTT se pueden ver en la Tabla 1; estos incluyen los mensajes de error en la conexión.
Value | Return Code Response | Description |
0 | 0x00 Connection Accepted | Connection accepted |
1 | 0x01 Connection Refused, unacceptable protocol version | The Server does not support the level of the MQTT protocol requested by the Client |
2 | 0x02 Connection Refused, identifier rejected | The Client identifier is correct UTF-8 but not allowed by the Server |
3 | 0x03 Connection Refused, Server unavailable | The Network Connection has been made but the MQTT service is unavailable |
4 | 0x04 Connection Refused, bad user name or password | The data in the user name or password is malformed |
5 | 0x05 Connection Refused, not authorized | The Client is not authorized to connect |
6-255 | Reserved for future use |
Tabla 1. Códigos de retorno de una conexión MQTT
Tomado de la definición de MQTT de Oasis Open.
Los códigos anteriormente especificados pueden ser muy útiles ya que al presentarse algún error en la configuración del sistema, le dará un indicio de cómo arreglar el mismo. Sin embargo, no siempre se podrán evidenciar los errores por este medio aunque el sistema no esté funcionando correctamente. Más adelante, en la sección de pruebas se explicará un ejemplo de esto.
Para ampliar la información sobre MQTT y Mosquitto puede consultar los siguientes enlaces:
A continuación se presentan los pasos requeridos para crear y configurar la instancia EC2 requerida para el desarrollo del tutorial.
Figura 1. Interfaz de inicio del laboratorio
wget https://raw.githubusercontent.com/SELF-Software-Evolution-Lab/Realtime-Monitoring-webApp/main/tutoriales/Capa%20de%20Sesi%C3%B3n/IOT-MQTT.template.json -O template --no-check-certificate
aws cloudformation create-stack --stack-name broker-mqtt --template-body file://template --capabilities "CAPABILITY_IAM"
Dicho comando debe retornar en consola una salida como la siguiente:
{
"StackId": "arn:aws:cloudformation:us-east-1:123456789012:stack/broker-mqtt/330b0120-1771-11e4-af37-50ba1b98bea6"
}
AWS
" en la interfaz de inicio del laboratorio, como se puede ver en la Figura 2 .Figura 2. Inicio de la consola de AWS
CloudFormation
" (https://console.aws.amazon.com/cloudformation/) podrá verificar el estado de instanciación del stack. Espere a que el stack se termine de crear, esto lo podrá verificar ya que el mensaje de estado será "CREATE_COMPLETE
" (Ver Figura 3).Figura 3. Stacks creados en CloudFormation
EC2->Instances
" y verifique que la máquina EC2 esté creada y en estado "Running
" (Ver Figura 4). Puede usar este enlace https://console.aws.amazon.com/ec2/v2/ Figura 4. Máquina EC2 creada y corriendo
ping
a la dirección IP pública de la máquina desde la terminal de su equipo (este comando está disponible en cualquier sistema operativo). La dirección ip de la máquina puede consultarla en su descripción.ping <ip de la máquina>
En caso de que se pueda acceder al servidor debe recibir un mensaje de echo reply
que muestra la dirección IP de contacto, el número de bytes, el tiempo que ha tardado en enviar y recibir el paquete, y el TTL; así mismo muestra el número de paquetes enviados y recibidos y el Tiempo aproximado de ida y vuelta en milisegundos. En caso de no recibir un mensaje de este tipo, se debe verificar la configuración de red de la instancia y de su máquina personal.
Una vez se ha desplegado correctamente la instancia de la máquina EC2, se procede a la configuración del broker MQTT.
A continuación se especifican los pasos a seguir:
~$ echo 'port 8082' | sudo tee -a /etc/mosquitto/mosquitto.conf
~$ sudo systemctl restart mosquitto.service
A continuación se deben definir los temas habilitados para publicación y suscripción en el broker. Recuerde que los temas son la forma de clasificar los mensajes dentro del protocolo MQTT; se puede pensar que son canales. El publicador y el suscriptor usan los tópicos para enviar o recibir la información relevante que quieren.
Por ejemplo, un publicador puede enviar una señal de encendido a los bombillos de la sala de la casa usando el tema "casa/sala/bombillos/", y también enviar una señal de apagado al televisor de la cocina con el tema "casa/cocina/tv/". En este caso los suscriptores serán los bombillos y el televisor que están escuchando los mensajes que llegan a su respectivo tema.
Los temas pueden ser dinámicos, es decir que no necesitan ser creados ni eliminados; para que un tema funcione debe existir un publicador que envíe mensajes a dicho tema y un suscriptor que lo escuche.
Para el sistema de sensado que se está construyendo en el curso se utilizará la siguiente estructura para definir los temas que se van a permitir en el sistema y quién puede acceder a ellos:
En esa estructura el país, el estado y la ciudad pueden ser cualquier texto, pero para el parámetro usuario debe utilizarse la cuenta de un usuario registrado en el sistema.
Dado que se va a configurar el bróker para que sólo acepte mensajes de usuarios registrados en el sistema, y que sólo el usuario propietario del tema puede leer y escribir sobre este. También se necesita configurar en el broker que un usuario administrador pueda escribir y leer en cualquier tema así este pertenezca a un usuario en específico.
Para tal fin se debe realizar la configuración de las listas de acceso en el broker; a continuación se especifican los pasos que se deben seguir:
/etc/mosquitto/acl.txt
) donde se establecerán los patrones de los tópicos y si serán de lectura o escritura. Para tal fin cree un archivo de texto llamado acl (acl.txt)
en el directorio /etc/mosquitto/
con el siguiente comando:~$ sudo nano /etc/mosquitto/acl.txt
Al ejecutar el comando anterior se abre un editor de texto; úselo para agregar las siguientes líneas en el archivo:
| El " |
| Las reglas definidas después de esta línea sólo aplican para el usuario " |
| El símbolo " |
Guarde y cierre el archivo oprimiendo "
Ctrl+X
", seguido de "
y
" y "
Enter
".
mosquitto.conf
. Para incluir las reglas en el bróker se debe agregar "acl_file /etc/mosquitto/acl.txt"
al archivo de configuración (/etc/mosquitto/mosquitto.conf
). Puede hacerlo con el siguiente comando:~$ echo 'acl_file /etc/mosquitto/acl.txt' | sudo tee -a /etc/mosquitto/mosquitto.conf
~$ sudo systemctl restart mosquitto.service
users.txt
)que como su nombre lo indica es el archivo donde se almacenarán los usuarios válidos del sistema. Cada usuario debe estar en la misma línea con su contraseña en el formato usuario:contraseña
. Tenga en cuenta que si especificó reglas de temas sobre usuarios específicos (ej.: el usuario "admin"puede acceder a todos los temas), estos usuarios deberían estar en el archivo.
Ejecute el siguiente comando para crear el archivo:
~$ sudo nano /etc/mosquitto/users.txt
Ejemplo del archivo:
admin:admin1234
user1:123456
pe.perez:abc123
ironman:jarvis123
Jfkennedy:apolo11
Para salir de la edición del archivo oprimir "
Ctrl+X
", luego "
y
" y "
Enter
".
Figura 5. Archivo de usuarios creado
~$ sudo mosquitto_passwd -U /etc/mosquitto/users.txt
~$ cat /etc/mosquitto/users.txt
El archivo debería tener las contraseñas cifradas en un formato parecido al que se puede apreciar a continuación:
admin:$7$101$bhasbdbasxdfBdjbasjsajdbjasah==
user1:$7$101$bhasbdbdfjbasjsajdbjasah==
pe.perez:$7$101$bhasbddfhnjhkjwef4566jdbjasah==
ironman:$7$101$bhasbdRETdjbasjsajdbjasah==
Jfkennedy:$7$101$TDCHGK6FGJGVGHVGHJVHdffsVGhjv==
"allow_anonymous false"
y "password_file /etc/mosquitto/users.txt"
en el archivo de configuración (/etc/mosquitto/users.txt
). Puede usar los siguiente comandos: ~$ echo 'allow_anonymous false' | sudo tee -a /etc/mosquitto/mosquitto.conf
~$ echo 'password_file /etc/mosquitto/users.txt' | sudo tee -a /etc/mosquitto/mosquitto.conf
~$ sudo systemctl restart mosquitto.service
~$ sudo systemctl status mosquitto.service
La terminal debe mostrar que el servicio está activo y corriendo (active
). Para salir del resumen del servicio oprima "
Ctrl+C
".
La seguridad al transmitir los datos por Internet es un factor muy importante. Siempre que enviamos y recibimos datos, esta información queda expuesta en la red, por tal razón se hace necesario el cifrado de estos datos, y es allí donde entran en juego los protocolos SSL y TLS.
A continuación se presentarán los pasos necesarios para la configuración del cifrado de la comunicación del broker MQTT:
Cree la carpeta "ssl" e ingrese a la misma:
~$ mkdir ssl; cd ssl
A continuación genere la llave de CA ("Certificate Authority") con el siguiente comando. Nota: Este le pedirá una contraseña para crear la llave. Puede asignar la contraseña "mqtt".
~/ssl $ openssl genrsa -des3 -out ca.key 2048
El siguiente paso es generar el certificado de CA ("Certificate Authority") con el siguiente comando:
~/ssl $ openssl req -new -x509 -days 1826 -key ca.key -out ca.crt
El diálogo le pedirá la contraseña que ingresó en el paso anterior y otros datos como país, estado, ciudad, organización, etc.
Un ejemplo de datos puede ser este:
Country name: CO
State: Cundinamarca
City: Bogota
Organization: Uniandes
Unit name: MISO
Common name: <dirección ip pública de EC2> (importante)
Email: correo uniandes (ej: estudiante@uniandes.edu.co)
Ahora genere la llave para el servidor con el comando:
~/ssl $ openssl genrsa -out server.key 2048
Y genere el CSR ("Certificate Signing Request") para el servidor con:
~/ssl $ openssl req -new -out server.csr -key server.key
Al igual que cuando se generó el certificado de CA, ingrese la misma información que se le pida y en "Common name" ingrese la dirección IP de la máquina.
Después hay una información opcional que puede ingresar de la siguiente manera:
Challenge pwd: mqtt
Optional company: uniandes
Por último, genere el certificado para el servidor con el siguiente comando.
~/ssl $ openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 360
El diálogo le pedirá la contraseña que asignó a la llave de CA, en el ejemplo es "mqtt".
Si corre el comando ls
deberían aparecer 5 archivos como los siguientes:
ca.crt ca.key ca.srl server.crt server.csr server.key
Copie los archivos ca.crt
, server.crt
y server.key
al directorio de configuración de mosquitto. Siga los siguientes comandos:
c~/ssl $ sudo cp ca.crt /etc/mosquitto/ca_certificates/ca.crt
~/ssl $ sudo cp server.crt /etc/mosquitto/certs/server.crt
~/ssl $ sudo cp server.key /etc/mosquitto/certs/server.key
A continuación es necesario extraer el certificado de CA para usarlo en los dispositivos que estarán enviando mensajes al bróker. Para esto siga los siguientes pasos:
Muestre la información del archivo ca.crt
con el siguiente comando.
~/ssl $ less ca.crt
La consola debería mostrar un certificado como el siguiente:
-----BEGIN CERTIFICATE-----
MIIEowIBAAKCAQEAoHxKs/X9I/y7NpxA5Qgz3mUSE6CeHpWEwUyNdOzmrM0WR7Mh
xxBQrkXQAXduODpBCeO+7+aiw+HCYKc2Hdgb2ClYlPpxlKdR8BSL2OunBkU9KiWl
wZG4Rgz0nxjaDSm3L3ald3E0h5C4qX1viSI9KxeqRqx81/obUqNrVH8m3GVbpVre
IV0A/LhneV2JiJJiq10y5hLYyxZG/BDQtnq2gZtKoEd51nodyrTUD0WbEz8GYRXN
rPG6eRib0gYPjR9hJwblj24Y8/4ZJOCvF70UvA7FQi07uX5GfFxORartplGfm9NQ
/EVrRnkfA3tPT/tNbgH7Q2Jr40qhjTrh4xma7QIDAQABAoIBAG98SIzhqrvQOuHC
BFbWrumkvr0BzDYk2jdKDc6XL9wFEKA4cZOO4u1dtBUAuYG3/ix3mNGhH5sB/v0T
y8VJtnYgqte7byG8ZnBoZYoIklwJx2a7Bn4E08VeBKVtJzUTsJz5SBNEgiBWyeF8
MPpL3cBMzU4RTxzeMxLiUZI+Tmm1qethbvXF7rXHE6T+PLZKh+c9iYx1Wi9z1Hxl
WSQWucI3DKQkBtV+/FtQbJLKIpy8sSXOS50WHNatP4DALd7rRYw0u3MxVxPONMS1
hghoP/su9fQUM4vcfLXhETfxiU1sfJgdokwF+wf7rUNiP1hTTRxoFSBKqYBVq0SS
iAvM+KUCgYEA01FgQDFfC0UyLUloaPk61cD8E0Zv3eryUJmW/tPNKYwqLxxEK1m4
Q6+3DuIyHnAmsiqCDs0Ey6HsQtsDJqobA6uD3p1cFKyKaZTaoj3mabELzZeh7SKI
jNmz+3AG47QJL+CnChEjPreMYE1WpURSj+na9UOVWGmY24fwwHgtdUsCgYEAwmtc
+pNqOotj6zHtCTAHuBcrhqM8ZqLzVEKPeJ4G6xx474DK8+Fh6w00cCHPJ0mB0bYA
/7TIECnwL4XqwVnE6BT/JXfFP98JP+3NkXh8PezwnmOWEONDqD80QJZ0wkxDk/q+
6BlhpBZfx5h2Qvu5trsZg489hWdbU8JapFTS5acCgYBV55TrQ6bRnBWj2HvtALRs
RQG0jEPZwTM0lNuPSGb05ugXMrR7swN3cK1IPagGO61fbGxmu+2hIng7TXFgfHJy
8XywOOQ/+0xhU4P1xJgwiyqzL1tCXXGJYM8L/iSu2HeLoRYGv6TGUDOeypHYqYeu
vXCnmAvUX0kmpYK3m6NPNQKBgQCgJxTmjTy6kUxz2CKsqNYS/XMra5g77AuJ43KQ
J40Ha+LrWCrXD1g76hrCK/ebI2A/QjA8c81CE2n5m9UwBSTBEVrEoI7p+G6ELP5j
0N53nJDxyJM7whpfpAEFG2t/Cpe4dJuCUjYulwe7QYpZz0bCkgmIaByDogqHStij
+gPojQKBgDm3MsdrrxDoRVgT6WQzrNwMPUlgXckOzMpWzy+7XJjBN8o1nwVFW0Eh
QdUbEM+1wxL80eYT6XfgUjog9Js5ZlQc3MvePw5iGFBpelQ86Fg9W3XGRZDvxVfO
5Iy1/VlND5esjKRvc/wb7QL+K/0wb8v6KSJeTWJn50B3UNieR3hf
-----END CERTIFICATE-----
Debe copiar el contenido del archivo a un archivo de su computador local. Copie desde "-----BEGIN CERTIFICATE-----" hasta "-----END CERTIFICATE-----". Se recomienda que el archivo que cree se llame de la misma manera (ca.crt
). Para salir del visor de archivos oprima la tecla "q".
A continuación, modifique el archivo de configuración de mosquitto. Para esto use el comando:
~/ssl $ sudo nano /etc/mosquitto/mosquitto.conf
Agregue las siguientes líneas al archivo:
cafile /etc/mosquitto/ca_certificates/ca.crt
keyfile /etc/mosquitto/certs/server.key
certfile /etc/mosquitto/certs/server.crt
tls_version tlsv1.2
El archivo debería verse así:
# Place your local configuration in /etc/mosquitto/conf.d/
# A full description of the configuration file is at
# /usr/share/doc/mosquitto/examples/mosquitto.conf.example
persistence true
persistence_location /var/lib/mosquitto/
log_dest file /var/log/mosquitto/mosquitto.log
include_dir /etc/mosquitto/conf.d
port 8082
acl_file /etc/mosquitto/acl.txt
allow_anonymous false
password_file /etc/mosquitto/users.txt
cafile /etc/mosquitto/ca_certificates/ca.crt
keyfile /etc/mosquitto/certs/server.key
certfile /etc/mosquitto/certs/server.crt
tls_version tlsv1.2
Para guardar y salir oprima "Ctrl + X",seguido de "y" y "Enter".
El siguiente paso es cambiar los permisos de la llave y certificado del servidor con los comandos:
~/ssl $ sudo chmod 777 /etc/mosquitto/certs/server.crt
~/ssl $ sudo chmod 777 /etc/mosquitto/certs/server.key
Por último reinicie el servicio del bróker con:
~/ssl $ sudo systemctl restart mosquitto.service
Para asegurar que el servicio haya quedado correctamente configurado puede ejecutar el comando:
~/ssl $ sudo systemctl status mosquitto.service
La terminal debe mostrar que el servicio está activo y corriendo (active
).
Una vez establecida la configuración de temas, listas de acceso y cifrado de la comunicación se pueden establecer varios escenarios de prueba para el bróker con la finalidad de dejarlo listo para la integración con el resto de capas.
En este link encontrará un archivo comprimido con los distintos scripts para hacer las pruebas. Al descomprimir el archivo se encuentran estos tres (3) archivos: (i) publisher.py, (ii) subscriber.py, y (iii) requerimients.txt. Para ejecutar estos archivos es necesario que tenga Python 3 instalado en su computadora. Asegúrese de copiar (en el mismo directorio donde se encuentran los scripts) el certificado ca.crt que ha generado en pasos anteriores.
Los escenarios de prueba configurados son los siguientes:
Siga las siguientes instrucciones para probar los escenarios.
python3 -m pip install -r requeriments.txt
subscriber.py
con la siguiente información:HOST
: la dirección IP pública de su bróker MQTTPORT
: el puerto configurado en la configuración del bróker (en este tutorial es 8082)USER
: el usuario que tiene acceso a todos los tópicos (según el ejemplo es "admin
")PASSWD
: la contraseña del usuario especificado (según el ejemplo es "admin1234
")python3 subscriber.py
En la terminal deben aparecer los mensajes de conexión y suscripción. Cuando se ejecuten las pruebas en esta consola podrá ver los mensajes entrantes que pasan por MQTT.
En este punto es importante resaltar que se deben tener abiertas dos (2) terminales diferentes, una para el suscriptor y otra para las pruebas con el publicador.
Nota: para detener la ejecución de cualquier programa (subscriber.py
o publisher.py
) basta con oprimir "Ctrl+C
".
Para este escenario se necesita conocer un usuario configurado en el broker y su contraseña. En este caso el tema que es accesible para lectura y escritura sería cualquiera que tenga el patrón +/+/+/
. Si se registraron los usuarios del ejemplo dado, un tópico válido sería colombia/cundinamarca/cajica/user1
o también mexico/jalisco/guadalajara/user1
.
python3 publisher.py --host <ip-bróker> --user <usuario-seleccionado> --passwd <contraseña-del-usuario> --topic <tópico-seleccionado>
Ejemplo:
python3 publisher.py --host 3.122.32.43 --user user1 --passwd 123456 --topic mexico/jalisco/guadalajara/user1
En la terminal del publicador se mostrará un mensaje cada 2 segundos con el formato
. Esto quiere decir que el publicador ya está enviando mensajes.
Data received: MQTT Test
; esto indica que tanto el control de temas y la autenticación quedaron bien configurados.Para este escenario se necesita conocer un usuario configurado en el bróker, pero no es necesaria su contraseña ya que se usará una contraseña diferente a la del usuario. Como en el escenario anterior el tema puede ser cualquiera que tenga el patrón +/+/+/
. Si se registraron los usuarios del ejemplo dado, un tópico válido sería colombia/cundinamarca/cajica/user1
o también mexico/jalisco/guadalajara/user1
.
python3 publisher.py --host <ip-bróker> --user <usuario-seleccionado> --passwd <contraseña-inválida> --topic <tópico-seleccionado>
Ejemplo:
python3 publisher.py --host 3.122.32.43 --user user1 --passwd ABCDEFG --topic mexico/jalisco/guadalajara/user1
En la terminal del publicador se mostrará un mensaje cada 2 segundos con el formato
. Adicionalmente se mostrará el estado de la conexión en la línea siguiente con el formato Msg:
. Lea atentamente los mensajes de estas líneas. Como la autenticación no es correcta el estado de la conexión indicará "Connection Refused: bad user name or password".
En este escenario se usará un usuario registrado con su respectiva contraseña, pero cambiará el tema al que se le enviará el mensaje; recuerde que los temas válidos para cada usuario (exceptuando "admin" pues tiene reglas diferentes) son +/+/+/
. Por ejemplo, como "user1" es un usuario registrado en el sistema, un tema válido sería colombia/cundinamarca/cajica/user1
o también mexico/jalisco/guadalajara/user1
.
Para esta prueba algunos temas inválidos serían:
colombia/cundinamarca/bogota/user2
user1
panama/colon/user1
python3 publisher.py --host <ip-bróker> --user <usuario-seleccionado> --passwd <contraseña-inválida> --topic <tópico-seleccionado>
Ejemplo:
python3 publisher.py --host 3.122.32.43 --user user1 --passwd 123456 --topic panama/colon/user1
En la terminal del publicador se mostrará un mensaje cada 2 segundos con el formato
. Adicionalmente se mostrará el estado de la conexión en la línea siguiente con el formato Msg:
. Lea atentamente los mensajes de estas líneas. A diferencia de la prueba anterior, el programa no arroja ningún error, pero si indica publicación exitosa.
En este escenario no se muestra ningún error en los programas de publicación y suscripción aunque el bróker si ha controlado el acceso correcto.
Al finalizar este tutorial, se espera que se haya familiarizado con el protocolo MQTT así como con su configuración y su despliegue.
Juan Avelino Carlos Andrés Lozano Garzón | Autores |
Kelly Garcés Andrés Bayona Rocío Héndez | Revisores |