Mosquitto SSL Configuration -MQTT TLS Security

configure-tls-mosquittoIn this tutorial we will configure the mosquitto MQTT broker to use TLS security.

We will be using openssl to create our own Certificate authority (CA), Server keys and certificates.

We will also test the broker by using the Paho Python client to connect to the broker using a SSL connection.

You should have a basic understanding of PKI, certificates and keys before proceeding. See SSL and SSL Certificates Explained



The steps covered here will create an encrypted connection between the MQTT broker and the MQTT client just like the one between a web browser client and a Web Server.

In this case we only need a trusted server certificate on the Client.

We do not need to create client certificates and keys.

Important Note: Many other tutorial on the web also configure username and password authentication at the same time. I don’t recommend you do this as errors could be cause by either SSL or authentication. Only do one thing at one time when testing.

Client Requirements

  • A CA (certificate authority) certificate of the CA that has signed the server certificate on the Mosquitto Broker.

Broker Requirements

  • CA certificate of the CA that has signed the server certificate on the Mosquitto Broker.
  • CA certificated server certificate.
  • Server Private key for decryption.

Creating and Installing Broker Certificates and keys

To create these certificates and keys we use the openssl software.

For windows you will find the install download files here.

On Linux you can install openssl using :

sudo apt-get install openssl

Although the commands to create the various certificates and keys are given in this Mosquitto manual page. Here is a quick snapshot:

tls-manual-page-mods

There is a problem with the page because openssl no longer comes with a CA certificate, and so you will need to create your own self signed CA certificate.

You should also note that when you generate keys you shouldn’t use encryption (the -ds3 switch) for the server certificate as this creates a password protected key which the broker can’t decode.

Note the certificates and keys created can be used on the Mosquitto broker/server, and also on a web server, which is why you see the term server used in the Mosquitto manual and not broker.

Overview of Steps

  1. Create a CA key pair
  2. Create CA certificate and use the CA key from step 1 to sign it.
  3. Create a broker key pair don’t password protect.
  4. Create a broker certificate request using key from step 3
  5. Use the CA certificate to sign the broker certificate request from step 4.
  6. Now we should have a CA key file,a CA certificate file, a broker key file, and a broker certificate file.
  7. Place all files in a directory on the broker e.g. certs
  8. Copy the CA certificate file to the client.
  9. Edit the Mosquitto conf file to use the files -details below
  10. Edit the client script to use TLS and the CA certificate. -details below

Note: when entering the country, organisation etc in the form don’t use exactly the same information for the CA and the server certificate as it causes problems. Here is a screen shot of a comment from a reader that brought it to my attention:

Detailed Steps Windows

Note this as done on a windows XP machine.

The same commands and procedures apply to linux but the folder locations will be different and you may need to change permissions, as well as using the sudo command.

Step 1:

First create a key pair for the CA

Command is:   openssl genrsa -des3 -out ca.key 2048

create-ca-key

Note: it is OK to create a password protected key for the CA.

Step 2:

Now Create a certificate for the CA using the CA key that we created in step 1

Command is:  openssl req -new -x509 -days 1826 -key ca.key -out ca.crt

create-ca-certificate

Step 3:

Now we create a server key pair that will be used by the broker

Command is: openssl genrsa -out server.key 2048

create-server-key

Step 4:

Now we create a certificate request .csr. When filling out the form the common name is important and is usually the domain name of the server.

Because I’m using Windows on a local network I used the Windows name for the computer that is running the Mosquitto broker which is ws4.

You could use the IP address or Full domain name. You must use the same name when configuring the client connection.

Command is: openssl req -new -out server.csr -key server.key

create-server-certificate-request

Note: We don’t send this to the CA as we are the CA

Step 5:

Now we use the CA key to verify and sign the server certificate. This creates the server.crt file

Command is:  openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 360

create-signed-server-certificate

Step 6:

The above steps created various files. This is what the directory looks like now:

key-certificate-files

Note: We don’t need to copy the CA.key file. This file is used when creating new server or client certificates.

Step 7:

Copy the files ca.crt, serever.crt and server.key to a folder under the mosquitto folder. I have used a folder called certs.

on Linux you should already have a ca_certificates folder under /etc/mosquitto/ and also a certs folder.

Use the ca_certificates folder for the CA certificate and the certs folder for the server certificate and key.

Step 8:

Copy the CA certificate file  ca.crt to the client.

Step 9:

Edit the mosquitto.conf file as shown:

mosquitto-conf-tls

Notes:

  1. I’ve used the default listener but you could also add an extra listener.
  2.  The ca path is not used as I told it the file location instead.
  3. On my Linux install the entire TLS section of the mosquitto.conf file was missing I had to copy it from my windows install and then edit it. Here is the mosquitto.conf file documentation

Step 10 -Client Configuration:

Edit the client to tell it to use TLS and give it the path of the CA certificate file that you copied over.

I’m using the python client and the client method is tls_set(). Although there are several parameters that you can pass the only one you must give is the CA file as shown below.

client.tls_set(‘c:/python34/steve/MQTT-demos/certs/ca.crt‘).

The python client will default to TLSv1.

You shouldn’t need to change it as the mosquitto broker also defaults to TLSv1.

However to change it to TLSv1.2 use:

client.tls_set(‘c:/python34/steve/MQTT-demos/certs/ca.crt’,tls_version=2)

