您的位置:首页 > 产品设计 > UI/UE

Securing MQTT communication between Ardruino and Mosquitto

2016-07-01 11:55 344 查看
I tried a lot of solutions, experimented heavily, but this was the most consistent way for my monitoring and remote command design. Your mileage may vary (greatly) based on your use case.

As I posted late in the summer, connecting and interacting with an Arduino remotely with MQTT and web sockets is fairly straight forward. Dealing with the security however is not so trivial.


Captain, we need more power (for the SSL)

While we can make the ATmega328 do many things, doing secure socket layer (SSL) isn’t an option. Which leaves us with a bit of a dilemma before we even get started: how do we secure communications? If we just use the username and password authentication available
within both the MQTT libs for Arduino and Mosquitto, we’re passing them in the wide open. Anyone with Wireshark and a couple minutes will start opening your garage door.


Sometimes you need a middle man

In a perfect world, Arduino does SSL (or maybe we’re using Rasberry Pi’s or Netdruino’s) and we don’t have any need for a middle man. However, it’s not a perfect world, and we have lots of Arduino’s we want to securely control from the outside world. We need
a middle man.

In our case, our middle man is a local instance of Mosquitto that we’ll run bridged to our outside instance. We’re making a few presumptions (in particular that your home network isn’t wide open and is secured), but let’s for a second pretend you have some
device that’s always running. In my case, that happens to be a netbook that has been re-purposed as a print server, so it’s not seeing constant action.


Building bridges

Okay, so now our Audrinos are talking and listening the the local instance of Mosquitto. The local network is locked down, so we’re not worried about line snooping. Let’s start simple, and bridge our local Mosquitto instance with our remote Mosquitto instance.

Bridging Mosquitto instances is fairly well documented (see mosquitto.conf documentation). Sticking with the
sane defaults, creating the bridge is like so:
#... previous things

address ec2-somethingsomething.us-west-1.compute.amazonaws.com:8883
connection BridgeIt

topic devices/# out "" home
topic cmds/# in remote ""

username SomeUser
password SomePassword

bridge_cafile /etc/keys/myCA.crt
bridge_certfile /etc/keys/myServer.crt
bridge_keyfile /etc/keys/myServer.key

#... other things


Breaking down the config, we’re securing the bridge connection for using SSL (to see how to generate the certs and keys, have a look at the mosquitto-tlsdocumentation),
we’re using a username/password, and we’re defining which topics we’re sending out and listening for.


A note on topic mapping: don't loop me

Topic mapping is important, but slightly out of the scope of the security conversation…but I’m going to talk about it anyway. Topic mapping defines which messages will flow across the bridge. It can be very easy to create a loop, where both brokers continuously
send the same message back and forth. This is beyond problematic; you will anger the CPU gods and make your broker machines unhappy.

What to do? It really depends on how your overall information design. For me, I remap from the local devices tree into the remote home/devices/+ and to be super paranoid, I add an access control list rule that only allows the bridge user to write to that tree.


Locking up the remote side

So you’ve created this bridge, but your remote server needs some options set as well in it’s own config to make all this work. For the sake of not being open at all on the remote end, let’s not allow anonymous access, require password, and set the defaults
to use SSL.
#... previous things

acl_file /etc/mosquitto/accesscontrols
allow_anonymous false
password_file /etc/mosquitto/users

bind_address 127.0.0.1
port 8883

cafile /etc/keys/ca.crt
certfile /etc/keys/server.crt
keyfile /etc/keys/server.key

#... other things


To create the password file, you can use mosquitto_passwd. The access control file will differ based on your
information design, but I basically set up some limits on the users that I’ve defined for my over all system. You could very well not use acl’s and the SSL and password file will suffice.

I’m not going to go indepth on pre-shared keys, but if you’re interested in knowing, you could very well use PSK and not use the password_file at all.


So where does this leave us?

In the end we end up with two Mosquitto brokers; one in the outside world that only speaks to the web socket server, and one on our inside private network, which only talks to the Arduinos. Together, the two brokers talk over SSL through the bridge.

Since the python Mosquitto library has SSL support, it talks to the outside instance securely. We then run our dashboard and interface panel over HTTPS, which further secures information exchange. And because we’re running HTTPS, the web socket service will
use WSS (WS over TLS), also secure.

It’s a rather long path to secure everything, but in the end, as long as we make sure we don’t have any gaps in our local network, we can still talk securely and control those Arduinos remotely.
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: