MQTT - Mosquitto MQTT Broker setup on the Ubuntu 20.04

 I quoted a lot from "How to Install and Secure the Mosquito MQTT Messaging Broker on Ubuntu 18.04".

MQTT is a machine-to-machine messaging protocol, designed to provide lightweight publish/subscribe communication to “Internet of Things” devices. It is commonly used for geo-tracking fleets of vehicles, home automation, environmental sensor networks, and utility-scale data collection.
Mosquitto is a popular MQTT server (or broker, in MQTT parlance) that has great community support and is easy to install and configure. 

MQTT is often thought of only as IoT platform and applied to devices such as Arduino and many sensors. However, Message Queue (MQ) is a protocol that has long been used to deliver asynchronous messages.  It can be applied to various applications for asynchronous message delivery. The Public, Subscribe model for a particular topic can also be useful for implementing chat rooms, etc. There are rumors that Facebook's messenger actually used Mosquito.(This is something I haven't confirmed yet.)


MQTT communication architecture

MQTT does not consist of a client-server structure like HTTP, normal TCP, etc., but consists of a broker, publisher, and subscriber structure.


<MQTT Publish / Subscribe Architecture from https://mqtt.org/>

A Publisher publishes a Topic, and a Subscriber subscribes to a Topic. Broker acts as a relay between them, and since multiple subscribers can subscribe to a single topic, it is also very useful for establishing 1:N communication.


MQTT Brokers

The role of the broker that mediates messages in the middle is important, and the software that plays this role is called an MQTT broker (server).


<MQTT brokers from https://mqtt.org/software/>

https://mqtt.org/software/ introduces numerous MQTT brokers. Among them, there are products that are used, and there are products that are open source and available for free.
The most popular of these open source products is Mosquitto from the Eclipse Foundation. There are many brokers that can implement MQTT, but I will explain using the most popular and easily accessible mosquitto.


MQTT Topic

Publishers and Subscribers work on a per-topic basis. Topics can be hierarchically organized using forward slashes (/), so that a large number of sensor devices can be efficiently managed. For example, if you have a sensor that measures various states of your computer, you could configure it as follows.

If you've ever implemented the HTTP Restful API, you'll know that forward slashes ("/") in URIs are used to separate resources.

In MQTT, topics can also be separated using forward slashes, so that subscribers and publishers can process messages efficiently.


<topic> 

If your subscriber wants to receive temperature, brightness, and CO2 density from all three topics belonging to /Home/Kitchen, you can do it at once with "/Home/Kitchen/#".


MQTT QoS level

QoS-related information brought from

MQTT has its origins in IBM's Message Queue. Message Queue uses TCP/IP but uses an asynchronous transmission method. Therefore, even when the communication of subscribe is cut off, the broker can keep the message and send it when communication is restored.

However, if all messages are processed in this way, the load is large, so MQTT can be used in three QoS modes.

MQTT provides 3 QOS levels-

  • QOS 0 – Once (not guaranteed)
  • QOS 1 – At Least Once (guaranteed)
  • QOS 2 – Only Once (guaranteed)

QOS 0 –  Once

This is the fastest method and requires only 1 message. It is also the most unreliable transfer mode. The message is not stored on the sender, and is not acknowledged. The message will be delivered only once, or not at all. Once the message has been sent by the client it is deleted from the outbound message queue. Therefore with this QOS level there is no possibility of duplicate messages.


QOS 1 – At Least Once

This level guarantees that the message will be delivered at least once, but may be delivered more than once. (See Flow Diagram on right.) Publishing with QOS of 1 requires 2 messages. The sender sends a message and waits for an acknowledgement (PUBACK).

If it receives an acknowledgement then it notifies the client app, and deletes the message from the outbound queue.. If it doesn’t receive an acknowledgement it will resend the message with the DUP flag set (Duplicate Flag). The message will continue to be resent at regular intervals, until the sender receives an acknowledgement.


QOS 2 – Only Once

