Settings

Theme

Secure your MQTT server with authentication and encryption

jurian.slui.mn

88 points by juriansluiman 5 years ago · 29 comments

Reader

fullstop 5 years ago

I found it to be much easier to put haproxy in TCP mode in front of mosquitto than to use mosquitto's TLS capabilities. This lets me reload the certificate without restarting mosquitto.

My local devices (esp8266) can't really handle TLS well, but I want access from outside of my local network to be encrypted. This lets them operate in plain-text mode locally, with firewall rules forcing outside access to be secure.

  • juriansluimanOP 5 years ago

    Author here:

    That's exactly what this post does only with Traefik instead of haproxy. The TLS of Mosquitto is just too much of a maintenance burden.

    A cross post from what I replied at a Reddit topic:

    > Mosquitto does have TLS support by itself, but the manual only deals with self-signed certificates. Self-signed certificates do involve a maintenance burden I don't want to deal with. All my applications/devices which expose a HTTP frontend (or other TCP stream) are encrypted via Let's Enncrypt certificates. They are automatically trusted by a lot of platforms (pc's, phones and other devices).

    > I was using acme.sh before and the post-install hook can refresh every service, but it just wasn't working properly on every occasion. You also have to reload all your applications for loading the new certs (that is, Home Assistant, Unifi, Pi-hole, mosquitto, my smart meter readings platform and so on). Just reloading everything for a cert renew felt cumbersome, and Traefik dealing with TLS termination decouples the TLS part from the application itself.

    > Since I used Traefik already, it was really straightforward to put Mosquitto behind Traefik too. Of course every situation is different, this post is mainly geared towards users which do not authenticate or encrypt Mosquitto at all.

    • fullstop 5 years ago

      I'll have to give Traefik a peek. I've used haproxy for a long time, and it's my go-to tool for my TLS termination and proxy needs, but it's always good to have more tools.

  • RedShift1 5 years ago

    Mosquitto 2 supports reloading the TLS cert without restarting. Send SIGHUP to reload certs.

    • fullstop 5 years ago

      This is also good to know. Thanks, I was unaware that 2.0.x had been released!

  • eeZah7Ux 5 years ago

    You are much better off with a gateway than a proxy.

    • fullstop 5 years ago

      Can you explain further?

      • eeZah7Ux 5 years ago

        Very often in home and industrial automation you want to have a smart enough, local, gateway that can:

        - speak multiple protocols as needed by the devices

        - aggregate data, provide history of values from sensors & so on

        - isolates the (limited) network stacks of local devices from the Internet - e.g. provides different timeouts and retransmission behavior

        - terminates a VPN, often providing better security than exposing services directly on the Internet!

fuhry 5 years ago

My approach with a recent personal project (i.e. no actual scaling required) was to have the MQTT server just listen on localhost. Application connects without TLS on the loopback interface. Clients connect over WebSocket (TLS) using their existing OAuth access token as the username and "x" as the password. The application involves an API as well so client credentials are already in use.

I used jpmens/mosquitto-auth-plug <https://github.com/jpmens/mosquitto-auth-plug> for the Mosquitto side of things, with a query along the lines of:

  SELECT "hardcoded password hash" FROM oauth_access_tokens WHERE access_token = "%s" AND scope REGEXP "\bmqtt\b";
theflyinghorse 5 years ago

We were able to set up a certificate-per-device authorization for MQTT where we use CN field of the cert for mapping to what particular device is allowed to pub/sub to

mleo 5 years ago

I use almost the same thing with an Internet accessible MQTT server that acts as relay of Zoom Webhook events, except it is using nginx as the proxy. I have local MQTT server that connects to the public MQTT server and then local clients that show zoom status via LEDs are connected to my local server.

There is also no mention in article of what is being used for internal DNS resolution. I could assume pi-hole, but something to resolve DNS on home network is required is this operation.

majormjr 5 years ago

This is a good tutorial to get the server side of things secured. I didn't know you could use Traefik to proxy the MQTT connections as well which looks quite useful.

The biggest issue I have is with the client side and its various support of TLS and getting a trusted CA certificate distributed. This is the harder part of the equation in my opinion, support is getting better with firmwares like Tasmota but getting some third party IoT device to work over TLS is still a challenge.

  • juriansluimanOP 5 years ago

    You're totally right. Although in my experience this is much easier to maintain with "upstream root certificates" (not sure how you'd call them) then self-signed certs. Applications like Home Assistant are already TLS aware and simply trust all root certs which are available on the host. With self signed certs, you have to distribute them all by yourself.

    Besides this trade-off, you have to check all clients to be TLS aware on beforehand. In my setup, all clients were capable of TLS. The only hassle are my NodeMCU devices which need to swap the WifiClient to a WifiSSLClient and you need to embed the public DST Root CA X3 yourselves.

