[solved] MQTT with SSL/TLS not working with Home Assistant

Hi,

I’m trying to setup MQTT with Home assistant, but it doesn’t want to work. I’m running Mosquitto broker (not add-on) with configured SSL/TLS, but with require_certificate set to false, since I want encryption, but not necesserily having to hand out certificate files to each client. I have also set a username and password authentication. I have tested this with a mobile app and two devices, and all checks out good (I can publish something on one device and the other device that is subscribed to that topic receives the message).

In Home Assistant I have added this code to configuration.yaml

mqtt:
  broker: 192.168.0.245
  port: 8883
  username: !secret MQTT_user
  password: !secret MQTT_passwd
  tls_insecure: true

and respectively username and password to the secrets.yaml file.

Now here comes the weird part. In the mosquitto log I can see

New connection from 192.168.0.245 on port 8883.,

but when I try to publish something from the MQTT tab in the Developer Tools the value doesn’t change. The same goes, when I try to subscribe to a topic. When I publish to it from another device, Home assistant doesn’t see any changes. I can confirm that the message has been in fact published with the second device.

I also tried to add a binary sensor to confirm, that there is something work with this added to configuration.yaml

binary_sensor:
  - platform: mqtt
    name: "Test Sensor"
    state_topic: "Test/toggle"
    payload_on: "ON"
    payload_off: "OFF"
    unique_id: test_binary

but had no luck either.

I’m running Home Assistant 0.107.3 with Hass.io as a Docker Container on a Raspberry Pi 3 B+. My Python version is 3.7.6, not sure that it would change anything. The MQTT broker is running on the same machine. What am I doing wrong?

2 Likes

Ok, so I checked and a couple of things are happening. The Home Assistant seems to connect to the broker but doesn’t register as a client. By that I mean, that I do receive

New connection from 192.168.0.245 on port 8883. ,

but nothing after that. My phone, on the other hand, does this

New connection from 192.168.0.246 on port 8883. New client connected from 192.168.0.246 as MqttDashboard-56921 (c1, k60, u'user').

Moreover, I seem to get these errors

OpenSSL Error: error:1408F10B:SSL routines:ssl3_get_record:wrong version number Socket error on client <unknown>, disconnecting.

Quick Google search didn’t help. I tried to add set the TLS version on both Home Assistant and Mosquitto to 1.2, without any luck. I also tried adding a constant clientID, but still didn’t work.

Any ideas?

1 Like

Solved

Turns you MUST include a certificate file in configuration.yaml. The certificate you include is the same file you included in mosquitto.conf as a certfile. To avoid accessability issues, I suggest you place a copy in the same directiory that configuration.yaml resides. Then under mqtt: add certification: yourfile.crt (I don’t think that the cert file extension matters). I’m still tracking down some issues involving self-signed certificates but I’ll keep looking for the anwsers or open a new thread for it. But anyways I’m closing this thread.

Edit: I’m stupid, this is all wrong, use the guide in post #11

1 Like

Hi @fufs

Can you confirm that this solution still works?
If I try to add ‘certification: xxxx’ in configuration.yaml, I get an error about invalid option?

Yes, it still works. I had an sd card failure and after reinstalling the self-signed issues dissappeared. My current configuration entry looks like this:

mqtt: 
  broker: !secret MQTT_ip
  port: !secret MQTT_port
  client_id: home-assistant
  username: !secret MQTT_user
  password: !secret MQTT_passwd
  certificate: server.crt
  tls_insecure: true

Sorry for responding so late, I haven’t been on the forum lately.

1 Like

@TheStigh
Ah, I now see the problem - I said that the option was called certification, when it’s actually called certificate. Sorry, my bad.

I’m using the MQTT add-on but running into this problem even if I set the certificate to the same file.

MQTT Add-on Config

logins:
  - username: '!secret mqtt_username'
    password: '!secret mqtt_password'
customize:
  active: false
  folder: mosquitto
certfile: fullchain.pem
keyfile: privkey.pem
require_certificate: false

configuration.yaml:

mqtt:
  certificate: /ssl/fullchain.pem
  broker: !secret mqtt_ip
  port: !secret mqtt_port
  username: !secret mqtt_username
  password: !secret mqtt_password
  tls_insecure: true

I’ve also tried setting:

mqtt:
  client_cert: /ssl/fullchain.pem
  client_key: /ssl/privkey.pem
  broker: !secret mqtt_ip
  port: !secret mqtt_port
  username: !secret mqtt_username
  password: !secret mqtt_password
  tls_insecure: true

but doesn’t help. For both the logs of MQTT show that it is finding the cert:

[02:49:40] INFO: Setting up user homeassistant
[02:49:40] INFO: Certificates found: SSL is available

But then the version error on connection:

1626688294: New connection from 172.30.32.1 on port 8883.
1626688294: OpenSSL Error[0]: error:1408F10B:SSL routines:ssl3_get_record:wrong version number
1626688294: Socket error on client <unknown>, disconnecting.
1626688296: Client connection from 172.30.32.1 failed: error:1408F10B:SSL routines:ssl3_get_record:wrong version number.

There are 3 files:

  • CA certificate,
  • Server certificate,
  • Server Key

In mosquito you need to supply all 3 (certfile is the server certificate, not CA; iirc CA was declared by cafile:)

In configuration.yaml certificate: is the ca cert. You don’t need client_cert: and client_key: if you’ve set mosquito with require_certificate: false. CA cert (certificate:), however, is required.

1 Like

Ah thanks, for that clarification. Your earlier post [solved] MQTT with SSL/TLS not working with Home Assistant - #3 by fufs said to use certfile in mosquitto config. Using cafile instead made it work.

