目前,我正在做一个MQTT测试项目。因此,我设置了一个必须与 TLS 配合使用的 Mosquitto MQTT 代理。问题是,我无法使用安全 TLS 连接通过 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代理的密钥对:
$ openssl genrsa -out server.key 2048
使用服务器密钥创建证书签名请求,发送给假 CA 进行身份验证:
$ openssl req -new -key server.key -out server.csr -sha256
现在作为假CA,我收到了服务器对我的签名请求。我已经验证了服务器的真实身份(在特定 IP 上运行的 MQTT 代理),因此我创建了一个新证书并使用我的虚假权限的所有权力对其进行了签名:
$ openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 360
创建服务器证书和密钥后,我将这些文件放置在各自的文件夹中,并将 Mosquitto 配置为使用它们来启用 TLS。为此,我修改了
default.conf
:
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
现在我在 paho mqtt 库的帮助下编写了一个 python 脚本来创建一个 mqtt 订阅者客户端。为了启用双向安全连接,我还使用这三个命令为客户端生成了一个证书:
openssl genrsa -out client.key 2048
openssl req -new -out client.csr -key client.key
openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client.crt -days 360
我的Python代码在paho mqtt库的TLS设置中使用CA证书(ca.crt)、客户端证书(client.crt)和客户端密钥(client.key)。代码如下所示:
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()
请注意,我在另一台计算机上执行此 python 脚本,并将证书和客户端密钥复制到该计算机。我还通过事先使用不带 TLS 的连接尝试了 MQTT Broker 的一般功能。效果很好。
但是,如果我想执行 python 脚本(使用 TLS)来订阅主题,我会得到以下信息:
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 通信?
我按照本指南解决了问题。感谢哈迪尔布的评论!当我用谷歌搜索你的弃用警告时,我找到了指南。