You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让Paho MQTT客户端信任自签名证书以实现TLS连接?

问题:Paho MQTT客户端无法连接使用自签名证书的Mosquitto Broker

我正在开展一个MQTT测试项目,搭建了需通过TLS运行的Mosquitto MQTT Broker,但因使用自签名证书,无法通过Paho MQTT客户端建立安全TLS连接。

证书生成步骤

我使用OpenSSL执行了以下步骤生成证书:

  • 生成伪造CA签名密钥:$ openssl genrsa -des3 -out ca.key 2048
  • 生成伪造CA的证书签名请求:$ openssl req -new -key ca.key -out ca.csr -sha256
  • 创建伪造CA的根证书:$ openssl x509 -req -in ca.csr -signkey ca.key -out ca.crt -days 365 -sha256
  • 创建服务器/MQTT Broker密钥对:$ openssl genrsa -out server.key 2048
  • 使用服务器密钥生成证书签名请求(通用名称设为Broker的特定IP):$ openssl req -new -key server.key -out server.csr -sha256
  • 以伪造CA身份签署服务器证书:$ openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 360

Mosquitto配置

修改default.conf启用TLS:

listener 8883

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

require_certificate true

password_file /etc/mosquitto/passwd

客户端证书生成与Python代码

为实现双向认证,生成客户端证书:

  • 创建客户端密钥对:openssl genrsa -out client.key 2048
  • 生成客户端证书签名请求:openssl req -new -out client.csr -key client.key
  • 以伪造CA身份签署客户端证书:openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client.crt -days 360

Python客户端代码:

import paho.mqtt.client as mqtt
import ssl

def on_message(client, userdata, msg):
    print(f"Received message '{msg.payload.decode()}' on topic '{msg.topic}'")

def on_connect(client, userdata, flags, rc):
    if rc == 0:
        print("Connected to MQTT Broker!")
        client.subscribe("test")
    else:
        print(f"Failed to connect, return code {rc}\n")

client = mqtt.Client()

client.on_connect = on_connect
client.on_message = on_message

username = "x"
password = "x"
client.username_pw_set(username, password)

client.tls_set(ca_certs="certs/ca.crt",
               certfile="certs/client.crt",
               keyfile="certs/client.key",
               tls_version=ssl.PROTOCOL_TLSv1_2)

client.tls_insecure_set(False)  # Ensure this is False for security

broker_address = 'my_ip'  
port = 8883 
client.connect(broker_address, port)

client.loop_forever()

错误信息

执行脚本时出现以下错误:

mqtt_sub.py:17: DeprecationWarning: Callback API version 1 is deprecated, update to latest version
  client = mqtt.Client()
Traceback (most recent call last):
  File "mqtt_sub.py", line 39, in <module>
    client.connect(broker_address, port)
  File "/home/lutz/.local/lib/python3.8/site-packages/paho/mqtt/client.py", line 1435, in connect
    return self.reconnect()
  File "/home/lutz/.local/lib/python3.8/site-packages/paho/mqtt/client.py", line 1598, in reconnect
    self._sock = self._create_socket()
  File "/home/lutz/.local/lib/python3.8/site-packages/paho/mqtt/client.py", line 4612, in _create_socket
    sock = self._ssl_wrap_socket(sock)
  File "/home/lutz/.local/lib/python3.8/site-packages/paho/mqtt/client.py", line 4671, in _ssl_wrap_socket
    ssl_sock.do_handshake()
  File "/usr/lib/python3.8/ssl.py", line 1338, in do_handshake
    self._sslobj.do_handshake()
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate (_ssl.c:1145)

需求:如何让Paho MQTT库与自签名证书配合使用,或有哪些其他方案实现安全MQTT通信?


解决方案

1. 确认CA证书的信任配置

错误提示“self signed certificate”说明客户端未正确信任你生成的CA根证书:

  • 检查ca_certs参数的路径是否正确:建议使用绝对路径(如/home/user/certs/ca.crt)避免相对路径问题,确保文件是你生成的CA根证书。
  • 将CA证书添加到客户端系统的信任根库:
    • Linux:复制ca.crt到/usr/local/share/ca-certificates/,执行update-ca-certificates更新信任列表。
    • Windows:双击ca.crt,选择安装到“受信任的根证书颁发机构”存储区。

2. 验证服务器证书的标识匹配

你将服务器证书的通用名称设为Broker的IP,需确保客户端连接时使用的broker_address与该IP完全一致,不能用主机名(除非证书包含主机名SAN字段):

  • 若需用主机名连接,重新生成服务器证书并添加SAN字段:
    创建server.cnf配置文件:
    [req]
    distinguished_name = req_distinguished_name
    req_extensions = v3_req
    prompt = no
    
    [req_distinguished_name]
    CN = 192.168.1.100  # Broker的IP
    
    [v3_req]
    keyUsage = keyEncipherment, dataEncipherment
    extendedKeyUsage = serverAuth
    subjectAltName = @alt_names
    
    [alt_names]
    IP.1 = 192.168.1.100
    DNS.1 = broker.local  # Broker的主机名
    
    生成CSR:openssl req -new -key server.key -out server.csr -sha256 -config server.cnf,再重新签署服务器证书。

3. 检查双向认证配置一致性

Mosquitto配置了require_certificate true,客户端必须提供信任CA签署的证书:

  • 确认client.crt是你的CA根证书签署的,且代码中certfile和keyfile路径正确。
  • 若客户端密钥带密码(生成时用了-des3),需在代码中添加密码参数,或重新生成无密码密钥:openssl genrsa -out client.key 2048。

4. 临时调试(禁止生产环境使用)

测试阶段可临时跳过服务器证书验证,但会降低安全性:

  • 将client.tls_insecure_set(True),此操作仅跳过服务器证书验证,双向认证仍生效。

替代安全方案

若自签名证书配置繁琐,可选择以下方案:

  • Let's Encrypt证书:若Broker有公网域名,申请免费可信证书,客户端无需额外配置即可信任。
  • 预共享密钥(PSK):Mosquitto支持PSK认证,无需证书,只需客户端与Broker共享密钥。示例配置:
    listener 8883
    psk_hint hint
    psk_file /etc/mosquitto/psk.txt
    
    客户端代码使用client.tls_set_psk()方法配置PSK。

内容的提问来源于stack exchange,提问作者Lennart Lutz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.18 02:00:55