MQTT – The Heart of IoT Communication
Thilan Dissanayaka Hardware Hacking June 07, 2020

MQTT – The Heart of IoT Communication

In the world of IoT (Internet of Things), devices need a lightweight and reliable way to communicate. Enter MQTT (Message Queuing Telemetry Transport)—a protocol designed for efficient and real-time data exchange. Whether it’s a smart home system, industrial sensors, or connected cars, MQTT powers seamless communication between devices and servers.

In this blog post, we’ll explore:

What MQTT is and why it’s important

How MQTT works

Key components: brokers, clients, topics, and messages

QoS levels and reliability

Practical examples and demos

Security considerations

Use cases and advantages

What is MQTT?

MQTT is a lightweight, publish-subscribe messaging protocol developed in 1999 by IBM. Its main goal is to provide low-bandwidth, low-power communication for devices that are resource-constrained, like sensors, microcontrollers, and mobile devices.

Key features of MQTT:

Lightweight: Minimal overhead, ideal for low-bandwidth networks.

Reliable: Supports different Quality of Service (QoS) levels.

Real-time: Low latency communication.

Decoupled: Devices (clients) do not need to know each other; they communicate via a broker.

How MQTT Works

MQTT is based on a publish-subscribe model instead of a traditional client-server request-response model:

Clients: Devices or applications that send (publish) or receive (subscribe) messages.

Broker: Central server that manages message routing between publishers and subscribers.

Topics: Channels or subjects to which messages are published.

Messages: Data sent from publishers to subscribers via topics.

Workflow Example:

A temperature sensor publishes data to the topic home/livingroom/temperature.

A home automation system subscribes to this topic.

The MQTT broker receives the message from the sensor and forwards it to all subscribers.

MQTT Quality of Service (QoS) Levels

MQTT offers three QoS levels to ensure message delivery:

  • QoS 0 (At most once): Message is delivered once, with no acknowledgment. Fast but not guaranteed.

  • QoS 1 (At least once): Message is delivered at least once; duplicates are possible.

  • QoS 2 (Exactly once): Ensures message is delivered only once. Most reliable but slower.

Choosing the right QoS depends on the application’s criticality and network reliability.

MQTT Retained Messages and Last Will

Retained messages: MQTT broker stores the last message of a topic. New subscribers immediately receive it.

Last Will and Testament (LWT): If a client disconnects unexpectedly, the broker sends a predefined message to notify other subscribers.

Practical Example with Python (paho-mqtt)

import paho.mqtt.client as mqtt

# MQTT Broker
broker = \"test.mosquitto.org\"
port = 1883
topic = \"home/livingroom/temperature\"