The pub and subscribe scripts that come with the mosquitto broker default to TLSv1.2.

Problems I Encountered and Notes

While creating and working through these procedures i encountered the following problems

  1. Error when connecting due to the common name on the server certificate not matching.
  2. I password protected the server key and the broker couldn’t read it. I found this command which will remove the passphrase from the key –  openssl rsa -in server.key -out server-nopass.key.
  3. Not using the correct name for the broker. I used the IP address and not the name that I entered into the certificate.You can use the tls_insecure_set(True) option to override name checking as a temporary measure.
  4. Authentication errors as I had previously configured my broker to require passwords. Therefore try to start with a clean conf file and beware that the errors you are getting may not be SSL related.

Self Signed Certificates

Currently the Paho python client require a CA certificate file and so it is not possible to use a self signed certificate. I came across a couple github threads relating to this but no real solution.

Testing

If all goes well you should be able to publish and subscribe to topics as normal, but now the connection between client and broker is encrypted.

Unfortunately there is no easy way of seeing this.

This is the Python script I used:

tls-test-script

To test using the mosquitto_pub client use:

test-tls-mos-pub

Failure Example

This shows that the common name you enter on the certificate must match the name used by the client when it connects. If not it doesn’t work.

ca-common-name-error

Video

Configuring SSL on the Mosquitto MQTT broker

Reported Problems and Solutions

  • Wrong/Old openssl version reported on Centos 7. Update openssl fixed it.
  • Problems when using capath on mosquitto_pub tool. Use cafile instead -mosquitto_pub -h host.name -u username -P password -t test/topic -p 8883 –cafile ~/keys/ca.crt -m message
  • Problems with Server name on certificate. Use the tls_insecure_set(True) on the python client or the –insecure switch in the mosquitto_pub tool.

Mosquitto Configuration Tutorials

Other Related Articles and Resources:

Facebooktwittergoogle_plusredditpinterestlinkedinmail