This level guarantees that the message will be delivered only once. This is the slowest method as it requires 4 messages.

  1. The sender sends a message and waits for an acknowledgement (PUBREC)
  2. The receiver sends a PUBREC message
  3. If the sender doesn’t receive an acknowledgement ( PUBREC)  it will resend the message with the DUP flag set.
  4. When the sender receives an acknowledgement message PUBREC it then sends a message release message (PUBREL). The message can be deleted from the queue.
  5. If the receiver doesn’t receive the PUBREL it will resend the PUBREC message
  6. When the receiver receives the PUBREL message it can now forward the message onto any subscribers.
  7. The receiver then send a publish complete (PUBCOMP) .
  8. If the sender doesn’t receive the PUBCOMP message it will resend the PUBREL message.
  9. When the sender receives the PUBCOMP the process is complete and it can delete the message from the outbound queue, and also the message state.


Installation

 First of all, I will install Mosquito MQTT Broker in Ubuntu. Eclipse Mosquitto is an open source (EPL/EDL licensed) message broker that implements the MQTT protocol versions 5.0, 3.1.1 and 3.1. Mosquitto is lightweight and is suitable for use on all devices from low power single board computers to full servers.

Installation is very simple. I will install Mosquito client for testing.

root@ubuntusrv:/# apt-get update
root@ubuntusrv:/# apt-get  install mosquitto mosquitto-clients

 

Simple Test

By default, Ubuntu will start the Mosquitto service after install. 

root@ubuntusrv:/etc/mosquitto/certs# service --status-all
 [ + ]  apparmor
 [ + ]  apport
 [ + ]  atd
 [ - ]  console-setup.sh
 [ + ]  cron
 [ - ]  cryptdisks
 [ - ]  cryptdisks-early
 [ + ]  dbus
 [ + ]  grub-common
 [ - ]  hwclock.sh
 [ + ]  irqbalance
 [ - ]  iscsid
 [ - ]  keyboard-setup.sh
 [ + ]  kmod
 [ - ]  lvm2
 [ - ]  lvm2-lvmpolld
 [ + ]  mosquitto
 [ + ]  multipath-tools
 [ - ]  open-iscsi
 [ + ]  open-vm-tools
 [ - ]  plymouth
 [ - ]  plymouth-log
 [ + ]  procps
 [ - ]  rsync
 [ + ]  rsyslog
 [ - ]  screen-cleanup
 [ + ]  ssh
 [ + ]  udev
 [ + ]  ufw
 [ + ]  unattended-upgrades
 [ - ]  uuidd 

 

 Let’s test the default configuration. We’ll use one of the Mosquitto clients we just installed to subscribe to a topic on our broker.
Topics are labels that you publish messages to and subscribe to. They are arranged as a hierarchy, so you could have sensors/outside/temp and sensors/outside/humidity, for example. How you arrange topics is up to you and your needs. Throughout this tutorial we will use a simple test topic to test our configuration changes.

Log in to your server a second time, so you have two terminals side-by-side. In the new terminal, use mosquitto_sub to subscribe to the test topic:

root@ubuntusrv:/# mosquitto_sub -t test

-t is the topic name. You’ll see no output after hitting ENTER because mosquitto_sub is waiting for messages to arrive. Switch back to your other terminal and publish a message:

 The options for mosquitto_pub are the same as mosquitto_sub, though this time we use the additional -m option to specify our message. Hit ENTER, and you should see hello world pop up in the other terminal. You’ve sent your first MQTT message!

root@ubuntusrv:/# mosquitto_pub -t "test" -m "hello world" 

 

 <test screen>

 mosquitto_sub, mosquitto_pub are both mosquitto client programs.

The example above is tested locally. In most cases, we will probably communicate with different hosts, so we will test them on different hosts.


Test MQTT on Different Hosts

To test MQTT on different hosts, you can use the -h option to specify the host on which the MQTT broker is working.


On different hosts, you can see the same output coming from the mosquitto_sub program that subscribed the test topic.


Access Control with ID/Password

Let’s configure Mosquitto to use passwords. Mosquitto includes a utility to generate a special password file called mosquitto_passwd. This command will prompt you to enter a password for the specified username, and place the results in /etc/mosquitto/passwd.

