cflurin / homebridge-mqtt

Homebridge-mqtt is a Plugin for Homebridge.
Apache License 2.0
229 stars 39 forks source link

Support for mqtts and client certificates. #36

Closed frankiboy1 closed 7 years ago

frankiboy1 commented 7 years ago

I've set up my broker to require client sertificates, which homebridge-mqtt does not support. I'm not too familiar with javascript, but made an attempt to add this support. (Also, I'm not familiar with github, so I don't have a proper patch.)

Making the change below to enable the new support:

diff model.js.orig model.js

4a5

var fs = require('fs'); 43a45 options.port = this.config.port || 1883; 47a50,58 if(this.config.cert != null) { options.cert = fs.readFileSync(this.config.cert); } if(this.config.key != null) { options.key = fs.readFileSync(this.config.key); } if(this.config.ca != null) { options.ca = fs.readFileSync(this.config.ca); }

This will add the following configuration options:

"platforms": [
    {
        "platform": "mqtt",
        "name": "mqtt",
        "url": "mqtts://mqtt.example.com",
        "port": 8883,
        "topic_prefix": "homebridge",
        "username": "username",
        "password": "password",
        "cert": "/path/to/certificate.pem",
        "key":  "/path/to/key.pem",
        "ca":   "/path/to/ca_certificate.pem"
    },

I've made some basic testing and it did not break anything in my setup. Hope this can be added so I don't have to maintain my own patch.

Frank

frankiboy1 commented 7 years ago

Seems like there is one issue, which I have not found a resolution for, but you might be able to understand this.

With the above patch, I can successfully connect to my broker using mqtts and client certificates. homebridge-mqtt publish several messages and subscribe to some topics. Then it disconnects and reconnects every few seconds. There's no extra output from homebridge, so it looks like the homebridge-mqtt is unaware that the client is disconnecting.

From the logs it looks like the client tries to connect a second time, which causes the disconnect.

I've tried both mosquitto v1.4.8 and mosquitto v1.4.11 with the same result.

1494113633: mosquitto version 1.4.11 (build date Mon, 20 Feb 2017 22:47:27 +0000) starting 1494113633: Config loaded from /etc/mosquitto/mosquitto.conf. 1494113633: Opening ipv4 listen socket on port 8883. 1494113633: Opening ipv6 listen socket on port 8883. 1494113634: New connection from 10.1.50.120 on port 8883. 1494113634: New client connected from 10.1.50.120 as mqttjs_470dec79 (c1, k60, u'username'). 1494113634: Sending CONNACK to mqttjs_470dec79 (0, 0) 1494113634: Received SUBSCRIBE from mqttjs_470dec79 1494113634: homebridge/to/# (QoS 0) 1494113634: mqttjs_470dec79 0 homebridge/to/# 1494113634: Sending SUBACK to mqttjs_470dec79 1494113634: Received SUBSCRIBE from mqttjs_470dec79 1494113634: homebridge/to/# (QoS 0) 1494113634: mqttjs_470dec79 0 homebridge/to/# 1494113634: Sending SUBACK to mqttjs_470dec79 1494113634: Received SUBSCRIBE from mqttjs_470dec79 1494113634: homebridge/to/# (QoS 0) 1494113634: mqttjs_470dec79 0 homebridge/to/# 1494113634: Sending SUBACK to mqttjs_470dec79 1494113634: Received SUBSCRIBE from mqttjs_470dec79 1494113634: homebridge/to/# (QoS 0) 1494113634: mqttjs_470dec79 0 homebridge/to/# 1494113634: Sending SUBACK to mqttjs_470dec79 1494113634: Received SUBSCRIBE from mqttjs_470dec79 1494113634: homebridge/to/# (QoS 0) 1494113634: mqttjs_470dec79 0 homebridge/to/# 1494113634: Sending SUBACK to mqttjs_470dec79 1494113634: Received PUBLISH from mqttjs_470dec79 (d0, q0, r0, m0, 'homebridge/from/connected', ... (30 bytes)) 1494113634: New connection from 10.1.50.33 on port 8883. 1494113634: Sending CONNACK to 10.1.50.33 (0, 5) 1494113634: Socket error on client , disconnecting. 1494113635: New connection from 10.1.50.33 on port 8883. 1494113635: Sending CONNACK to 10.1.50.33 (0, 5) 1494113635: Socket error on client , disconnecting.

frankiboy1 commented 7 years ago

Doing some further debugging on my patch, I found that the disconnects happens because another python client is misbehaving. Disabling the python client makes everything work as expected.

frankiboy1 commented 7 years ago

And to close this from my side....

You need to pass the options when connecting anonymously as well, to enable certificates with anonymous connections. (This is probably very relevant as the username/password is likely to be dropped when you authenticate with certificates).

It looks like these lines could be simplified to allow this:

if(options.username === null || options.password === null) { this.log("connect Anonymous"); client = mqtt.connect(url); } else { this.log("connect Authentication with username/password"); client = mqtt.connect(url, options); }

Changing the above lines to:

this.log("connecting"); client = mqtt.connect(url, options);

Would work for both anonymous connections and when using username/password.