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

Mosquitto与TwinCAT 3 SSL证书认证连接时出现协议错误求助

问题

我是MQTT新手,希望在Windows环境下通过带SSL证书认证的MQTT连接Mosquitto与TwinCAT 3,但连接时Mosquitto提示protocol error。

我已通过OpenSSL生成SSL证书,使用的命令如下:
生成CA证书和密钥:

openssl req -x509 -newkey rsa:4096 -days 365 -keyout ca-key.pem -out ca-cert.pem -nodes

生成MQTT客户端密钥和CSR:

openssl req -newkey rsa:4096 -keyout client-key.pem -out client-req.pem -nodes

用CA签署CSR:

openssl x509 -req -in server-req.pem -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -out client-cert.pem

我已在Mosquitto程序文件夹中新建目录保存所有生成的证书和密钥,并修改Mosquitto.conf配置文件,让MQTT代理在本地8883端口启用SSL证书认证:

listener 8883
protocol mqtt
require_certificate true
cafile C:\Program Files\mosquitto\certs\ca-cert.pem
keyfile C:\Program Files\mosquitto\certs\client-key.pem
certfile C:\Program Files\mosquitto\certs\client-cert.pem

接下来,我在TwinCAT 3 PLC软件中通过以下代码设置发布客户端:

PROGRAM MAIN
VAR
    fbMqttClient: FB_IotMqttClient;
    TopicToPublish : STRING(255) := 'Temperatures';
    MessageToPublish : STRING(255);
    fbSendMessageIntervalTimer : TON := (PT:=T#1S);
    ai_RoomTemperature AT %I* : INT;
END_VAR

IF _TaskInfo[GETCURTASKINDEXEX()].FirstCycle THEN
    fbMqttClient.sHostName := '127.0.0.1';
    fbMqttClient.nHostPort := 8883;
    fbMqttClient.sTopicPrefix := '';
    fbMqttClient.sClientId := 'Publishing PLC';
    fbMqTTClient.stTLS.sCert := 'C:\Program Files\mosquitto\certs\client-cert.pem';
    fbMqTTClient.stTLS.sKeyFile := 'C:\Program Files\mosquitto\certs\client-key.pem';
    fbMqTTClient.stTLS.sCA := 'C:\Program Files\mosquitto\certs\ca-cert.pem';
    fbMqTTClient.stTLS.bNoServerCertCheck := TRUE;
END_IF
 
fbMqttClient.Execute(bConnect := TRUE);
 
IF fbMqttClient.bConnected THEN
    fbSendMessageIntervalTimer(IN:=TRUE);
    IF fbSendMessageIntervalTimer.Q THEN
        fbSendMessageIntervalTimer(IN:=FALSE);
        MessageToPublish := CONCAT('Room temperature: ',REAL_TO_STRING(ai_RoomTemperature / 10.0));
     
        fbMqttClient.Publish(sTopic:= TopicToPublish,
            pPayload:= ADR(MessageToPublish),
            nPayloadSize:= LEN2(ADR(MessageToPublish))+1,
            eQoS:= TcIotMqttQos.AtMostOnceDelivery,
            bRetain:= FALSE,
            bQueue:= FALSE);
    END_IF
END_IF

在Mosquitto中执行mosquitto -c mosquitto.conf -v并启动TwinCAT程序后,Mosquitto出现以下错误:

1665110106: New connection from 127.0.0.1:63409 on port 8883.
1665110106: Client <unknown> disconnected due to protocol error.

我还测试了无证书认证的连接,此时Mosquitto与TwinCAT 3可正常连接,输出如下:

1665110793: New connection from 127.0.0.1:63889 on port 8883.
1665110793: New client connected from 127.0.0.1:63889 as Publishing PLC (p2, c1, k60).
1665110793: No will message specified.
1665110793: Sending CONNACK to Publishing PLC (0, 0)
1665110794: Received PUBLISH from Publishing PLC (d0, q0, r0, m0, 'Temperatures', ... (22 bytes))
1665110795: Received PUBLISH from Publishing PLC (d0, q0, r0, m0, 'Temperatures', ... (22 bytes))

请问导致该协议错误的原因是什么,该如何排查解决?

原因分析
  • 证书生成错误:签署客户端CSR时,命令中误用了server-req.pem作为输入文件,但实际生成的客户端CSR是client-req.pem,导致生成的client-cert.pem无效。
  • Mosquitto配置混淆:代理的keyfile和certfile应使用服务器端专属证书和密钥,当前配置错误使用了客户端证书文件,破坏了TLS握手的身份验证逻辑。
  • TLS参数逻辑冲突:TwinCAT中设置bNoServerCertCheck := TRUE跳过服务端证书校验,但Mosquitto要求客户端提供有效证书,二者叠加引发握手协议错误。
解决步骤

1. 重新生成正确的证书链

步骤1:生成服务端证书和CSR

openssl req -newkey rsa:4096 -keyout server-key.pem -out server-req.pem -nodes

步骤2:用CA签署服务端CSR

openssl x509 -req -in server-req.pem -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -out server-cert.pem -days 365

步骤3:修正客户端证书签署命令

openssl x509 -req -in client-req.pem -CA ca-cert.pem -CAkey ca-key.pem -CAcreateserial -out client-cert.pem -days 365

2. 修正Mosquitto配置文件

将mosquitto.conf中的服务端证书配置替换为正确的服务器证书:

listener 8883
protocol mqtt
require_certificate true
cafile C:\Program Files\mosquitto\certs\ca-cert.pem
# 服务端专属密钥和证书
keyfile C:\Program Files\mosquitto\certs\server-key.pem
certfile C:\Program Files\mosquitto\certs\server-cert.pem

修改后重启Mosquitto:

mosquitto -c mosquitto.conf -v

3. 调整TwinCAT的TLS参数

取消服务端证书校验跳过(服务端证书由自有CA签署,可正常校验):

IF _TaskInfo[GETCURTASKINDEXEX()].FirstCycle THEN
    // 其他配置保持不变
    fbMqTTClient.stTLS.bNoServerCertCheck := FALSE;
END_IF

4. 验证证书有效性

用OpenSSL命令检查证书链完整性:

openssl verify -CAfile ca-cert.pem server-cert.pem client-cert.pem

输出OK则证书有效,否则检查证书生成时的CN等参数是否匹配。

5. 排查TLS握手细节

开启Mosquitto调试日志查看详细错误:

mosquitto -c mosquitto.conf -v -d

用openssl s_client测试TLS连接:

openssl s_client -connect 127.0.0.1:8883 -cert client-cert.pem -key client-key.pem -CAfile ca-cert.pem

握手成功会显示SSL连接信息,失败则会给出具体错误提示。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 15:30:51