root@ubuntusrv:/# mosquitto_passwd -c /etc/mosquitto/passwd your_id 

This command will create or update  passwd files that includes your_id and its encrypted password
Now we’ll open up a new configuration file for Mosquitto and tell it to use this password file to require logins for all connections:

root@ubuntusrv:/# vim /etc/mosquitto/conf.d/default.conf
 
root@ubuntusrv:/# cat /etc/mosquitto/conf.d/default.conf
allow_anonymous false
password_file /etc/mosquitto/passwd 

"allow_anonymous false" will disable all non-authenticated connections, and the password_file line tells Mosquitto where to look for user and password information. Save and exit the file.

CentOS users

If you are using CentOS, you might not find /etc/mosquitto/conf.d directory. In this case, modify the /etc/mosquitto/mosquito.conf file, 

# vim /etc/mosquitto/mosquitto.conf

#### Add the following lines to the bottom of the file. 

allow_anonymous false
password_file /etc/mosquitto/passwd 


Now restart the mosquitto broker again.

root@ubuntusrv:/# systemctl restart mosquitto

From now on, access to the Mosquito broker is only possible by using id/password.



Secure communication over SSL

Before you can use SSL, you must create a certificate. I will use the script file provided by https://github.com/owntracks/tools/blob/master/TLS/generate-CA.sh.

The ifconfig command must be installed to use this script. In recent Ubuntu or CentOS, the ipaddr command is mainly used, so it may not be installed. If the ifconfig command is not installed, install net-tools first.

root@ubuntusrv:/# apt-get install net-tools


Create certificates in the /etc/mosquitto/certs directory. First download the generate-CA.sh file. And modify the IP and host information at the beginning of the script file.

#	IPLIST="172.13.14.15 192.168.1.1"
#	HOSTLIST="a.example.com b.example.com"

IPLIST="211.53.210.33"    # Enter Your IP list
HOSTLIST="myhost_pbx"     # Enter Your Hostname list


Then run the script.

root@ubuntusrv:/etc/mosquitto/certs# wget https://github.com/owntracks/tools/raw/master/TLS/generate-CA.sh
root@ubuntusrv:/etc/mosquitto/certs# chmod 755 generate-CA.sh
root@ubuntusrv:/etc/mosquitto/certs# ./generate-CA.sh 

Be Careful : The "generate-CA.sh" file creates a certificate with a validity of 825 days. If you want to change the duration, find and modify "825" in the script file.

Now the cert directory looks like this. Files that start with ubuntusrv will be renamed on your computer. This value is the hostname.

root@ubuntusrv:/etc/mosquitto/certs# ls -al
total 48
drwxr-xr-x 2 root root 4096 Oct  7 12:40 .
drwxr-xr-x 5 root root 4096 Oct  7 11:59 ..
-r--r--r-- 1 root root 2041 Oct  7 12:40 ca.crt
-r-------- 1 root root 3272 Oct  7 12:40 ca.key
-rw-r--r-- 1 root root   41 Oct  7 12:40 ca.srl
-rwxr-xr-x 1 root root 8835 Oct  7 12:31 generate_CA.sh
-rw-r--r-- 1 root root  130 Mar  3  2020 README
-r--r--r-- 1 root root 2634 Oct  7 12:40 ubuntusrv.crt
-rw-r--r-- 1 root root 1695 Oct  7 12:40 ubuntusrv.csr
-r-------- 1 root root 3243 Oct  7 12:40 ubuntusrv.key

Paste in the following at the end of the file, leaving the two lines we already added:

root@ubuntusrv:/etc/mosquitto/conf.d# cat default.conf
allow_anonymous false
password_file /etc/mosquitto/passwd


listener 8883
cafile /etc/mosquitto/certs/ca.crt
certfile /etc/mosquitto/certs/ubuntusrv.crt
keyfile /etc/mosquitto/certs/ubuntusrv.key
 
 

Again, be sure to leave a trailing newline at the end of the file.