89 comments

  1. Hi Steve,
    Your tutorial is excellent!
    I have followed all the steps and it feels that everything is going well. However, I have a problem that I am trying to resolve.
    When I run your script to check the paho client I get the following error:
    “Traceback (most recent call last):
    File “Desktop/PahoClient1.py”, line 21, in
    client1.tls_set(‘/Home/Downloads/Python-3.6.1/mqtt-demos/ca.crt’, tls_version=2)
    File “/usr/local/lib/python2.7/dist-packages/paho_mqtt-1.4.0.dev0-py2.7.egg/paho/mqtt/client.py”, line 772, in tls_set
    context.load_verify_locations(ca_certs)
    IOError: [Errno 2] No such file or directory”

    I have installed Python-3.6.1, while python 2.7 was already installed on Ubuntu. Does the cause of the error is that I installed paho client on Python-3.6.1 and not on python 2.7?

    Thank you in advance!

    Vagia

    1. Tks for the nice comment
      It could be. When you have multiple versions of Python when you do a PIP
      install it might get installed for the new version.
      You need to check if the mqtt client is installed for 3.6 which you can do
      by using
      pip show paho-mqtt
      to see where pip will install use
      pip –version.

      Can you confirm that you can pub/sub without ssl?
      You also need to check the location of you ca file when using ssl
      You might find this useful
      http://www.steves-internet-guide.com/python-notes/
      I created it because I had the same problems when I started.
      Let me know how you get on
      rgds
      steve

  2. Hi Steve!
    THANK YOU for this really cool howto! It works great!
    I have a question:
    When i verify and sign the server certificate with “-days 360”, does this mean, that i have to update the files on the clients physically every 360 days?
    Please don’t lought, my client are 100 km away. I don’t want to go there by car.
    I’m the absolute dud on such server things, so …
    Greetings from austria!

  3. Steve,
    When apply this: openssl req -new -x509 -days 1826 -key ca.key -out ca.crt
    I get some error like this:
    ————————————————
    Enter pass phrase for ca.key:
    Can’t load ./.rnd into RNG
    7240:error:2406F079:random number generator:RAND_load_file:Cannot open file:cryp
    to\rand\randfile.c:88:Filename=./.rnd
    You are about to be asked to enter information that will be incorporated
    into your certificate request.
    What you are about to enter is what is called a Distinguished Name or a DN.
    There are quite a few fields but you can leave some blank
    For some fields there will be a default value,
    If you enter ‘.’, the field will be left blank.
    —–
    Country Name (2 letter code) [AU]:CN
    State or Province Name (full name) [Some-State]:Guangdong
    Locality Name (eg, city) []:ShenZhen
    Organization Name (eg, company) [Internet Widgits Pty Ltd]:Harman
    Organizational Unit Name (eg, section) []:Pro T&V
    Common Name (e.g. server FQDN or YOUR name) []:Yongxiang
    Email Address []:Yongxiang@mo.com
    ——————————————————————-
    Looks like I can get the ca.crt, but How can I resolve the error?
    I use the laptop do this, OS is win7 64BIT

  4. Has anyone been able to solve the “tlsv1 alert unknown ca” message? I’ve been through the tutorial several times and can not find out what is causing the problem.
    Client:
    Error: A TLS error occurred.

    Server:
    1540843163: New connection from xxx.xxx.xxx.xxx on port 8883.
    1540843163: OpenSSL Error: error:14094418:SSL routines:ssl3_read_bytes:tlsv1 alert unknown ca
    1540843163: OpenSSL Error: error:140940E5:SSL routines:ssl3_read_bytes:ssl handshake failure
    1540843163: Socket error on client , disconnecting.

  5. Hey,
    I justed wanted to say thanks for the tutorial. It was the only one the net which let me enable secure communication successfully 🙂 I think the other instructions fail to mention how important the domain is. I added the local ip address and it worked just fine. I also tested it with home assitant and it worked 🙂

    So, a big thank you for this!

    best regards

  6. Hi Steve , just to clarify ,from a comment made by vicky on 11 April 2018 , it was mentioned that if the input field of step 2 and step 4 were identical , the ca.crt would not work ,hence only the server.crt is applicable. If the input fields of step 2 and 4 were of different values , it means that the ca.crt would work fine without error?Further more if i am using mosquitto library , can the ca.crt and server.crt certificates be used? Or is there a need to create a pem version?

    Regards
    Wayne

    1. Yes if the forms ca.crt and server.crt are identical then it can cause problems.
      The server.crt is not applicable as it need a ca.crt on the client so you would be best to create the ca.cr and server.crt again.
      You don’t need a pem version as you aready have one as pem is encoding and I ‘m pretty sure the tutorial create a pem version. See this guide http://info.ssl.com/article.aspx?id=12149%20
      Rgds
      Steve

      1. Hi, steve
        thanks for explaining , so i can assume that ca.crt = ca.pem? i googled and some people are using the .pem and i am getting a little confused

        Rgds,
        Wayne

        1. Yes and no. The easiest way is to open the certificate in a text editor and if you can read it and it starts with BEGIN CERTIFICATE the it is in perm format.
          I was as well confused by all of the different extensions as there isn’t really a fixed relationship.
          On your own setup I would stick to the .crt and .key extensions which seem more common.
          If you have a ca.pem certificate then you can rename it to ca.crt and it will work as normal.
          rgds
          steve

          1. Hi, thanks for explaining once again.Followed your guide and it work . However ,when i tried using openssl (s_client -connect domainname:8883 -showcerts) to test the connectivity, i was return with an error,
            “Verification error: self signed certificate in certificate chain” . Can i seek your opinion and guidance on this?

            Regards,
            Wayne

  7. Hi steve
    I have a question about mqtt security at all. As we know MQTT designed the way that any client who subscribe to a topic can receive the messages that publish on that topic. So a question is that in a big network with lots of users and devices connected to that how should we prevent a user to sniff or publish messages to other users devices? for example we have user1 with device1 belonging to that and user2 with device2. for example we have a topic for device1 that lets user1 control it, how should we prevent user2 which is connected to that broker to publish or subscribe to device1 topics? considering there’s lots of devices and users.
    Thanks in advance

    1. Any security you will need to build into the clients like using access tokens etc. However the brokers also provide various degrees of security like ACLs and username and passwords.
      http://www.steves-internet-guide.com/topic-restriction-mosquitto-configuration/
      http://www.steves-internet-guide.com/mqtt-username-password-example/
      Personally I like message encryption as it is end to end see here
      http://www.steves-internet-guide.com/encrypting-the-mqtt-payload-python-example/

      1. Thanks for your articles and answering questions. Those were great. I agree with you, message encryption is a better way to go but we should also use TLS if we want to secure the topics as well. Also considering that ACLs and username and passwords need another service to control the brokers resources

          1. Yes that’s a good way. Just a problem is that if some one sniffs the packets, can find the topic and start to send huge data to that topic and cause the devices not to work properly.

  8. If you’re getting “Socket error on client , disconnecting.” you should look in your config if allow_anonymous is set to False. In this case, using certificate, set it to True or provide username during logging.

  9. I was using certificate generation process mentioned on CentOS 7. Configured mosquitto for websockets, when starting mosquitto broker, I am getting ‘OpenSSL doesn’t support ECDH’ error.

    1. Both are certificates. You can consider them as the same as passports.
      The server certificate contains the public keys for that server.
      The CA certificate contains the public keys of the certificate authority which can be self signed or signed by an higher certificate authority.
      The ca private signature key is used to sign the server certificate. It is the trusted authority.
      When a client connects to a server to use SSL the server sends the client its certificate which contains its public key (which has been signed by a CA (trusted authority) and the client uses the public signature key in the CA certificate to verify that the server public key is valid.
      For this to work the client must have a copy of the CA certificate.
      CA certificates for public certificate authorities like verisign are included with your browser.
      Does this make sense?

      1. OK got it ..Thank you. Is it possible to provide client side authentication using MQTT ? I read to your reply ,it says – YES but complexity is more. I want to know whats the complexity inovolved?

  10. Hey Steve, thanks for this great tutorial, it was my starting point in securing my mosquitto broker communication. Just a question, do you think its a good idea to buld and use for each client a different private key (ca.crt)? Additionally I want to use user-id and password autentification.

    Kind regards,
    Christoph

    1. The Ca.crt is the certificate authority certificate and Usually you only use 1 for all your clients.
      You can use certificate authentication which means giving each client it’s own key but It would probably be too difficult to manage and I haven’t tried it.
      The tutorial for username password is here
      http://www.steves-internet-guide.com/mqtt-username-password-example/
      I would recommend getting ssl to work then getting username./password to work and then combine them at the end
      rgds
      steve

  11. Hi Steve,

    Really helpful article. I followed all the steps listed but I am receiving an error that says “Error: Problem setting TLS options”. The command I am running is mosquitto_sub -t home/livingroom -v -d –cafile ca_certificates/ca.crt -h 192.168.0.32 -p 8883. The CN on both CA and server certificate is 192.168.0.32. I also tried using the option –tls-version tlsv1.

    My mosquitto.conf file has the following contents
    port 8883

    cafile /etc/mosquitto/ca_certificates/ca.crt
    keyfile /etc/mosquitto/certs/server.key
    certfile /etc/mosquitto/certs/server.crt
    tls_version tlsv1

    Can you point out where I could be going wrong?

    Thank you.

    1. Try the full path for the certificate file and also try the –insecure option and comment out the tls_version in the conf file otherwise looks ok
      rgds
      steve

  12. In log i get error: Error: Unable to load CA certificates. Check cafile “/root/jbre/SSL/ca.crt”
    I i comment out server.key it loads mosquitto or if i comment out ca.crt, mosquitto works, so i guess those two files are not compatible….hm… i did generate keys with step 2 and 4 with slightly different value… but i also leave some fields empty, like mail, maybe thats problem?

  13. Hey.
    First, really nice and useful blog. So i did everything exactly like you wrote in this configuration but when i try to connect with client to broker i get “Error: Connection refused”. I am trying simple with “mosquitto_sub -d -v -h 20.0.0.211 –insecure –cafile /home/ubuntu/jbre/SSL/ca.crt -t test -p 8883”.

    Maybe any idea?
    Thank you in advance.

    1. Connection refused is often when you use the wrong port or IP address the command you are using looks OK I would check the broker.

      1. Thank you for fast answer. I see now that when i add in mosquitto.conf cafile, certfile, keyfile mosquitto broker can’t start or is in failed status:
        Jun 28 07:07:19 kibernetmq mosquitto[1776]: 1530169639: mosquitto version 1.4.15 (build date 2018-05-05 12:54:33+0000) starting
        Jun 28 07:07:19 kibernetmq mosquitto[1776]: 1530169639: Config loaded from /etc/mosquitto/mosquitto.conf.
        Jun 28 07:07:19 kibernetmq mosquitto[1776]: 1530169639: Opening ipv4 listen socket on port 8883.
        Jun 28 07:07:19 kibernetmq systemd[1]: mosquitto.service: main process exited, code=exited, status=1/FAILURE
        Jun 28 07:07:19 kibernetmq systemd[1]: Unit mosquitto.service entered failed state.
        Jun 28 07:07:19 kibernetmq systemd[1]: mosquitto.service failed.

        When i comment this lines out mosquitto starts normally and is active:
        Jun 28 07:06:46 kibernetmq mosquitto[1766]: 1530169606: mosquitto version 1.4.15 (build date 2018-05-05 12:54:33+0000) starting
        Jun 28 07:06:46 kibernetmq mosquitto[1766]: 1530169606: Config loaded from /etc/mosquitto/mosquitto.conf.
        Jun 28 07:06:46 kibernetmq mosquitto[1766]: 1530169606: Opening ipv4 listen socket on port 8883.
        Jun 28 07:06:46 kibernetmq mosquitto[1766]: 1530169606: Opening ipv6 listen socket on port 8883.

        Any idea?
        Thanks again,

        1. The most likely cause is that it can’t find one of the files or there is a syntax error in the conf file.
          When testing I would start the broker manually from the command line using
          mosquitto -c myconfile.conf.
          Place the myconfile in the home directory as it is easier than having to edit the conf file in the etc folder.
          You can move it there when done.
          Rgds
          Steve

        2. Btw in mosquitto.conf i only have:
          port 8883
          cafile /root/jbre/SSL/ca.crt
          certfile /root/jbre/SSL/server.crt
          keyfile /root/jbre/SSL/server.key
          require_certificate true

  14. Some stuff i found out following your tutorial:
    – Common name MUST be you computer name. I couldn’t find out how to use wildcards to make it work on a PC in a domain (PC at work), but on a non network managed computer (my home computer) it finally worked.

    – If you set ‘tls_version tlsv1’ in the mosquitto.conf file, you MUST use ‘–tls-version tlsv1’ on the pub/sub command line or it will default to TLS v1.2
    > mosquitto_sub -h DESKTOP-09SCS82 -p 8883 –cafile ca.crt -t hello/world –tls-version tlsv1

    1. Quick update, got it working on a managed network. Here’s the deal, your System window (windows key + pause break) has three informations:
      – Computer Name
      – Full Computer Name
      – Domain

      You should use “*.your.domain.name.com” as your CN so you can estabilish a connection from every computer in the network that has the certifcate. When stabilishing a connection, your host must be the “Full Computer Name” information like mosquitto_sub -h PC023.your.domain.name.com -p 8883 –cafile ca.crt -t hello/world –tls-version tlsv1

      1. Thank you so much! This solved my issue.
        Common name is so important. When generating Certificate Sign Request, we have to use “*.myDomain.com” or “myComputerName.myDomain.com” as the common name. Then when doing the client connection, host has to be “myComputerName.myDomain.com”.
        That is how the TLS certificate works!

  15. If you’re seeing this error: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed

    I’d suggest use the server.crt on the client side. Someone named Vicky from comments above has explained why it could be the thing.

    Cheers
    vin

  16. when I run mosquitto broker I don’t get
    “enter pem passphrase:” prompt as I have seen in other youtube video.

    1. It is because you have password protected one or more of the files.There is a note in the tutorial about this. It should still work ok

  17. I tried wireshark to see where it is going wrong and found that
    Server hello is successfully done
    Client sends Client key Exchange, Change Cipher spec, Encrypted handshake Message
    that Server replys with RST and abruptly drops communication

  18. Steve
    Thanks for reply, yes I tried –insecure I didn’t try paho-client, yes broker is running on Windows,
    I have checked following things
    – firewall is not blocking TCP traffic
    – tried different port number
    – running mosquitto_pub on separate admin cmd (console window) ,
    – running mosquitto_pub on vmware
    – can establish mqtt communication without TLS/SSL
    – make sure that password file is not mentioned and password required is off
    – make sure allow allow_anonymous true (i.e default but tried explicitly set)

    Difference from defualt/original mosquitto.conf is following
    – #port 1883 -> port 8883
    – cafile c:\mosquitto\certs\ca.crt
    – keyfile c:\mosquitto\certs\server.key
    – certfile c:\mosquitto\certs\server.crt
    tried server key with/without passphrase

    I have Win32OpenSSL-1_1_0g installed.
    from this installation I have copied following dlls to mosquitto folder
    libcrypto-1_1.dll
    libssl-1_1.dll
    pthreadVC2.dll

    I have run following command and don’t get any error except
    openssl s_client -showcerts -connect MyTest-PC:8883

    Protocol : TLSv1.2
    Verify return code: 18 (self signed certificate)

    1. I have found the problem after debugging through mosquitto and openssl source code.
      When creating CA and Server certificate I provided exactly same (I mean exactly identical input for all fields) detail in step 2 and 4. If we do this then SSL thinks it is single certificate solution, and compare ca.crt and server.crt because both have different SH1 thumbprint so it fails it. in this case if we use same certificate (i.e server.crt ) both on client and server then it probably works. Here in this article example slightly different information is provided, for example field “organization name” has different value provided in step 2 and 4, this is crucial even single character difference will work fine 🙂 and I failed to notice this, on a bright side it gave me chance to look into source code mosquitto broker and openssl source code 🙂

      1. Tks for that I do remember a while ago reading something about that but it wasn’t really that clear. I’ll update the tutorial to make everyone aware.
        Rgds
        steve

        1. Hi , regarding to what vicky said , does it mean that as long the input for all field are different in step 2 and 4 in mosquitto_pub i can call ca.crt instead of server.crt ? Currently it works without error when i use server.crt
          Regards
          wayne

          1. Hi
            Only one field needs to be slightly different.On the client you use the ca.crt certificate not the server .crt

  19. I followed steps in this tutorial. Tried out on Windows.
    I am getting error
    ” New connection from 10.186.0.66 on port 8883″
    “Socket error on client , disconnecting.” on server and on client side I get “A TLS error occured”.
    I am using CN=My computer name where I am rung mosquitto server. I tried client from VMWare and on same local machine where mosquitto sever is running both gives same error.

    1. Use the tls_insecure_set(True) on the python client or the –insecure switch in the mosquitto_pub tool.
      To eliminate problems with the server name on the certificate.
      Is your broker also running on Windows?

  20. Hi Steve, I am having some problems with this. Perhaps a second pair of eyes would help:

    My key generation process is basically a copy paste of the commands you have in your setup. The only change I have is instead of using ws4, I am using my local computer name (computer name is ubuntu)

    The same computer is running the MQTT Broker and the Client:

    My configuration file TLS section is as follows:
    listener 8883
    cafile /home/edyza/Desktop/tls/ca.crt
    keyfile /home/edyza/Desktop/tls/server.key
    certfile /home/edyza/Desktop/tls/server.crt
    require_certificate false
    tls_version tlsv1

    Here is my python code:
    import paho.mqtt.client as mqtt
    import ssl

    broker = “ubuntu”
    port = 8883

    def on_connect(client, userdata, flags, rc):
    print(“Connected with result code “+str(rc))
    client.subscribe(“#”, qos=1)

    def on_message(client, userdata, msg):
    print(msg.topic+” “+str(msg.payload))

    def on_log(client, userdata, level, buf):
    print(“Buffer:{}”.format(buf))

    id = “123456123456”

    client = mqtt.Client(
    client_id=””, clean_session=True, userdata=None, protocol=mqtt.MQTTv311
    )

    client.on_log = on_log
    client.on_connect = on_connect
    client.on_message = on_message

    client.tls_set(
    ca_certs=”/home/edyza/Desktop/tls/ca.crt”, tls_version=ssl.PROTOCOL_TLSv1
    )

    client.tls_insecure_set(True)
    client.connect(broker, port)
    client.loop_forever()

    Here is my traceback:
    Traceback (most recent call last):
    File “/home/edyza/edyza-gateway/server/mqtt_services/mqtt_bridge/mqtt_bridge/test.py”, line 36, in
    client.connect(broker, port)
    File “/home/edyza/miniconda3/envs/mqtt_bridge/lib/python3.5/site-packages/paho/mqtt/client.py”, line 768, in connect
    return self.reconnect()
    File “/home/edyza/miniconda3/envs/mqtt_bridge/lib/python3.5/site-packages/paho/mqtt/client.py”, line 927, in reconnect
    sock.do_handshake()
    File “/home/edyza/miniconda3/envs/mqtt_bridge/lib/python3.5/ssl.py”, line 996, in do_handshake
    self._sslobj.do_handshake()
    File “/home/edyza/miniconda3/envs/mqtt_bridge/lib/python3.5/ssl.py”, line 641, in do_handshake
    self._sslobj.do_handshake()
    ssl.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:719)

    And the error message from console of the broker is:

    edyza@ubuntu:~/edyza-gateway$ mosquitto -c ./server/configs/mosquitto.conf -v
    1520979358: mosquitto version 1.4.15 (build date Wed, 28 Feb 2018 11:29:47 +0000) starting
    1520979358: Config loaded from ./server/configs/mosquitto.conf.
    1520979358: Opening ipv4 listen socket on port 8883.
    1520979358: Opening ipv6 listen socket on port 8883.
    1520979359: New connection from 127.0.0.1 on port 8883.
    1520979359: OpenSSL Error: error:14094418:SSL routines:ssl3_read_bytes:tlsv1 alert unknown ca
    1520979359: OpenSSL Error: error:140940E5:SSL routines:ssl3_read_bytes:ssl handshake failure
    1520979359: Socket error on client , disconnecting.

    I know this is a lot of trace to parse, but can you please point me to the right direction here?

    1. Hi Steve, I think there is a typo in the tutorial. When I change the line in my python code from

      client.tls_set(
      ca_certs=”/home/edyza/Desktop/tls/ca.crt”,
      tls_version=ssl.PROTOCOL_TLSv1
      )

      to

      client.tls_set(
      ca_certs=”/home/edyza/Desktop/tls/server.crt”,
      tls_version=ssl.PROTOCOL_TLSv1
      )

      Everything works as I expect it to

      1. Hi
        The text in the tutorial is correct it should be the CA certificate on the client. However what you call it is really up to you.
        I think that maybe you got the files mixed up. I did it several time when I was creating the files for various machines.

  21. Thanks, a really great blog for using TLS/SSL.

    When following the steps, I got the following error messages when I use ca.crt on the client PC.
    1520070804: OpenSSL Error: error:14094418:SSL routines:ssl3_read_bytes:tlsv1 alert unknown ca
    1520070804: OpenSSL Error: error:140940E5:SSL routines:ssl3_read_bytes:ssl handshake failure

    After changing ca.crt to server.crt, I can sub/pub message from the client.

  22. Hi,

    When i use my mac (client) to send mosquitto_pub -h 192.168.0.111 -t hello/world -p 8883 –cafile /Users//ca.crt -m “hello”
    Error: A TLS error occurred.

    The MQTT broker is returning
    OpenSSL Error: error:14094418:SSL routines:SSL3_READ_BYTES:tlsv1 alert unknown ca
    1517743023: OpenSSL Error: error:140940E5:SSL routines:SSL3_READ_BYTES:ssl handshake failure

    Note i set the CN to the IP address of my Pi (MQTT broker), when generating the certs, because with the name of the pi was causing a resolve error. The mac (client) has the exact copy of ca.crt.

    Do you know what might be causing this? It looks like the server is not accepting the CA that im sending, but it is the one I generated earlier?
    Thanks,
    Dan

    1. I was having same issue. It was corrected after giving different email id for ca certificate and server certificate.

  23. Hi Steve,
    Thanks a lot for all your great articles on MQTT.
    I would like to check with you, if it is possible to set up MQTT (mosquitto broker) with TLS1.2 and the OCSP Stapling is enabled ?
    If I’m getting a TLS certificate from a valid CA (not to create one on my own) for this purpose, do you think it will work without any additional configuration in Mosquitto broker ?

    1. Sorry but I’m not really sure. As far as I am aware the python client doesn’t check and I don’t think it is supported by mosquitto as it is.
      The certificate might work but not with OCSP. I’d be interested to hear how you get on

  24. How to use TLS connection via web client? In javascript library “mqttws31.js”, there is only an option named:useTLS, but no parameter to import ca.crt file, anyone can answer me? thanks.

    1. I think it is because the script uses the certificate store of the browser and so you would need to import the certificate into your browser.
      If it isn’t trusted then you should get an error.

  25. Hi Steve,
    Thanks for the valuable info.
    Do you have any inputs for using the client certificates on IOT devices?

    Regards,
    Prad

    1. Personally I don’t think devices like sensors will use SSL, especially initially as most are likely to use other protocols other than MQTT.
      I think it will be important between brokers i.e. from the MQTT gateway to the cloud.

  26. My system is 3.10.0-514.10.2.el7.centos.plus.x86_64

    mosquitto version: 1.4.13 (build date 2017-07-01 11:06:40+0000)

    Firstly, i created a folder where /etc/mosquitto/certs
    Then respectively

    1- openssl genrsa -des3 -out ca.key 2048
    2- openssl req -new -x509 -days 1826 -key ca.key -out ca.crt
    3- openssl genrsa -out server.key 2048
    4- openssl req -new -out server.csr -key server.key
    5- openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 360

    i used hostname for certificates with my domain ip adress

    My mosquitto.conf
    cafile /etc/mosquitto/certs/ca.crt
    keyfile /etc/mosquitto/certs/server.key
    certfile /etc/mosquitto/certs/server.crt
    require_certificate false
    tls_version tlsv1

    i can try to connect mosquitto with;
    mosquitto_pub -h “mydomainipadress” -p 8883 -u “usernam” -P “password” -t temp –cafile /etc/mosquitto/certs/ca.crt -m “testmessage” -d

    This is giving me a errot which “A TLS error occurred.”

    I also try to connect with python3.6 with codes;
    import sys
    import time
    import mail
    import paho.mqtt.publish as publish
    import paho.mqtt.client as paho
    import ssl
    auth = {‘username’:”a”, ‘password’:”*”}
    def on_connect(client, userdata, flags, rc):
    global conn_flag
    conn_flag = True
    broker=”domainipadress”
    port = 8883
    while True:
    client=paho.Client()
    client.tls_set(“/etc/mosquitto/certs/ca.crt”)
    client.on_connect=on_connect
    client.connect(broker,port)
    text = open(“info.txt”,”r”)
    t = text.readline(2)
    print(t)
    publish.single(topic=”temp”,payload=t,hostname=broker,auth=auth,port=8883)

    and it gives me a error too like

    sock.do_handshake()
    File “/usr/lib64/python3.6/ssl.py”, line 1061, in do_handshake
    self._sslobj.do_handshake()
    File “/usr/lib64/python3.6/ssl.py”, line 683, in do_handshake
    self._sslobj.do_handshake()
    ssl.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:749)

    Where am i doing wrong? Can anybody help me ?

    1. You could try the tls_insecure_set(True) on the python client to rule out the domain name on the CA certificate.
      the python error code seems to point to CA file problems
      You should check your mosquitto.conf file that it matched mine in the tutorial.
      The main problems I encountered were the wrong version number and the name on the certificate.
      You are using username/password. I like to test without to make it simpler as I also encountered lots of problems that caused it to fail that were not ssl related.
      If you still have problems you can send me your certificate files and I can try them on my test machine.

      1. I tryed before that tls_insecure_set, without password_file but it still doesn’t work. If you send me your mail adress i can send you certificates.

        1. Oguz fixed the problem as follows:

          I found what where is the problem. Main problem is that openssl version. When i updated openssl version and created new certificates that problem has gone on centos 7. Centos has openssl verison date in 2013 with default, we need to update.

  27. I would like to get this working using a wildcard certificate. I have gotten past the TLS errors and managed to crank up the websocket logging, but I can’t figure out why the broker is dropping mosquitto_sub and mosquitto_pub. I can get http://www.hivemq.com/demos/websocket-client/ to stay connected and pass messages, but not the bundled test tools.

    Command:
    mosquitto_pub -h mqtt.example.com -p 8883 -t test –cafile /home/root/local_cert/COMODO_DV_SHA-256_bundle.crt -u “user” -P “password” -m “hello world”

    Details below :

    in mosquitto.conf
    websockets_log_level 2047

    Logs :
    1496460723: mosquitto version 1.4.8 (build date Tue, 23 May 2017 22:14:40 +0100) starting
    1496460723: Config loaded from /etc/mosquitto/mosquitto.conf.
    1496460723: Opening ipv4 listen socket on port 1883.
    1496460723: Opening websockets listen socket on port 8883.
    1496460723: Initial logging level 2047
    1496460723: Libwebsockets version: 1.7.1 unknown-build-hash
    1496460723: IPV6 not compiled in
    1496460723: libev support compiled in but disabled
    1496460723: LWS_DEF_HEADER_LEN : 1024
    1496460723: LWS_MAX_PROTOCOLS : 5
    1496460723: LWS_MAX_SMP : 32
    1496460723: SPEC_LATEST_SUPPORTED : 13
    1496460723: sizeof (*info) : 216
    1496460723: SYSTEM_RANDOM_FILEPATH: ‘/dev/urandom’
    1496460723: default timeout (secs): 20
    1496460723: Threads: 1 each 1024 fds
    1496460723: mem: context: 62808 bytes (58712 ctx + (1 thr x 4096))
    1496460723: mem: http hdr rsvd: 67712 bytes (1 thr x (1024 + 3208) x 16))
    1496460723: mem: pollfd map: 8192
    1496460723: mem: platform fd map: 8192 bytes
    1496460723: LWS_MAX_EXTENSIONS_ACTIVE: 2
    1496460723: mem: per-conn: 808 bytes + protocol rx buf
    1496460723: canonical_hostname = ip-172-31-9-197
    1496460723: Compiled with OpenSSL support
    1496460723: Using SSL mode
    1496460723: SSL ECDH curve ‘prime256v1’
    1496460723: insert_wsi_socket_into_fds: 0x16056b0: tsi=0, sock=8, pos-in-fds=1
    1496460723: Listening on port 8883
    1496460732: accepted new conn port 61718 on fd=9
    1496460732: Accepted 0x16060f0 to tsi 0
    1496460732: lws_adopt_socket: new wsi 0x16060f0
    1496460732: insert_wsi_socket_into_fds: 0x16060f0: tsi=0, sock=9, pos-in-fds=2
    1496460732: inserted SSL accept into fds, trying SSL_accept
    1496460732: SSL_accept failed 2 / error:00000002:lib(0):func(0):system lib
    1496460732: SSL_ERROR_WANT_READ
    1496460732: accepted new SSL conn
    1496460732: lws_header_table_attach: wsi 0x16060f0: ah (nil) (tsi 0)
    1496460732: lws_header_table_attach: wsi 0x16060f0: ah 0x15ee470: count 1 (on exit)
    1496460732: lws_server_socket_service: 0x16060f0: rxpos:0 rxlen:0
    1496460732: lws_server_socket_service: wsi 0x16060f0, ah->rxlen = 55
    1496460732: lws_read: incoming len 55
    1496460732: issuing 55 bytes to parser
    1496460732: WSI_TOKEN_NAME_PART ” (mode=0)
    1496460732: Unknown method – dropping
    1496460732: lws_parse failed
    1496460732: lws_header_table_detach: wsi 0x16060f0: ah 0x15ee470 (tsi=0, count = 1)
    1496460732: closing connection at lws_read bail:
    1496460732: lws_close_free_wsi: shutting down connection: 0x16060f0
    1496460732: lws_server_socket_service: wsi 0x16060f0 read -1
    1496460732: lws_close_free_wsi: real just_kill_connection: 0x16060f0
    1496460732: remove_wsi_socket_from_fds: wsi=0x16060f0, sock=9, fds pos=2, end guy pos=3, endfd=0
    1496460732: not calling back closed mode=0 state=2
    1496460732: lws_free_wsi: 0x16060f0, remaining wsi 1
    1496460761: mosquitto version 1.4.8 terminating

  28. In case this helps, I was running into those same errors as Kirk and Max (I am using mosquitto_pub/mosquitto_sub as the client) I was able to get it working by using the parameter ‘–cafile” rather than “–capath” and specifying the complete path to the cafile. Below is an example:

    mosquitto_pub -h host.name -u username -P password -t test/topic -p 8883 –cafile ~/keys/ca.crt -m message

    Great tutorial Steve, many thanks!

  29. Running into the same issue like ‘Kirk Bailey’.
    Getin this strange error even though i did everything like you.
    I changed the TLS version to 1.1 and 1.2 but without success.
    If anybody solved this, i would appreacate your help.

    Cheers, Max

    1. Use the contact form and send me a screenshot of the broker console. If you send me your certificates and keys I’ll try them on my broker.
      I’ve been trying to reproduce your error. I get a similar one when using different CA files on client and broker. Have you copied over the broker CA to the client.
      Additionally the mosquiito_sub and pub programs default to version 1.2. If you use the python client it defaults to version1.
      If you are using the wrong version the consoles log tells you quite clearly the problem

        1. Can you describe exactly what error message you are seeing and how you are testing. Did you create your own certificates and keys?

          1. Installed the latest version of Mosquitto and Openssl on a server 2012 instance. Works fine, but now trying to enable TLS. I cannot get a purchased nor self signed certificate to work..

            Steps i’ve taken:
            I placed the certificates into a folder and set the following values:
            cafile C:\mosquitto\certs\ca.crt
            certfile C:\mosquitto\certs\server.crt
            keyfile C:\mosquitto\certs\server.key
            Changed the port from 1883 to 8883.
            restarted Mosquitto. It starts up without issue.

            Everytime i try to connect from a client, i get the following message:
            OpenSSL Error: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown
            OpenSSL Error: error:140940E5:SSL routines:ssl3_read_bytes:ssl handshake failure

            i re imported this certificate about 50 times now. i’ve tried every option possible. I’ve tried using .pem instead of .crt.

          2. Steve
            Here are the notes you sent me by email on how you got it working using a comado certificate.

            1) openssl genrsa -out verCert.key 2048
            2) openssl req -new -key verCert.key -out verCert.csr
            3) Submit the .csr to CA(in my case, its Comado) and complete the registration process.
            4) You will receive a email from Comado containing two files. Besides the .crt file, i also received back a “subdomain.domain.com.ca.bundle” file.
            5) open the “subdomain.domain.com.ca.bundle” file with notepad++.
            6) Two certificate files are inside the bundle file(subdomain.domain.com.ca.bundle). Copy the text from the first one(from —–BEGIN CERTIFICATE—– to —–END CERTIFICATE—–) and create a new file called ca.crt with the contents.
            7) The 2nd .crt file is already enclosed in the email from Comado(file should be named (subdomain.domain.com.crt).
            8) Copy all three files(ca.crt, subdomain.domain.com.crt, verCert.key) to your mosquitto cert folder.
            9) edit the mosquitto config file(make sure logging is enabled to help troubleshoot)
            Mosquitto config should have the following:
            cafile C:\mosquitto\certs\ca.crt
            certfile C:\mosquitto\certs\subdomain.domain.com.crt
            keyfile C:\mosquitto\certs\verCert.key
            port 8883
            tls_version tlsv1.2

            11) if all settings are correct, you should see valid connection info in the log files when connecting with your mqtt client.

  30. I tried using your certificate-generation technique because it’s simpler than the one that comes with the Mosquitto test code. If I run the broker using these certs, but when I try to connect a client, I get the error (at the broker) “OpenSSL Error: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown”. The client I used was the “mosquitto_sub” that comes with the package. Everything works if I instead use the certs generated by the cert-generation script that comes with the test code. Any idea why this would be? Do your certs work with your version of mosquitto_sub?

Leave a Reply

Your email address will not be published. Required fields are marked *