Search code examples
pythonsslmqttpahopython-3.7

Problems using paho mqtt client with python 3.7


I am running the following code to connect to a mqtt server.

import paho.mqtt.client as mqtt
import ssl
import uuid

client = mqtt.Client(str(uuid.uuid1()))
client.tls_set(
    "ca.crt",
    "client.crt",
    "client.key",
    cert_reqs=ssl.CERT_REQUIRED,
    tls_version=ssl.PROTOCOL_TLSv1
)
client.connect(
    "127.0.0.1",
    8883,
)
client.loop_forever()

This code works fine with python2.7 version. But when I run it with python3.7 version I am getting the below error.

Traceback (most recent call last):
  File "test.py", line 29, in <module>
    8883,
  File "virtualenvs/mqtt-xG2h6zri/lib/python3.7/site-packages/paho/mqtt/client.py", line 839, in connect
    return self.reconnect()
  File "mqtt-xG2h6zri/lib/python3.7/site-packages/paho/mqtt/client.py", line 994, in reconnect
    sock.do_handshake()
  File ".pyenv/versions/3.7.0/lib/python3.7/ssl.py", line 1108, in do_handshake
    self._sslobj.do_handshake()
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: IP address mismatch, certificate is not valid for '127.0.0.1'. (_ssl.c:1045)

Please help me figure out how to make this work in python 3.7.


Solution

  • Found the answer.

    Actually, according to this link matching server IP address with CN field of certificate is deprecated for more than 15 years. But python versions lower than 3.7 still allow this even though it is deprecated. Therefore I had to create a certificate with the ip address of the server added in the SAN field.

    Creating certificates with SAN fields is explained in this answer. But the solution in the answer uses domain names. If you are creating certificates with IP address use this command to create a certificate instead of the command in that answer.

    openssl x509 -req -in server.csr \
            -extfile <(printf "subjectAltName=IP:127.0.0.1") \
            -CA ca.crt \
            -CAkey ca.key \
            -CAcreateserial -out server.crt \
            -days 365
    

    After using these certificates the error is solved.