Tuesday 1 June 2021

Mosquitto 2.0 + mosquitto-auth-plugin + MySQL

The de facto Mosquitto auth plugin jpmens/mosquitto-auth-plug has been archived since March 2019.  Unfortunately it wasn't handed over to anyone and, as of today, 475+ forks of the project exist.  I decided to get one of these working, although on reflection a better choice may have been the iegomez/mosquitto-go-auth plugin which is currently maintained.  Anyway, this is how I've got the original working on Ubuntu 18.04:

You may or may not need to install the following packages:

    # apt install gcc g++ make xsltproc docbook-xsl libwebsockets-dev libmysqlclient-dev

If an older version of Mosquitto has already been installed, fully remove it:

    # apt purge mosquitto

Pull down the official 2.0 source:

    # wget https://mosquitto.org/files/source/mosquitto-2.0.10.tar.gz
    # tar xvf mosquitto-2.0.10.tar.gz

Inside mosquitto-2.0.10 directory edit config.mk setting:

    WITH_WEBSOCKETS:=yes
    WITH_CJSON:=no


Websockets is only required if you are using websocket connections to Mosquitto.  Somewhat frustratingly I had to set WITH_CJSON:=no otherwise I get a "can't find cjson.h'" type error on Ubuntu 18.04.  Didn't have enough time to investigate further.

Build and install:

    # make
    # make install


Create a mosquitto user and chown certain directories:

    # useradd -r mosquitto
    # mkdir /var/log/mosquitto
    # chown mosquitto:mosquitto /var/log/mosquitto/
    # mkdir /var/lib/mosquitto
    # chown mosquitto:mosquitto /var/lib/mosquitto/


Create the file /etc/systemd/system/mosquitto.service:

    [Unit]
    Description=Mosquitto MQTT v3.1/v3.1.1 server
    Wants=network.target
    Documentation=http://mosquitto.org/documentation/

    [Service]
    Type=simple
    User=mosquitto
    Group=mosquitto
    ExecStart=/usr/local/sbin/mosquitto -c /etc/mosquitto/mosquitto.conf
    Restart=on-failure
    SyslogIdentifier=Mosquitto

    [Install]
    WantedBy=multi-user.target


Pull down this (or your choice of) version of the auth plugin:

    # git clone https://github.com/kmihaylov/mosquitto-auth-plug.git

Inside the mosquitto-auth-plug directory edit a copy of config.mk

    # cp config.mk.in config.mk
    # vi config.mk

Update the following paths as appropriate to your environment

    MOSQUITTO_SRC = <your path>/mosquitto-2.0.10
    OPENSSLDIR = <your path>


hint: "which openssl" should reveal the OpenSSL directory (/usr/bin on my machine).

Next build the auth-plugin:

    # make

You will probably get some errors related to types and include files, for example:

/usr/local/include/mosquitto_plugin.h:167:46: error: unknown type name ‘mosquitto_plugin_id_t’; did you mean ‘mosquitto_property’?

The fix is very simple: rearrange the includes in auth-plug.c and log.c as follows:

    #include <mosquitto_broker.h>
    #include <mosquitto_plugin.h>
    #include <mosquitto.h>

It's probably worth copying the new auth-plug.so to a well known location, for example:

          
# cp auth-plug.so /var/lib/mosquitto

Copy /etc/mosquitto/mosquitto.conf.example to /etc/mosquitto/mosquitto.conf, and add the following line at the bottom:

    include_dir /etc/mosquitto/conf.d

In /etc/mosquitto/conf.d, create auth-plug.conf:

    auth_plugin /<your path>/auth-plug.so
    auth_opt_backends mysql
    auth_opt_log_quiet false
    auth_opt_host <your mysql host>
    auth_opt_port <your mysql port>
    auth_opt_dbname <your mysql schema>
    auth_opt_user <your mysql user>
    auth_opt_pass <your mysql password>
    auth_opt_userquery <your mysql select>
    auth_opt_ssl_enabled true

As this file contains a password, make readble to the mosquitto user only:

    # chown mosquitto:mosquitto auth-plug.conf
    # chmod go-rwx auth-plug.conf


This should be enough to get you going, but beware of these gottchas:

1/ you need the auth_opt_backends option set appropriately.  If you simply cut and paste from the jpmens page you'll likely miss this

2/ in the PBKDF2 examples the salt value is confusing, for example:

    PBKDF2$sha256$901$x8mf3JIFTUFU9C23$Mid2xcgTrKBfBdye6W/4hE3GKeksu00+

The actual salt is "x8mf3JIFTUFU9C23", the auth plugin does not base64 decode it, however the password hash *is* base64 decoded.  Bear this in mind when you populate your database. 

3/ Like me, you may have switched from password file authentication.  If so, make sure you remove the "password_file" option from your mosquitto.conf or else it will continue to use the password file and you'll waste time wondering why the auth plug isn't working.

4/ If the auth-plugin is refusing to authenticate your clients edit the config.mk and add -DPWDEBUG to the CFG_CFLAGS option.  Rebuild the plugin and you'll get additional, helpful, logging in /var/log/mosquitto/mosquitto.log

5/ Mosquitto only:  persistence is configured but still doesn't remember messages?  /var/lib/mosquitto/mosquitto.db not getting any larger?  Check your disk space.  It seems to silently fail when your disk is full.

Finally it does work, it can be frustrating at times, but hang in there.  I hope the above helps.  I have had it working with PBKDF2WithHmacSHA1 and PBKDF2WithHmacSHA256 + many different iterations, salts and key lengths.  It's fantastic.