Mosquitto Broker TLS连接报sslv3 alert bad certificate错误
问题根因
两端报错是同一个问题触发的连锁反应,核心原因如下:
- 你当前部署的broker服务端证书为X.509 Version 1 版本,该版本标准不支持
Subject Alternative Name (SAN,主题备用名称)扩展字段,且你贴出的证书有效期到2023年7月9日,本身已经过期。 - Python标准库
ssl模块和mosquitto_pub的证书校验逻辑存在本质差异:mosquitto_pub调用原生OpenSSL接口做校验,当证书不存在SAN字段时,会回退读取证书Subject中的CN字段做匹配,你证书CN值正好是192.168.1.254,和连接时用的IP一致,所以命令行连接无报错。- Python的
ssl模块从3.7版本开始严格遵循RFC 5280标准,仅从SAN扩展字段读取待匹配的IP/域名,完全不会回退校验CN字段内容,因此直接抛出「IP address mismatch」错误;客户端校验失败后会向broker发送错误告警,broker端日志就对应显示sslv3 alert bad certificate——这个报错不是指你的客户端证书有问题,只是broker记录收到的客户端告警而已。
- 你的Python脚本存在两处配置笔误:
- 脚本中写的CA证书路径是
/etc/mosquitto/ca.pem、客户端证书路径是/etc/mosquitto/VM.pem,但你正常连通的命令行用的是ca.crt和VM.crt,文件名不匹配会直接导致证书加载失败。 - 调用
tls_set()时仅传入了CA证书参数,没有加载双向TLS认证需要的客户端证书、客户端密钥参数,即使证书校验通过也会因为缺少客户端凭证被broker拒绝。
- 脚本中写的CA证书路径是
修复步骤
- 第一步:重新签发带SAN扩展的X.509 v3版本服务端证书
签发时必须在OpenSSL配置中添加v3扩展段,把树莓派IP写入SAN字段,示例配置片段如下:
签发服务端证书时添加[v3_ext] basicConstraints = CA:FALSE keyUsage = digitalSignature, keyEncipherment extendedKeyUsage = serverAuth subjectAltName = IP:192.168.1.254 # 如果后续需要用域名连接,可追加DNS记录,例如: # subjectAltName = IP:192.168.1.254,DNS:raspberrypi.local-extensions v3_ext参数,确保证书生成时加载上述扩展配置,同时把证书有效期设置为合理时长。 - 第二步:校验新证书有效性
签发完成后执行命令校验证书内容:
确认输出满足两个要求:openssl x509 -in 新服务端证书路径 -text -noout- 证书版本显示为
Version: 3 (0x2) - 扩展字段中存在
X509v3 Subject Alternative Name条目,且内容包含IP Address:192.168.1.254
- 证书版本显示为
- 第三步:修正Python脚本配置
统一证书文件名和实际路径,补全客户端证书、密钥的加载参数,修正后示例代码如下:import ssl import paho.mqtt.client as mqtt # 和命令行使用的证书路径、文件名保持完全一致 TLS_CERT_PATH = "/etc/mosquitto/ca.crt" client_crt = "/etc/mosquitto/VM.crt" client_key = "/etc/mosquitto/parrot.key" client = mqtt.Client() client.tls_set( ca_certs=TLS_CERT_PATH, certfile=client_crt, # 补全客户端证书参数 keyfile=client_key, # 补全客户端密钥参数 cert_reqs=ssl.CERT_REQUIRED, tls_version=ssl.PROTOCOL_TLSv1_2, ciphers=None ) client.tls_insecure_set(False) client.connect("192.168.1.254", 2259, 60) client.loop_forever() - 第四步:重启mosquitto服务加载新的服务端证书,再运行Python脚本即可正常连接。
内容的提问来源于stack exchange,提问作者cbcliff47
相关产品推荐
相关产品推荐