Though seems that I can’t use TLS everywhere since not all the MQTT clients I’m using can be configured with the certificate.

1 Like

Yeah, I’m not sure what I was smoking back then :sweat_smile::joy:.
Steve’s internet guide has made an updated TLS guide, with all of the stuff clearly explained, it’s a good read, if you feel like it. Also if you want to make it a bit more secure you can add domain (and ip addresses) to the cert and remove tls_insecure: false.

This is a guide I wrote for my future self, enjoy!

  1. Create CA private key (recommended to create password)
    $ openssl genrsa -des3 -out ca.key 2048

  2. Generate CA certificate (valid for 20 years)
    $ openssl req -new -x509 -days 7300 -key ca.key -out ca.crt

  3. Create server-side private key
    $ openssl genrsa -out server.key 2048

  4. Create a configuration file - this you must do on your own, here is an example:

[ req ]
default_bits = 2048
prompt = no
default_md = sha256
distinguished_name = dn
req_extensions = v3_req

[ dn ]
C = XX
ST = Province
L = Cty
O = OrgName
CN = domain.local

[ v3_req ]
subjectAltName = @alt_names

[alt_names]
DNS.1 = domain.local
DNS.2 = 192.168.0.xxx

What to change?
The dn section is the details of your certificate. Available variables can be found at What is a Distinguished Name (DN)? or by googling “distinguished name ssl”
The alt_names section are the FQDNs of the sites that the certificate will be used for. This is used by browsers to confirm that a given certificate was meant for a given site.

Save it as server.cnf

  1. Create a certificate request from a configuration file (this is a file containing all the details for a CA to create a server-side certificate, since we are the ca we’ll generate (sign) it ourselves, hence the name self-signed)
    $ openssl req -new -config server.cnf -key server.key -out server.csr -extensions v3_req

  2. Create the server-side certificate (10 years)
    $ openssl x509 -req -days 3650 -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -extfile server.cnf -extensions v3_req

NOTE:
This uses a workaround due to a bug to get x509v3 extensions working (SANs). By the time this was written the bug was fixed and a solution has been created, but not released.

REPLACE
-extfile server.cnf -extensions v3_req
WITH
-copy_extensions copyall

NOTE2:
When creating you first certificate with the CA use the -CAcreateserial flag, however, if this is not your first cert then use -CAserial ca.srl option to load your already existing serial file.

  1. Add CA certificate, Server certificate and server key to the mosquitto.conf file (cafile, certfile, keyfile) and require_certificate false. Add CA certificate to configuration.yaml (certificate). You can use certificate based authentication as well - set require_certificate true in mosquitto.conf and add client_cert: and client_key: in configuration.yaml.
4 Likes

Hey fufs,

Thanks for the guide, but I’m still not getting a connection over 8883. The only part of your guide I’m not sure on is this part:

I want both 1883 and 8883 enabled, (insecure for LAN traffic, secure for remote MQTT clients over WAN), so I believe I leave out " - set require_certificate true in mosquitto.conf" for this. But I’m not sure what should be in configuration.yaml and mosquitto.yaml.

Thanks again,
Seth

You need two mosquitto servers (can be on the same machine) and you need to link them. There should be such entry in mosquitto.conf

In HA: Put you CA certificate in /config or any other subfolder of /config. Then in configuration.yaml under mqtt: add certificate: /path/to/cacert. Use certfile: and certkey: only for certificate based authentication (for iot devices keep away from certificate based auth)

For protected and unprotected use my solution above but do remember that it’s not secure as all traffic from encrypted mqtt will be visible on the unencrypted one

There’s nothing in my mosquitto.conf file. None of the guides have included it. I definitely have no idea how to have two servers, let alone linked. Can you share your MQTT broker setup and .conf?

And all of the guides have said to leave out the mqtt: block from configuration.yaml, since it’s in the integration now. I’m fine with the homeassistant mqtt client using insecure to talk to the mqtt broker, since they are on the same network. But I want the mqtt clients that are connected through the WAN to be encrypted, such as my sprinkler controller in a different city. Right now I can’t get clients on the LAN or from the WAN to connect to the MQTT broker with 8883, so my broker settings are wrong probably?

Putting the mqtt: block in configuration.yaml stopped the insecure traffic from working (1884), and did not fix the secure problem (8883).

Sorry for all the questions, I’m lost on this one.

Maybe I’m getting this part wrong too. My hostname is RPI-HA
CN, should that be RPI-HA or RPI-HA.local?

For [alt names], should I have DNS.1 = RPI-HA or RPI-HA.local?
For DNS.2 = Host IP or IP of the client?
Should I add DNS.3 = mqtt.example.com

Thanks

Open a new thread for that and I’ll send all the required documentation there

1 Like

Send your mqtt entry from configuration.yaml

Also cn is not that important, alt names are but only if you want certification provider confirmation (you do for wan)

Could you please send me the part that you`ve use in your config.yaml(mqtt part) and mqtt add-oc config with the names used in your example config?

Im new in this certificate stuff and Im not clear what is fullchain, privkey… You mention that we need 3 files but in config.yaml (or at least the thing that I`ve rd) are mentioned only 2 files.

I`m kind of lost and frustrated :).

Thank you!

so how can we make these certs when openssh is not installed ?

|Version |core-2022.4.7|
|Installation Type |Home Assistant OS|

and googling install openssl onto open assistant everyone says its not needed …
and give no information how to install it

“The fact that HA OS is considered an appliance, you can’t install anything on HA OS, except add-ons.”