"listener 8883" sets up an encrypted listener on port 8883. This is the standard port for MQTT + SSL, often referred to as MQTTS. The next three lines, certfile, cafile, and keyfile, all point Mosquitto to the appropriate Let’s Encrypt files to set up the encrypted connections. Save and exit the file, then restart Mosquitto to update the settings:

Now restart the mosquitto broker again.

root@ubuntusrv:/# systemctl restart mosquitto


Update the firewall to allow connections to port 8883 if you are using the ufw firewall.

root@ubuntusrv: # ufw allow 8883

Output
Rule added
Rule added (v6)

Copy the ca.crt file to a remote computer that communicates with the Mosquitto Broker. The ca.crt file can be created using copy/paste.

spypiggy@ubuntu:~$ cd /etc
spypiggy@ubuntu:/etc$ sudo mkdir -p mosquitto/certs
spypiggy@ubuntu:/etc$ cd mosquitto/certs/
spypiggy@ubuntu:/etc/mosquitto/certs$ vim ca.crt
spypiggy@ubuntu:/etc/mosquitto/certs$ sudo vim ca.crt


You can see that SSL-enabled communications with id/password are working properly.


Procotols

MQTT has two communication protocols. One is mqtt and the other is websocket.

And these two protocols can use security protocols using SSL. Therefore, four protocols can be used. The following is the protocol and port settings section of the mosquitto.conf file.


#This is MQTT Protocol
port 1883
protocol mqtt

#This is Secure MQTT Protocol
listener 8883
protocol mqtt
cafile /etc/mosquitto/CA/ca.crt
certfile /etc/mosquitto/CA/ubuntu.crt
keyfile /etc/mosquitto/CA/ubuntu.key


#This is Websocket Protocol
listener 9001
protocol websockets

#This is Secure Websocket Protocol
listener 9003
protocol websockets
cafile /etc/mosquitto/CA/ca.crt
certfile /etc/mosquitto/CA/tubuntu.crt
keyfile /etc/mosquitto/CA/ubuntu.key


If you set it as above, you can check the port information as follows.

[root@ubuntu]# netstat -nltp|grep mosquitto
tcp        0      0 0.0.0.0:8883            0.0.0.0:*               LISTEN      277738/mosquitto    
tcp        0      0 0.0.0.0:1883            0.0.0.0:*               LISTEN      277738/mosquitto    
tcp6       0      0 :::9001                 :::*                    LISTEN      277738/mosquitto    
tcp6       0      0 :::9003                 :::*                    LISTEN      277738/mosquitto    
tcp6       0      0 :::8883                 :::*                    LISTEN      277738/mosquitto    
tcp6       0      0 :::1883                 :::*                    LISTEN      277738/mosquitto  


Test Secured MQTT on Different Hosts

If you want to test MQTTS on a remote client, you need to be careful about the hostname.

You should use hostnames instead of IP addresses. Files using the host name from the certificate I created earlier were created. Therefore, modify and use the hosts file of the client you want to test.

If it is Windows, edit the hosts file in the following directory. You must edit the file with administrator privileges to save it.


An error may occur if you use the host's IP address as shown below. The following is a test using the secured mqtt protocol.

C:\Users\spypi>mosquitto_pub -h 211.53.209.60 -p 8883 --cafile d:\temp\ca.crt  -t test -u dongu -P dongdong  -m "Hello"
Error: protocol error
C:\Users\spypi>mosqui
tto_pub -h ubuntusrv -p 8883 --cafile d:\temp\ca.crt  -t test -u dongu -P dongdong  -m "Hello"


If you are a Linux client, you can use it by editing the /etc/hosts file.


Wrapping Up

 The process of installing and testing the Mosquito MQTT Broker is not difficult. We also tested id/pw application and SSL communication. Next, use MQTTcla instead of Mosquito_sub, Mosquito_pub. I'll try to test it by implementing it myself.

If you are interested in mqt client implemented by Python, see MQTT - Python Client.

If you are interested in mqt client implemented by c/c++, see MQTT - c/c++ Client.

 

Useful links 



 

댓글

이 블로그의 인기 게시물

Connecting to SQL Server on Raspberry Pi

Making VoIP Phone Using Raspberry Pi