Mosquitto MQTT - Hardened, message broker
بواسطة Lynxroute
Mosquitto 2.1.2 - CIS Level 1 hardened MQTT broker on Ubuntu 24.04, TLS-only, SBOM + CIS
What is Eclipse Mosquitto
Eclipse Mosquitto is an open-source message broker implementing MQTT 5.0, 3.1.1 and 3.1 - the publish/subscribe protocol most IoT devices, industrial sensors and telemetry pipelines speak. Publishers send messages to a topic, subscribers receive every message on the topics they care about, and the broker sits in the middle keeping track. It supports quality-of-service levels 0 to 2, retained messages, last-will notifications, shared subscriptions, and persistent sessions that queue messages for devices while they are offline. Mosquitto is a single small C daemon with no database and no runtime to manage.
Why self-host Eclipse Mosquitto
A broker carries every message your devices and services exchange - sensor readings, commands, location, telemetry. Self-hosting keeps that traffic inside infrastructure you control and inside one jurisdiction, which matters for GDPR and for industrial data you are barred from sending to a third party. It also removes per-message and per-connection billing: a fleet that grows tenfold costs you a larger VM, not a larger invoice.
What this VM image adds
Security hardening:
- TLS-only listener on 8883 - there is no cleartext 1883 listener in this image at all, so a plain client is refused at the handshake rather than silently downgraded. MQTT sends the password inside the CONNECT packet, so a cleartext fallback would put the credential on the wire
- Anonymous access refused - allow_anonymous is false and there is no mapping that hands an unauthenticated connection a real identity
- Two ACL-scoped users, generated at first boot - a messaging user with read and write on your topics, and a monitoring user restricted to the broker statistics tree, so a metrics collector never holds a credential that can publish
- Per-instance credentials and certificate, no baked secrets - the distributed image holds no password file and no private key. Both are generated on your own instance at first boot, and the certificate carries your instance address and is reissued automatically if that address changes
- CVE scan - every image is scanned for vulnerabilities with Trivy before release
- UFW firewall - inbound limited to SSH 22 and MQTT 8883, nothing else
- fail2ban - SSH brute-force protection
- AppArmor - mandatory access control
- Sandboxed service unit - the broker runs unprivileged on a read-only filesystem apart from its own data and log directories, and cannot rewrite its own password file or access rules
OS hardening (CIS Level 1):
- CIS Level 1 hardened - CIS Ubuntu 24.04 LTS Level 1 Benchmark via ansible-lockdown
- auditd - system call auditing for critical paths
- SSH hardening - PasswordAuthentication disabled, key-only access
- Kernel hardening - SYN cookies, ASLR, rp_filter, TCP BBR
- Azure IMDS endpoints - egress rules pre-configured (169.254.169.254, 168.63.129.16)
Compliance artifacts (inside the VM):
- SBOM - CycloneDX 1.6 at /etc/lynxroute/sbom.json
- CIS Conformance Report - OpenSCAP HTML at /etc/lynxroute/cis-report.html
- Tailored CIS profile - /usr/share/doc/lynxroute/CIS_TAILORED_PROFILE.md
- Credentials handout - /root/mosquitto-credentials.txt, written at first boot, with the connection details and worked client examples
Quick Start
- Deploy the VM (Standard_B2s or larger recommended) and allow inbound 8883 from the networks your devices connect from
- SSH: ssh -i key.pem <username>@<PUBLIC_IP> (username set during VM creation, default: azureuser). The login banner shows the broker version, service state and the connect URL
- Read the credentials: sudo cat /root/mosquitto-credentials.txt - passwords plus copy-paste client examples
- Set CA=/etc/mosquitto/certs/server-cert.pem, then subscribe: mosquitto_sub -h localhost -p 8883 --cafile $CA -u app -P PASSWORD -t 'demo/#' -v
- Publish from another shell: mosquitto_pub -h localhost -p 8883 --cafile $CA -u app -P PASSWORD -t demo/hello -m 'hello world'
The certificate is self-signed and generated on your instance - point clients at it with --cafile, or replace it with your own PKI. Give each device its own user and topic scope before putting real traffic on the broker.
Eclipse and Mosquitto are trademarks of Eclipse Foundation AISBL.