User Tools

Site Tools


brokers:central_broker

Central broker

mqopen infrastructure

Central broker is main part of network infrastructure. It collects data from all local MQTT brokers and provides data exchange.

Central broker must be available from the public Internet and must be maximally secured. This means that it must accept encrypted connections only and every client have to be authenticated.

Broker implementation is mosquitto. It is open source software, compliant with MQTT version 3.1 and 3.1.1.

This tutorial expects that central broker is run at Virtual Private Server (VPS) with pubic IPv4 address and Debian operating system installed.

SSL connection vs. VPN

There are two ways how to establish encrypted connection between local and central brokers:

  • Configure mosquitto to use SSL connection. Preffered.
  • Setup VPN tunnel and configure mosquitto to listen on tunnel interface only.

Reason for that VPN tunnel is not preferred, it the tunnel itself. There is always possibility that attacker can compromise server with central broker. In that case, he gains access to many devices which can act as gateway to their local network. If some local broker at other side of the tunnel has some exploitable vulnerability, attacker can do pivoting and spread deeper into network.

This is unacceptable risk for many networks and VPN tunnel should not be used.

Central MQTT broker configuration

First of all, let's install mosquitto:

# apt-get install mosquitto

Central broker should be configured with following attributes:

  • Restrict listening interfaces – Configure which interfaces can accept connection.
  • Client authentication – Even if key owners has access to broker, I like to add username/password protection. Credentials are send in plain text, but the are encrypted in VPN tunnel for outside world.

mosquitto creates its default configuration file /etc/mosquitto/mosquitto.conf which looks like this:

/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 /var/run/mosquitto.pid

persistence true
persistence_location /var/lib/mosquitto/

log_dest file /var/log/mosquitto/mosquitto.log

include_dir /etc/mosquitto/conf.d

It specifies persistence directory. This is useful when clients uses messages with retain feature and broker is restarted for some reason. Persistence will save retain messages over broker restarts.

To configure central broker, create configuration file /etc/mosquitto/conf.d/central-broker.conf with following content:

/etc/mosquitto/conf.d/central-broker.conf
# Listen on localhost interface.
bind_address localhost

# Internet listener witch SSL encryption.
listener 1883 <public IP address>
cafile <cafile>
certfile <certfile>
keyfile <keyfile>

# listen on VPN interface. Uncomment this to make mosquitto listen on your VPN interface. 
#listener 1883 <VPN tunnel address>

# User authentication.
password_file <password file>
allow_anonymous false

Following configuration options must be adjusted:

  • listener - Specify public IP address of your server.
  • cafile - Path to your CA file. For example: /etc/mosquitto/ca_certificates/ca.crt.
  • certfile - Path to your cert file. For example: /etc/mosquitto/certs/central-broker.crt.
  • keyfile - Path to your key file. For example: /etc/mosquitto/certs/central-broker.key.
  • password_file - Path o your password file. For example: /etc/mosquitto/mosquitto.passwd.

Next part defines on which addresses mosquitto should listen for incoming connections. Default listener listens on localhost. Another listener directives declare other listen addresses. Listening on localhost is useful for some data processing services which can run on the same machine.

Finally, last part defines user authentication. Unfortunately, authentication is required to clients from all interfaces. It would be great to allow anonymous access from localhost.

Passwords

To authenticate MQTT users, we need to store user names and passwords somewhere. Mosquitto comes with mosquitto_passwd utility for managing password files. To create new file issue following commad:

# mosquitto_passwd -c /etc/mosquitto/mosquitto.passwd testuser

Command asks you for password and store it in hashed form in appropriate file. Unfortunately, this utility cannot accept password via command line argument, so using some generated password is quite complicated.

I also noticed, that command can accept -U option, which updates password file to use hashed password instead of plain text. I don't know why, but it re-hash already hashed passwords. This makes this feature little bit useless.

systemd unit (optional)

By default, mosquitto doesn't use standard systemd unit. It is started using traditional System V script located at /etc/init.d/mosquitto. You can check this by following command:

# systemctl status mosquitto
● mosquitto.service - LSB: mosquitto MQTT v3.1 message broker
   Loaded: loaded (/etc/init.d/mosquitto)
   Active: active (running) since Tue 2015-09-29 14:41:55 CEST; 9s ago
   CGroup: /system.slice/mosquitto.service
           └─3037 /usr/sbin/mosquitto -c /etc/mosquitto/mosquitto.conf

I like modern systemd units, which runs services in foreground. So let's create is. Stop current mosquitto service at first:

# systemctl stop mosquitto
# update-rc.d mosquitto remove
# rm /etc/init.d/mosquitto

Now create systemd unit file /etc/systemd/system/mosquitto.service with following content:

/etc/systemd/system/mosquitto.service
[Unit]
Description=MQTT v3.1 message broker

# If mosquitto is not cofigured to listen on VPN interface.
After=network.target

# If you are listening on VPN interface, instruct systemd that it should wait 
# until VPN service is started up.
#After=network.target openvpn-server@buben-vps.service
#Wants=network.target openvpn-server@buben-vps.service
 
[Service]
Type=simple
ExecStart=/usr/sbin/mosquitto -c /etc/mosquitto/mosquitto.conf
Restart=always
 
[Install]
WantedBy=multi-user.target

Lets talk about systemd unit configuration directives little bit. Requires directive specifies that this unit needs active network.target unit and openvpn-server@buben-vps.service unit. If any unit listed there is stopped or fails, this unit will be stopped as well. After directive defines activation order. Activation of this unit is delayed until all units listed at After directive are started up.

Both After and Requires directives has same values. network.target tells that service should be started after network related stuff is initialized (such as initialization of TCP/IP stack). This dependecy is much more important for shut-down procedure. It instructs systemd that this service should be terminated before network connectivity. This ensures that broker can nicely close all its connections. For more information about systemd network targets, you can read official Running Services After the Network is up page.

openvpn-server@buben-vps.service defines dependency on service which provides VPN connectivity. If mosquitto is configured to listen at VPN tunnel IP address, this service must be started up before mosquitto gets activated.

Other configuration directives are self explanatory. If you are not sure about their meaning, check systemd documentation.

After unit file is created, reload systemd configuration, enable unit and start it up:

# systemctl daemon-reload
# systemctl enable mosquitto
# systemctl start mosquitto
brokers/central_broker.txt · Last modified: 2016/05/09 10:24 (external edit)