使用蚊子:
mosquitto_pub -h <public ip address> -t testssl/topic -m "hello world" --cafile ./ca_certificate.pem -p 8883 --tls-version tlsv1.2 -d --id client2
Client client2 sending CONNECT
Client client2 received CONNACK (0)
Client client2 sending PUBLISH (d0, q0, r0, m1, 'testssl/topic', ... (12 bytes))
Client client2 sending DISCONNECT
使用 python paho 脚本:
# python 3.11
import datetime
import json
import random
import time
import uuid
from paho.mqtt import client as mqtt_client
from config import broker, port, topic
# Generate a Client ID with the publish prefix.
client_id = f'publish-{random.randint(0, 100)}'
def connect_mqtt():
def on_connect(client, userdata, flags, rc):
if rc == 0:
print("Connected to MQTT Broker!")
else:
print("Failed to connect, return code %d\n", rc)
client = mqtt_client.Client(client_id)
client.tls_set(
ca_certs="ca_certificate.pem",
tls_version=mqtt_client.ssl.PROTOCOL_TLSv1_2,
)
# client.username_pw_set("rw", "readwrite")
client.on_connect = on_connect
client.connect(broker, port)
return client
def fake_sensor_data():
"""Generate a fake sensor data event."""
list_of_sensor_ids = [ uuid.uuid4() for _ in range(10) ]
values = [ 0, 0, 0, 0, 0, 0, 1, 0, 0 ]
return {
"timestamp": time.time(),
"device_id": str(list_of_sensor_ids[random.randint(0, 9)]),
"event": {
"payload": values[random.randint(0, 8)],
}
}
def publish(client):
while True:
time.sleep(3)
msg = json.dumps(fake_sensor_data())
result = client.publish(topic, msg)
status = result[0]
if status == 0:
print()
print(datetime.datetime.now(), msg)
def run():
print("Connecting to MQTT Broker")
print(f"Broker: {broker}")
print(f"Port: {port}")
print(f"Topic: {topic}")
client = connect_mqtt()
print("Connected!")
print("Ready to publish messages!")
client.loop_start()
publish(client)
client.loop_stop()
if __name__ == '__main__':
run()
错误:
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: IP address mismatch, certificate is not valid for '<public ip address>'. (_ssl.c:1006)
我在我的服务器上的脚本中使用 tls-gen 生成了 ca_certificate。我在其他地方读到,如果我提供公共 IP 地址而不是 DNS 名称,我应该使用 SAN,但是 tls-gen 不允许我轻松指定一个 - 最好不必修改服务器启动脚本太多了。
我想了解为什么 mosquitto 可以工作,而 python/paho 需要 SAN 来存储相同的证书文件。
mosquitto验证证书的原因可以在文件中的
mosquitto__verify_certificate_hostname
函数中找到lib/tls_mosq.c
:
可以看到,这是检查
SAN
条目,如果证书中没有 CN
部分,则仅检查 SAN
。
if(have_san_dns){
/* Only check CN if subjectAltName DNS entry does not exist. */
return 0;
}`
因此,在没有明确询问 Roger(mosquitto 维护者)的情况下,我希望这只是 mosquitto 仍然支持长期弃用的选项来使用
CN
,而 Python 已经放弃了该选项。