Mosquitto v2 MQTT Broker on Debian Bullseye
- Install Mosquitto on Debian Bullseye
- Configure Mosquitto
- Verify that the Broker is working
- Websockets
- Mosquitto Webserver
- Adding Encryption
- Connect your INSTAR IP Camera
Mosquitto is a message broker that implements the MQTT protocol. Mosquitto is an open-source project developed by Eclipse. MQTT protocol uses a publish/subscribe model. Client can publish message to a broker and other clients can subscribe to the topic of that message. A broker is a central component that receives all messages from the clients and then publishes the messages to all subscribed clients.
Install Mosquitto on Debian Bullseye
Check Building Eclipse Mosquitto v2 from Source for building the broker from it's source code under Arch Linux.
Add the Mosquitto repository:
wget http://repo.mosquitto.org/debian/mosquitto-repo.gpg.key
sudo apt-key add mosquitto-repo.gpg.key
cd /etc/apt/sources.list.d/
wget http://repo.mosquitto.org/debian/mosquitto-bullseye.list
Install Mosquitto broker:
apt update
apt install mosquitto
Check Mosquitto version:
mosquitto -h | grep version
mosquitto version 2.0.14
Check if Mosquitto service is running:
service mosquitto status
● mosquitto.service - Mosquitto MQTT Broker
Loaded: loaded (/lib/systemd/system/mosquitto.service; enabled; vendor preset: enabled)
Active: active (running) since Sat 2022-02-05 14:06:50 HKT; 25min ago
Docs: man:mosquitto.conf(5)
man:mosquitto(8)
Process: 574 ExecStartPre=/bin/mkdir -m 740 -p /var/log/mosquitto (code=exited, status=0/SUCCESS)
Process: 586 ExecStartPre=/bin/chown mosquitto /var/log/mosquitto (code=exited, status=0/SUCCESS)
Process: 593 ExecStartPre=/bin/mkdir -m 740 -p /run/mosquitto (code=exited, status=0/SUCCESS)
Process: 598 ExecStartPre=/bin/chown mosquitto /run/mosquitto (code=exited, status=0/SUCCESS)
Main PID: 599 (mosquitto)
Tasks: 1 (limit: 9357)
Memory: 3.6M
CPU: 1.184s
CGroup: /system.slice/mosquitto.service
└─599 /usr/sbin/mosquitto -c /etc/mosquitto/mosquitto.conf
Feb 05 14:06:49 nomad-minion systemd[1]: Starting Mosquitto MQTT Broker...
Feb 05 14:06:50 nomad-minion mosquitto[599]: 1644041210: Loading config file /etc/mosquitto/conf.d/custom.conf
Feb 05 14:06:50 nomad-minion systemd[1]: Started Mosquitto MQTT Broker.
Here I can see that the Mosquitto binary was installed in /usr/sbin
and it is being started with a default configuration file in /etc/mosquitto/mosquitto.conf
.
Configure Mosquitto
Mosquitto installs 5 further tools that we can use with our broker:
ls -la /usr/bin | grep mosquitto
-rwxr-xr-x 1 root root 60448 Jun 9 2021 mosquitto_ctrl
-rwxr-xr-x 1 root root 31456 Jun 9 2021 mosquitto_passwd
-rwxr-xr-x 1 root root 60296 Jun 9 2021 mosquitto_pub
-rwxr-xr-x 1 root root 64608 Jun 9 2021 mosquitto_rr
-rwxr-xr-x 1 root root 64608 Jun 9 2021 mosquitto_sub
Password file can be created using mosquitto_passwd
tool:
mosquitto_passwd -c /etc/mosquitto/password_file admin
Password: instar
Reenter password: instar
First argument is path to a file, second argument is username. The -c
option means that new password file will be created. Run the following command and enter a password for the user.
Next, open Mosquitto configuration file:
cat /etc/mosquitto/mosquitto.conf
# 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
pid_file /run/mosquitto/mosquitto.pid
persistence true
persistence_location /var/lib/mosquitto/
log_dest file /var/log/mosquitto/mosquitto.log
include_dir /etc/mosquitto/conf.d
Here I can see that the "actual" configuration file, the one that I need to edit, must be located in /etc/mosquitto/conf.d
. So let's take a look:
/etc/mosquitto/conf.d/custom.conf
# =================================================================
# General configuration
# =================================================================
# per_listener_settings false
# allow_zero_length_clientid true
auto_id_prefix zeroid-
# check_retain_source true
#max_inflight_bytes 0
#max_inflight_messages 20
#max_keepalive 65535
#max_packet_size 0
#max_queued_bytes 0
#max_qos 2
#max_queued_messages 1000
#memory_limit 0
#message_size_limit 0
persistent_client_expiration 7d
# pid_file /var/run/mosquitto/mosquitto.pid
queue_qos0_messages true
#retain_available true
#set_tcp_nodelay false
#sys_interval 10
#upgrade_outgoing_qos false
#user mosquitto
# =================================================================
# Listeners
# =================================================================
listener 1883
protocol mqtt
listener 1885
protocol websockets
#socket_domain
#bind_interface
#http_dir
#max_connections -1
#mount_point
#use_username_as_clientid
#websockets_headers_size
# -----------------------------------------------------------------
# Certificate based SSL/TLS support
# -----------------------------------------------------------------
#certfile
#keyfile
#ciphers
#ciphers_tls1.3
#crlfile
#dhparamfile
#require_certificate false
#cafile
#capath
#use_identity_as_username false
# -----------------------------------------------------------------
# Pre-shared-key based SSL/TLS support
# -----------------------------------------------------------------
#psk_hint
#ciphers
#use_identity_as_username false
# =================================================================
# Persistence
# =================================================================
#autosave_interval 1800
#autosave_on_changes false
#persistence false
#persistence_file mosquitto.db
#persistence_location
# =================================================================
# Logging
# =================================================================
#log_dest stderr
log_type error
log_type warning
log_type notice
log_type information
connection_messages true
#log_facility
log_timestamp true
log_timestamp_format %Y-%m-%dT%H:%M:%S
#websockets_log_level 0
# =================================================================
# Security
# =================================================================
#clientid_prefixes
allow_anonymous false
# -----------------------------------------------------------------
# Default authentication and topic access control
# -----------------------------------------------------------------
password_file /etc/mosquitto/passwordfile
acl_file /etc/mosquitto/acl.file
# -----------------------------------------------------------------
# External authentication and topic access plugin options
# -----------------------------------------------------------------
# auth_plugin
# auth_opt_db_host
# auth_opt_db_port
# auth_opt_db_username
# auth_opt_db_password
# =================================================================
# Bridges
# =================================================================
#connection <name>
#address <host>[:<port>] [<host>[:<port>]]
#topic <topic> [[[out | in | both] qos-level] local-prefix remote-prefix]
#bridge_bind_address
#bridge_attempt_unsubscribe true
#bridge_protocol_version mqttv311
#idle_timeout 60
#keepalive_interval 60
#local_clientid
#notifications true
#notification_topic
#remote_clientid
#remote_password
#remote_username
# restart_timeout 20
# restart_timeout 10 30
#restart_timeout 5 30
#round_robin false
#start_type automatic
#threshold 10
#try_private true
#bridge_outgoing_retain true
#bridge_max_packet_size 0
# -----------------------------------------------------------------
# Certificate based SSL/TLS support
# -----------------------------------------------------------------
#bridge_cafile
#bridge_capath
#bridge_alpn
#bridge_insecure false
#bridge_certfile
#bridge_keyfile
# -----------------------------------------------------------------
# PSK based SSL/TLS support
# -----------------------------------------------------------------
#bridge_identity
#bridge_psk
# =================================================================
# External config files
# =================================================================
#include_dir
Make changes as needed and restart the Mosquitto service with:
service mosquitto restart && service mosquitto status
Verify that the Broker is working
Mosquitto CLI Tools
Verify that the broker is working using the Mosquitto subscription and publication tools:
mosquitto_sub -h localhost -p 1883 -u admin -P instar -v -t '$SYS/broker/uptime'
$SYS/broker/uptime 1089 seconds
$SYS/broker/uptime 1100 seconds
$SYS/broker/uptime 1111 seconds
Subscribing to $SYS/broker/uptime
will give you the broker uptime in an 10s interval (interval can be adjusted in the mosquitto config).
Connecting Clients
And to something more exciting - I will connect an INSTAR IP camera:
And send an update to switch the privacy area 1 on and off again using the command topic:
mosquitto_pub -h 192.168.2.111 -p 1883 -u admin -P instar -t 'cameras/117/multimedia/privacy/region1/enable' -m '{"val":"1"}' -d
Client (null) sending CONNECT
Client (null) received CONNACK (0)
Client (null) sending PUBLISH (d0, q0, r0, m1, 'cameras/117/multimedia/privacy/region1/enable', ... (11 bytes))
Client (null) sending DISCONNECT
mosquitto_pub -h 192.168.2.111 -p 1883 -u admin -P instar -t 'cameras/117/multimedia/privacy/region1/enable' -m '{"val":"0"}' -d
Client (null) sending CONNECT
Client (null) received CONNACK (0)
Client (null) sending PUBLISH (d0, q0, r0, m1, 'cameras/117/multimedia/privacy/region1/enable', ... (11 bytes))
Client (null) sending DISCONNECT
Subscribing to the status topic I can see that the command was executed as expected:
mosquitto_sub -h localhost -p 1883 -u admin -P instar -v -t 'cameras/117/status/multimedia/privacy/region1/enable'
cameras/117/status/multimedia/privacy/region1/enable {"val":"1"}
cameras/117/status/multimedia/privacy/region1/enable {"val":"0"}
Websockets
MQTT Explorer
So far I have been using the configured default listener on port 1885
using the MQTT protocol. But I added an additional listener on port 8885
that requires a websocket connection:
# =================================================================
# Listeners
# =================================================================
listener 1883
protocol mqtt
listener 1885
protocol websockets
In the MQTT Explorer you can switch the used protocol to ws
to test the service:
MQTT.js Web Client
Using a MQTT.js React Dashboard to connect to the WS service:
import React, { useState, Fragment } from 'react';
import './App.css';
var mqtt = require('mqtt');
var options = {
protocol: 'ws',
username: 'admin',
password: 'instar',
// clientId uniquely identifies client
// choose any string you wish
clientId: 'mqttjs_' + Math.random().toString(16).substr(2, 8),
};
var client = mqtt.connect('ws://192.168.2.111:1885', options);
// Get Broker Uptime MQTT topic
client.subscribe('$SYS/broker/uptime');
function App() {
var note;
client.on('message', function (topic, message) {
note = message.toString();
// Updates React state with message
setMsg(note);
console.log(note);
client.end();
});
// Sets default React state
const [msg, setMsg] = useState(<Fragment><em>connecting...</em></Fragment>);
return (
<div className="App">
<header className="App-header">
<h1>Mosquitto Broker</h1>
<p>Uptime: {msg}</p>
</header>
</div>
);
}
export default App;
Mosquitto Webserver
When a listener is using the websockets protocol, it is possible to serve http data as well. Set http_dir
to a directory which contains the files you wish to serve. If this option is not specified, then no normal http connections will be possible. Let's add this third listener to the configuration file:
# =================================================================
# Listeners
# =================================================================
listener 1883
protocol mqtt
listener 1885
protocol websockets
listener 8080
protocol websockets
http_dir /opt/mqtt-tree
I am going to use this D3 Tree from @hardillb
and download to /opt/mqtt-tree
. All I need to add the the ./index.html
file is the Mosquitto WS URL, Port and the broker login to display a tree view of all registered topics:
var options = {
// host: location.hostname,
// port: parseInt(location.port),
host: '192.168.2.111',
port: 1885,
clientID: "web" + new Date().getTime(),
connectOpts: {
userName: 'admin',
password: 'instar',
// useSSL: true,
keepAliveInterval: 30,
timeout: 10,
cleanSession: false,
onSuccess: onConnect,
onFailure: onFailure
}
}
Restart the Mosquitto service and visit the broker IP on port 8080
with your web browser:
Adding Encryption
Creating Self-Signed Certificates
Client Requirements
- A CA (certificate authority) certificate of the CA that has signed the server certificate on the Mosquitto Broker.
Broker Requirements
- CA certificate of the CA that has signed the server certificate on the Mosquitto Broker.
- CA certificated server certificate.
- Server Private key for decryption.
openssl version
OpenSSL 1.1.1l 24 Aug 2021
Mosquitto already creates a directory for self-signed certificates - if it does not exists create it with:
mkdir -p /etc/mosquitto/certs
chown mosquitto:mosquitto /etc/mosquitto/certs
CA Certificates
m
cd /etc/mosquitto/certs
openssl genrsa -out ca.key 4096
Important: The FQDN must not be the same as the server FQDN, otherwise you might end up with SSL errors. On a local network using a AVM Fritzbox router every device receives both a hostname - for example my Mosquitto server identifies as debian11
- and a domain name hostname + .fritz.box
. So, for example, I am able to access the Mosquitto webserver via http://debian11.fritz.box:8080/
:
openssl req -new -x509 -days 1825 -key ca.key -out ca.crt
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:INSTAR
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:debian11.fritz.box
Email Address []:
chown mosquitto:mosquitto ca.{crt,key}
Server Certificates
openssl genrsa -out server.key 4096
Important: Here the FQDN must be the hostname, otherwise you might end up with SSL errors. As mentioned above my server can be reached via the hostname debian11
- I can test this by visiting the mosquitto webserver http://debian11:8080/
:
openssl req -new -out server.csr -key server.key
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:INSTAR
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:debian11
Email Address []:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 1825
Signature ok
subject=C = AU, ST = Some-State, O = INSTAR, CN = debian11
Getting CA Private Key
chown mosquitto:mosquitto server.{csr,key,crt}
The certs
directory should now contain the following files:
-rw-r--r-- 1 mosquitto mosquitto 1956 Feb 16 20:31 ca.crt
-rw------- 1 mosquitto mosquitto 3243 Feb 16 20:30 ca.key
-rw-r--r-- 1 root root 41 Feb 16 20:37 ca.srl
-rw-r--r-- 1 mosquitto mosquitto 1834 Feb 16 20:37 server.crt
-rw-r--r-- 1 mosquitto mosquitto 1659 Feb 16 20:37 server.csr
-rw------- 1 mosquitto mosquitto 3243 Feb 16 20:34 server.key
Mosquitto Server Configuration
Add the following configuration to /etc/mosquitto/conf.d/custom.conf
:
# -----------------------------------------------------------------
# Certificate based SSL/TLS support
# -----------------------------------------------------------------
listener 8883
tls_version tlsv1.2
cafile /etc/mosquitto/certs/ca.crt
certfile /etc/mosquitto/certs/server.crt
keyfile /etc/mosquitto/certs/server.key
Then restart the service:
service mosquitto restart && service mosquitto status
Testing the Connection
All you need to establish a server connection is the ca.crt
file on your client machine. Then you can try to subscribe to the last-will topic of your camera and should receive it's online status:
mosquitto_sub -h debian11 -t 'cameras/117/status/connection' -p 8883 --insecure --cafile ca.crt --tls-version tlsv1.2 -u admin -P instar -v
cameras/117/status/connection {"val":"online"}
cameras/117/status/connection {"val":"offline"}
cameras/117/status/connection {"val":"online"}
Or with the MQTT Explorer:
Add the ca.crt
file here:
Client Certificates
For more security, you can add client certificates, which need to be signed by the server.
Creating a client certificate
Generate client certificates for the MQTT clients. Important: Don’t use the server name as FQDN:
openssl genrsa -out client.key 4096
openssl req -out client.csr -key client.key -new
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:INSTAR
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:mqtt.client
Email Address []:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
openssl x509 -req -in client.csr -CA ca.crt --CAkey ca.key --CAcreateserial -out client.crt -days 1825
Signature ok
subject=C = AU, ST = Some-State, O = INSTAR, CN = mqtt.client
Getting CA Private Key
chown mosquitto:mosquitto client.{csr,crt,key}
Restart the Mosquitto server:
service mosquitto restart && service mosquitto status
Update the Mosquitto Server Configuration
To enforce the usage of client certificates, you will need to add require_certificate true
to your listener configuration:
# -----------------------------------------------------------------
# Certificate based SSL/TLS support
# -----------------------------------------------------------------
listener 8883
tls_version tlsv1.2
cafile /etc/mosquitto/certs/ca.crt
certfile /etc/mosquitto/certs/server.crt
keyfile /etc/mosquitto/certs/server.key
require_certificate true
Testing the Connection
mosquitto_sub -h debian11 -t 'cameras/117/status/connection' -p 8883 --insecure --cafile ca.crt --cert client.crt --key client.key --tls-version tlsv1.2 -u admin -P instar -v
cameras/117/status/connection {"val":"online"}
For the MQTT Explorer upload the Client Key and Cert:
Connect your INSTAR IP Camera
To connect your INSTAR camera you first have to do 2 things:
- Combine the
client.key
andclient.crt
into a single file calledclient.pem
:
-----BEGIN RSA PRIVATE KEY-----
MIIJKAIBAAKCAgEAorc0ouM2Uh0pBlZ5IbCSonwOACUCPQ+FqWjhRl5FbAAke2iK
...
l6hxaLG33DoTvYoEbjBEmLtsBAz4sdnTGi2z6HOYfMsqGjMehPJmr2XH/kA=
-----END RSA PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
MIIFIDCCAwgCFHLf6A9ycbmW6ExF+DBGE3T3qhFAMA0GCSqGSIb3DQEBCwUAMFAx
...
CVSpxYNxMG6gIpeIFrTogygOfdc=
-----END CERTIFICATE-----
- Take the
ca.crt
and save it asca.pem
.
Now open your camera's SSL Cert menu, add the client.pem
as your custom certificate and enable it:
And secondly add the ca.pem
to the Custom CA Store of your camera:
Configure the client to use your MQTT brokers Hostname instead of it's local IP to be able to activate the Verify Certificate option:
Start your MQTT client and check the http://debian11/tmpfs/mqtt-log
- you should see it connect on port 8883
using TLS:
2022-2-18 4:11:11: [Info] Config: Version 2
2022-2-18 4:11:11: [Info] Config: Units loaded: 283
2022-2-18 4:11:11: [Info] Config: Memory required: 40749
2022-2-18 4:11:11: [Info] Authenticate with Mqtt-Broker
2022-2-18 4:11:11: [Info] Activate TLS
2022-2-18 4:11:11: [Info] Connect to Mqtt-Broker debian11 on port 8883...
2022-2-18 4:11:11: [Info] Synchronize Cgi-Server with Mqtt-Broker
2022-2-18 4:11:11: [Info] Mqtt listen thread has been started.
2022-2-18 4:11:11: [Info] Synchronize Cgi-Server with Mqtt-Broker
2022-2-18 4:11:12: [Info] Adapter connected!