Install the Mosquitto MQTT Broker on Ubuntu
Review the following guide for installing the Mosquitto MQTT broker on Ubuntu. Once installed, you can connect to the following connectors in Manufacturing Connect Edge:
- MQTT - Generic TCP
- MQTT - Generic over SSL.
Before You Begin
Make sure you do the following:
- Verify the Ubuntu OS is 19.10.
- Use a Virtual Machine on VirtualBox 6.0 to install Ubuntu.
- Verify that the Virtual Machine has two configured network adapters that are set as follows:
- Adapter 1 is set to Bridged Adapter
- Adapter 2 is set to NAT
Step 1: Install Net Tools
To install net tools:
- From a command prompt, enter sudo apt install net-tools, and press ENTER.
- If asked to provide your password, enter the password and press ENTER.
Step 2: Install MQTT Broker
To install the MQTT broker:
- From a command prompt, enter sudo apt-get update and press ENTER.
- If asked to provide your password, enter the password and press ENTER.
- Enter sudo apt-get install mosquitto and press ENTER.
- Enter Y and press ENTER to continue. The MQTT broker is installed.
Step 3: Install MQTT Client
You can install the MQTT client to test the MQTT broker configuration.
To install the MQTT client:
- Enter sudo apt-get install mosquitto-clients and press ENTER.
- Enter Y and press ENTER to continue. The MQTT client is installed.
Step 4: Test Initial Installation
You can verify that the MQTT broker and client are correctly installed.
To test the initial installation:
- Enter mosquitto_sub -t "test" and press ENTER.
- Right-click the Terminal icon and select New Window to open a second terminal window.
- Select the second terminal window.
- Enter mosquitto_pub -m "message from mosquitto_pub client" -t "test" and press ENTER.
- Select the first terminal window to view the message sent from the second terminal window. You should see: message from mosquitto_pub client
- Press Ctrl+C to exit the first terminal window.
Step 5: Set Up Username and Password
To set up a username and password:
- Enter sudo mosquitto_passwd -c /etc/mosquitto/passwd <username> and press ENTER. For example: sudo mosquitto_passwd -c /etc/mosquitto/passwd JohnSmith
- Enter a password for the username at the prompt and press ENTER.
- Re-enter the password and press ENTER.
- Enter sudo nano /etc/mosquitto/conf.d/default.conf and press ENTER to edit the default.conf file. The default.conf file opens in the nano editor. You can enforce refusal of connections from anonymous users and provide the path of the file holding all users and passwords from this file.
- Copy or enter the following two lines into the file. allow_anonymous false password_file /etc/mosquitto/passwd
- Press Ctrl+O to save the changes.
- Press ENTER. The changes are verified.
- Press Ctrl+X to exit the nano editor.
- From the terminal window, enter sudo ufw allow 1883 and press ENTER. The rule is applied. This rule ensures that the firewall allows connections on port 1883. This is the default port for the Mosquitto MQTT broker and is used for a connection using the username and password.
- Enter sudo systemctl restart mosquitto and press ENTER. Mosquitto restarts so the new configuration and rule can be used.
Step 6: Test Username and Password Requirements
To test the username and password requirements:
- Enter mosquitto_sub -t "test" -u "<username>" -P "<userpassword>" and press ENTER. For example: mosquitto_sub -t "test" -u "JohnSmith" -P "XYZcorp@1"
- Open a second terminal window if you have closed it and select it.
- Enter mosquitto_pub -t "test" -m "message from mosquitto_pub client" and press ENTER to try to connect a publisher without using the correct username and password. The connection is refused. You should see: connection error: Connection Refused: not authorized.
- Enter mosquitto _pub -t "test" -m "message from mosquitto_pub client" -u "<username>" -P "<password>" and press ENTER to connect using the correct username and password.
- Select the first terminal window. View the message: message from mosquitto_pub client in the first Terminal window.
- Press Ctrl+C to exit the subscription stage in the first Terminal window.
Step 7: Enable SSL/TSL
You can create certificates and keys in the Ubuntu system home directory.
Important: If you decide not to use the bash file for the following task and instead use either the commands individually or follow other guides available, you must use the FQDN (Fully qualified domain name) for the CN (Common Name). Never use the IP address.
Refer to the following content for step 2.
#!/usr/bin/env bash
#(@)generate-CA.sh - Create CA key-pair and server key-pair
signed by CA
# Copyright (c) 2013-2016 Jan-Piet Mens <jpmens()gmail.com>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with
or without
# modification, are permitted provided that the following
conditions are met:
#
# 1. Redistributions of source code must retain the above
copyright notice,
# this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the
above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the
distribution.
# 3. Neither the name of mosquitto nor the names of its
# contributors may be used to endorse or promote
products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
OR OTHERWISE)
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
# Usage:
# ./generate-CA.sh
creates ca.crt and server.{key,crt}
# ./generate-CA.sh hostname
creates hostname.{key,crt}
# ./generate-CA.sh client email
creates email.{key,crt}
#
# Set the following optional environment variables before
invocation
# to add the specified IP addresses and/or hostnames to the
subjAltName list
# These contain white-space-separated values
#
# IPLIST="172.13.14.15 192.168.1.1"
# HOSTLIST="a.example.com b.example.com"
set -e
export LANG=C
kind=server
if [ $# -ne 2 ]; then
kind=server
host=$(hostname -f)
if [ -n "$1" ]; then
host="$1"
fi
else
kind=client
CLIENT="$2"
fi
[ -z "$USER" ] && USER=root
DIR=${TARGET:='.'}
# A space-separated list of alternate hostnames (subjAltName)
# may be empty ""
ALTHOSTNAMES=${HOSTLIST}
ALTADDRESSES=${IPLIST}
CA_ORG='/O=OwnTracks.org/OU=generate-CA/[email protected]'
CA_DN="/CN=An MQTT broker${CA_ORG}"
CACERT=${DIR}/ca
SERVER="${DIR}/${host}"
SERVER_DN="/CN=${host}$CA_ORG"
keybits=2048
openssl=$(which openssl)
MOSQUITTOUSER=${MOSQUITTOUSER:=$USER}
# Signature Algorithm. To find out which are supported by
your
# version of OpenSSL, run `openssl dgst -help` and set your
# signature algorithm here. For example:
#
# defaultmd="-sha256"
#
defaultmd="-sha512"
function maxdays() {
nowyear=$(date +%Y)
years=$(expr 2032 - $nowyear)
days=$(expr $years '*' 365)
echo $days
}
function getipaddresses() {
/sbin/ifconfig |
grep -v tunnel |
sed -En '/inet6? /p' |
sed -Ee 's/inet6? (addr:)?//' |
awk '{print $1;}' |
sed -e 's/[%/].*//' |
egrep -v '(::1|127\.0\.0\.1)'
# omit loopback to add it later
}
function addresslist() {
ALIST=""
for a in $(getipaddresses); do
ALIST="${ALIST}IP:$a,"
done
ALIST="${ALIST}IP:127.0.0.1,IP:::1,"
for ip in $(echo ${ALTADDRESSES}); do
ALIST="${ALIST}IP:${ip},"
done
for h in $(echo ${ALTHOSTNAMES}); do
ALIST="${ALIST}DNS:$h,"
done
ALIST="${ALIST}DNS:localhost"
echo $ALIST
}
days=$(maxdays)
if [ -n "$CAKILLFILES" ]; then
rm -f $CACERT.??? $SERVER.??? $CACERT.srl
fi
if [ ! -f $CACERT.crt ]; then
# ____ _
# / ___| / \
# | | / _ \
# | |___ / ___ \
# \____/_/ \_\
#
# Create un-encrypted (!) key
$openssl req -newkey rsa:${keybits} -x509 -nodes
$defaultmd -days $days -extensions v3_ca -keyout
$CACERT.key -out $CACERT.crt -subj "${CA_DN}"
echo "Created CA certificate in $CACERT.crt"
$openssl x509 -in $CACERT.crt -nameopt multiline
-subject -noout
chmod 400 $CACERT.key
chmod 444 $CACERT.crt
chown $MOSQUITTOUSER $CACERT.*
echo "Warning: the CA key is not encrypted; store it
safely!"
fi
if [ $kind == 'server' ]; then
# ____
# / ___| ___ _ ____ _____ _ __
# \___ \ / _ \ '__\ \ / / _ \ '__|
# ___) | __/ | \ V / __/ |
# |____/ \___|_| \_/ \___|_|
#
if [ ! -f $SERVER.key ]; then
echo "--- Creating server key and signing
request"
$openssl genrsa -out $SERVER.key $keybits
$openssl req -new $defaultmd \
-out $SERVER.csr \
-key $SERVER.key \
-subj "${SERVER_DN}"
chmod 400 $SERVER.key
chown $MOSQUITTOUSER $SERVER.key
fi
if [ -f $SERVER.csr -a ! -f $SERVER.crt ]; then
# There's no way to pass subjAltName on the
CLI so
# create a cnf file and use that.
CNF=`mktemp /tmp/cacnf.XXXXXXXX` ||
{ echo "$0: can't create temp file" >&2; exit 1; }
sed -e 's/^.*%%% //' > $CNF <<\!ENDconfig
%%% [ JPMextensions ]
%%% basicConstraints
= critical,CA:false
%%% nsCertType
= server
%%% keyUsage
= nonRepudiation, digitalSignature, keyEncipherment
%%% nsComment
= "Broker Certificate"
%%% subjectKeyIdentifier
= hash
%%% authorityKeyIdentifier
= keyid,issuer:always
%%% subjectAltName
= $ENV::SUBJALTNAME
%%% # issuerAltName
= issuer:copy
%%% ## nsCaRevocationUrl
= http://mqttitude.org/carev/
%%% ## nsRevocationUrl
= http://mqttitude.org/carev/
%%% certificatePolicies
= ia5org,@polsection
%%%
%%% [polsection]
%%% policyIdentifier
= 1.3.5.8
%%% CPS.1
= "http://localhost"
%%% userNotice.1
= @notice
%%%
%%% [notice]
%%% explicitText
= "This CA is for a local MQTT broker installation only"
%%% organization
= "OwnTracks"
%%% noticeNumbers
= 1
!ENDconfig
SUBJALTNAME="$(addresslist)"
export SUBJALTNAME
# Use environment. Because I can. ;-)
echo "--- Creating and signing server
certificate"
$openssl x509 -req $defaultmd \
-in $SERVER.csr \
-CA $CACERT.crt \
-CAkey $CACERT.key \
-CAcreateserial \
-CAserial "${DIR}/ca.srl" \
-out $SERVER.crt \
-days $days \
-extfile ${CNF} \
-extensions JPMextensions
rm -f $CNF
chmod 444 $SERVER.crt
chown $MOSQUITTOUSER $SERVER.crt
fi
else
# ____ _ _ _
# / ___| (_) ___ _ __ | |_
# | | | | |/ _ \ '_ \| __|
# | |___| | | __/ | | | |_
# \____|_|_|\___|_| |_|\__|
#
if [ ! -f $CLIENT.key ]; then
echo "--- Creating client key and signing
request"
$openssl genrsa -out $CLIENT.key $keybits
CNF=`mktemp /tmp/cacnf-req.XXXXXXXX` ||
{ echo "$0: can't create temp file" >&2; exit 1; }
# Mosquitto's use_identity_as_username
takes the CN attribute
# so we're populating that with the
client's name
sed -e 's/^.*%%% //' >
$CNF <<!ENDClientconfigREQ
%%% [ req ]
%%% distinguished_name
= req_distinguished_name
%%% prompt
= no
%%% output_password
= secret
%%%
%%% [ req_distinguished_name ]
%%% # O
= OwnTracks
%%% # OU
= MQTT
%%% # CN
= Suzie Smith
%%% CN
= $CLIENT
%%% # emailAddress
= $CLIENT
!ENDClientconfigREQ
$openssl req -new $defaultmd \
-out $CLIENT.csr \
-key $CLIENT.key \
-config $CNF
chmod 400 $CLIENT.key
fi
if [ -f $CLIENT.csr -a ! -f $CLIENT.crt ]; then
CNF=`mktemp /tmp/cacnf-cli.XXXXXXXX` ||
{ echo "$0: can't create temp file" >&2; exit 1; }
sed -e 's/^.*%%% //' > $CNF
<<\!ENDClientconfig
%%% [ JPMclientextensions ]
%%% basicConstraints
= critical,CA:false
%%% subjectAltName
= email:copy
%%% nsCertType
= client,email
%%% extendedKeyUsage
= clientAuth,emailProtection
%%% keyUsage
= digitalSignature, keyEncipherment, keyAgreement
%%% nsComment
= "Client Broker Certificate"
%%% subjectKeyIdentifier
= hash
%%% authorityKeyIdentifier
= keyid,issuer:always
!ENDClientconfig
SUBJALTNAME="$(addresslist)"
export SUBJALTNAME
# Use environment. Because I can. ;-)
echo "--- Creating and signing client
certificate"
$openssl x509 -req $defaultmd \
-in $CLIENT.csr \
-CA $CACERT.crt \
-CAkey $CACERT.key \
-CAcreateserial \
-CAserial "${DIR}/ca.srl" \
-out $CLIENT.crt \
-days $days \
-extfile ${CNF} \
-extensions JPMclientextensions
rm -f $CNF
chmod 444 $CLIENT.crt
fi
fiTo enable SSL/TSL:
- From a terminal window, enter nano and press ENTER.
- Copy the content above and paste it into the nano editor.
- Press Ctrl+O to save the changes.
- Enter generate-CA.sh to provide the file name and press ENTER. The file is created.
- Press Ctrl+X to exit the nano editor. The file is in your default directory.
- Enter sudo chmod 774 <filename> and press ENTER to set permissions. For example: sudo chmod 774 generate-CA.sh
- Enter sudo ./<filename> and press ENTER execute the bash file and create the certificates. For example: Example: sudo ./generate-CA.sh The bash file is executed. You should see: JohnSmith@JohnSmith-virtualBox: ~$ ./generate-CA.sh Generating a RSA private key The certificates and key files are in your home directory.
- Enter sudo cp ca.crt /etc/mosquitto/ca_certificates and press ENTER to copy the ca.crt to the correct folder.
- Enter sudo cp <your FQDN>.crt /etc/mosquitto/certs and press ENTER to copy the file containing the FQDN.crt to the correct folder. For example: sudo cp JohnSmith-VirtualBox.crt /etc/mosquitto/certs
- Enter sudo cp <your FQDN>.key /etc/mosquitto/certs to copy the server certificate which has the file name <your FQDN>.key. For example: sudo cp JohnSmith-VirtualBox.key /etc/mosquitto/certs
- Enter sudo nano /etc/mosquitto/conf.d/default.conf and press ENTER to allow for SSL encryption. The default.conf file opens.
- Move your cursor down using the arrow keys and paste the following lines: # Plain MQTT protocol listener 1883 # End of plain MQTT configuration # MQTT over TLS/SSL listener 8883 cafile /etc/mosquitto/ca_certificates/ca.crt certfile /etc/mosquitto/certs/<your FQDN>.crt keyfile /etc/mosquitto/certs/<your FQDN>.key require_certificate false # End of MQTT over TLS/SLL configuration
- Press Ctrl+O to save the changes.
- Press ENTER, and then press Ctrl+X to exit the nano editor.
- Enter sudo ufw allow 8883 and press ENTER to allow SSL encrypted connections on port 8883. The rule is applied.
- Enter sudo systemctl restart mosquitto and press ENTER to run the Mosquitto broker using the new configuration and rule.
Step 8: Test Certificates, Username, and Password Requirements
To test the certificates, username, and password requirements:
- Enter mosquitto_sub --cafile /etc/mosquitto/ca_certificates/ca.crt -h <Host IP> -t "test" -p8883 -d -u "<username>" -P "<password>" and press ENTER to create a subscription. For example: mosquitto_sub --cafile /etc/mosquitto/ca_certificates/ca.crt -h 192.168.1.11 -t "test" -p 8883 -d -u "JohnSmith" -P "XYZcorp@1"
- Open a second terminal window if previously closed and select it.
- Enter mosquitto_pub -h <Host IP> -t "test" -m "hello" -p 8883 -d -u "<username>" -P "<password>" --cafile /etc/mosquitto/ca_certificates/ca.crt and press ENTER to publish a message. For example: mosquitto_pub -h 192.168.1.11 -t "test" -m "hello" -p 8883 -d -u "JohnSmith" -P "XYZcorp@1" --cafile /etc/mosquitto/ca_certificates/ca.crt
- Select the first Terminal window to view the message hello.
- Press Ctrl+C to exit the subscription stage in the first terminal window.