# Callback function when message arrives
def on_message(client, userdata, message):
    print(f\"Received message: {message.payload.decode()} on topic {message.topic}\")

# Create MQTT client
client = mqtt.Client(\"Temperature_Sensor\")
client.connect(broker, port)
client.subscribe(topic)
client.on_message = on_message

# Publishing a message
client.publish(topic, \"25°C\")

# Keep the client running
client.loop_forever()

This script shows a sensor publishing temperature readings and a subscriber receiving them in real-time.

MQTT Security Considerations

While MQTT is efficient, it doesn’t include security by default. Here are some recommendations:

Use TLS/SSL encryption for data in transit.

Enable username/password authentication on the broker.

Restrict topics and access control to prevent unauthorized access.

Regularly monitor broker logs for unusual activity.

Advantages of MQTT

Low bandwidth consumption → ideal for IoT devices

Real-time updates → suitable for live monitoring

Lightweight and scalable → works even on microcontrollers

Decoupled architecture → easy to integrate with multiple systems

Common Use Cases

Smart homes: Lights, thermostats, security sensors

Industrial IoT: Machine monitoring and predictive maintenance

Healthcare: Patient monitoring systems

Connected vehicles: Telemetry and location tracking

Agriculture: Soil moisture sensors, irrigation systems

In Part 1, we covered MQTT theory, architecture, and basic usage. Now it’s time to get our hands dirty with real MQTT demos. You’ll learn how to:

Run a local MQTT broker

Connect multiple clients (publisher & subscriber)

Use retained messages

Experiment with QoS levels

Enable basic security

Step 1: Setting Up a Local MQTT Broker

For testing, you can use Mosquitto, a popular open-source MQTT broker.

On Linux / Raspberry Pi sudo apt update sudo apt install mosquitto mosquitto-clients -y sudo systemctl enable mosquitto sudo systemctl start mosquitto

On Windows / Mac

Download from Mosquitto.org

Install and start the service

By default, Mosquitto listens on port 1883 without authentication. Later, we’ll add security.

Step 2: Multiple Clients Example

We will simulate two sensors publishing temperature and humidity, and one subscriber receiving updates.

Publisher 1 – Temperature Sensor import paho.mqtt.client as mqtt import time import random

broker = "localhost" topic = "home/livingroom/temperature"

client = mqtt.Client("Temp_Sensor") client.connect(broker, 1883)

while True: temp = round(random.uniform(20.0, 30.0), 2) client.publish(topic, temp, qos=1, retain=True) print(f"Published temperature: {temp}°C") time.sleep(5)

Publisher 2 – Humidity Sensor import paho.mqtt.client as mqtt import time import random

broker = "localhost" topic = "home/livingroom/humidity"

client = mqtt.Client("Humidity_Sensor") client.connect(broker, 1883)

while True: humidity = round(random.uniform(40.0, 60.0), 2) client.publish(topic, humidity, qos=1, retain=True) print(f"Published humidity: {humidity}%") time.sleep(5)

Subscriber – Receives All Data import paho.mqtt.client as mqtt

broker = "localhost"

def on_message(client, userdata, message): print(f"Received: {message.topic} -> {message.payload.decode()}")

client = mqtt.Client("Home_Automation") client.connect(broker, 1883) client.subscribe("home/livingroom/#") # # subscribes to all topics under this path client.on_message = on_message client.loop_forever()

Result: The subscriber sees live updates from both sensors in real-time. Using retain=True ensures that if the subscriber reconnects, it immediately receives the last published value.

Step 3: Experimenting with QoS

Change the qos parameter in the publish() method:

qos=0 → fastest, no guarantee

qos=1 → at least once, may duplicate

qos=2 → exactly once, ensures delivery

Try disconnecting the subscriber and see how messages behave under different QoS levels.

Step 4: Adding Basic Security Enable Username & Password

Edit the Mosquitto config file (usually /etc/mosquitto/mosquitto.conf) and add:

allow_anonymous false password_file /etc/mosquitto/passwd

Create a password file:

sudo mosquitto_passwd -c /etc/mosquitto/passwd user1

Restart Mosquitto:

sudo systemctl restart mosquitto

Connect with Authentication client.username_pw_set("user1", "your_password") client.connect(broker, 1883)

Step 5: Using TLS/SSL for Encryption

Generate self-signed certificates:

openssl req -new -x509 -days 365 -nodes -out mosquitto.crt -keyout mosquitto.key

Configure Mosquitto for TLS:

listener 8883 cafile /path/to/mosquitto.crt certfile /path/to/mosquitto.crt keyfile /path/to/mosquitto.key

Connect securely in Python:

client.tls_set(ca_certs="mosquitto.crt") client.connect(broker, 8883)

Now all MQTT messages are encrypted over TLS.

ALSO READ
Blockchain 0x000 – Understanding the Fundamentals
May 21, 2020 Web3 Development

Imagine a world where strangers can exchange money, share data, or execute agreements without ever needing to trust a central authority. No banks, no intermediaries, no single point of failure yet...

Identity and Access Management (IAM)
May 11, 2020 Identity & Access Management

Who are you — and what are you allowed to do? That's the fundamental question every secure system must answer. And it's exactly what Identity and Access Management (IAM) is built to solve.

How I built a web based CPU Simulator
May 07, 2020 Pet Projects

As someone passionate about computer engineering, reverse engineering, and system internals, I've always been fascinated by what happens "under the hood" of a computer. This curiosity led me to...

Writing a Shell Code for Linux
Apr 21, 2020 Exploit Development

Shellcode is a small piece of machine code used as the payload in exploit development. In this post, we write Linux shellcode from scratch — starting with a simple exit, building up to spawning a shell, and explaining every decision along the way.

Exploiting a Stack Buffer Overflow on Windows
Apr 12, 2020 Exploit Development

In a previous tutorial we discusses how we can exploit a buffer overflow vulnerability on a Linux machine. I wen through all theories in depth and explained each step. Now today we are going to jump...

Access Control Models
Apr 08, 2020 Identity & Access Management

Access control is one of the most fundamental concepts in security. Every time you set file permissions, assign user roles, or restrict access to a resource, you're implementing some form of access control. But not all access control is created equal...

Exploiting a  Stack Buffer Overflow  on Linux
Apr 01, 2020 Exploit Development

Have you ever wondered how attackers gain control over remote servers? How do they just run some exploit and compromise a computer? If we dive into the actual context, there is no magic happening....

Basic concepts of Cryptography
Mar 01, 2020 Cryptography

Ever notice that little padlock icon in your browser's address bar? That's cryptography working silently in the background, protecting everything you do online. Whether you're sending an email,...

Common Web Application Attacks
Feb 05, 2020 Application Security

Web applications are one of the most targeted surfaces by attackers. This is primarily because they are accessible over the internet, making them exposed and potentially vulnerable. Since these...

Remote Code Execution (RCE)
Jan 02, 2020 Application Security

Remote Code Execution (RCE) is the holy grail of application security vulnerabilities. It allows an attacker to execute arbitrary code on a remote server — and the consequences are as bad as it sounds. In this post, we'll go deep into RCE across multiple languages, including PHP, Java, Python, and Node.js.