bxparks 5 years ago

I'm a bit confused. You got a local MQTT server, and a local Traefik proxy, all behind your local firewall. How does Traefik get its LetsEncrypt certificate from behind the firewall when LetsEncrypt can't see Traefik?

The last time I tried to use LetsEncrypt for a local server, several years ago, this could not be done. Has this changed?

  • adev_ 5 years ago

    > How does Traefik get its LetsEncrypt certificate from behind the firewall when LetsEncrypt can't see Traefik?

    DNS registration. You can get letsencrypt validation through a DNS token for validation. You can generally script that using the API provided by your DNS provider.

    • adamcstephens 5 years ago

      With Traefik it’s just setting up the config and any authentication. After that Traefik will manage the lifecycle of the cert.

SV_BubbleTime 5 years ago

You lucky guys with IP stacks and TLS! I had to secure an IoT MQTT install where the packets themselves needed encryption which meant hamfisting in an encapsulated packet scheme (plain text header, end to end encrypted payloads). Kinda painful and I would not do that again!

  • tialaramex 5 years ago

    It really seems like you could squeeze IP and thus (D)TLS in there instead, definitely something to eye up if ever you do have to do this again.

    For TLS you can use pre-shared key mode so there's no extra gubbins like certificates, but you get all the same guarantees about whether what you're doing is actually safe as the big guys.

    • SV_BubbleTime 5 years ago

      Entire chip has 512K of rom, if I could have fit IP I would have considered it, but I was already really quite cramped for room! I’m sure there are some tight IP systems but I’m already mesh/proxy-ing stuff, it was easier to just encapsulate.

steve_gh 5 years ago

Securing MQTT is all good and well. It's more difficult with MQTT-SN (lighter weight and lower bandwidth) can run over UDP which is recommended for running over NB-IoT and similar cellular systems.

the_arun 5 years ago

Could we MQTT in regular applications as well? or just in IOT?

  • BrandoElFollito 5 years ago

    Absolutely yes.

    MQTT is a specific implementation of a general approach to buses. This is wildly used for asynchronous communication between services.

    I use MQTT (or other buses) when I have services that need to send some information without consideration for the services that need that information. The first ones are producers, the other ones - consumers.

    This is a very powerful approach when you have good cases. IoTs are typical cases where they send data and something else makes use of them. Another example is code that calculates some information and emits its results.

    Some of my code retrieve google calendar information and emits that - and it is consumed by a dashboard, some other code that makes decisions such as alarm clocks etc.

    In general you use this for asynchronous messaging, especially in with one-to-many scenarios.

  • juriansluimanOP 5 years ago

    (Author here)

    I run it to communicate with much more applications. It just depends on your own preferences. For example, some tools provide an API (local or cloud based) and you can directly plug in into that API. In The Netherlands you can read your electricity meter yourself by a "Dutch Smart Meter Readings" and DSMR integrates into Home Assistant with MQTT. I use Z-Wave as wireless mesh technology for lights and switches, the Z-Wave controller integrates into Home Assistant with MQTT.

    MQTT is so easy to setup and configure, you can use it for any messaging you want. As an example, I run Home Assistant locally to run my home automations, but also check the status of my local devices and online servers (Digital Ocean droplets). One use case is my backup script which publishes the backup results to an online MQTT server, my Home Assistant checks the topics at that server to display backup stats locally. If something went wrong, Home Assistant notifies my directly. PS. The backup script also sends out e-mails which I filter in Fastmail, the success mails are trashed and only error messages are kept in the inbox ;)

  • patwolf 5 years ago

    In my experience MQTT works well for telemetry and one-way messaging, but it's not good at doing request-response flow like you typically do in an application using HTTP. You can certainly come up with a mechanism for doing that, but you're having to re-invent a lot of what HTTP already solves.

    • BrandoElFollito 5 years ago

      HTTP is synchronous. MQTT is asynchronous.

      HTTP is 1:1. MQTT can be 1:many.

      What you use completely depends on your specific case.

  • jononor 5 years ago

    Sure. However if you are thinking for server/cloud usage, I would recommend considering AMQP instead (RabbitMQ etc). Especially if you want a "worker" type model with horizontal scalability for job processing, then the roundrobin.

    Some of the functionality has been added to the MQTTv5 spec, but client support is not as good for that yet, and its not as battle tested as AMQP.

  • rakoo 5 years ago

    MQTT is just a tool for publish/subscribe; that pattern exists in way more domains than IOT. Facebook Messenger, for example, is implemented on top of it.

Keyboard Shortcuts

j
Next item
k
Previous item
o / Enter
Open selected item
?
Show this help
Esc
Close modal / clear selection