设置
我正在尝试使用双向 TLS 将 Java 客户端连接到 mosquitto MQTT 代理。客户端和代理位于两个能够相互通信的独立虚拟机上。我正在尝试连接端口 8883。当我尝试使用自签名 PEM 格式证书连接时,连接成功。但是,当我尝试连接我公司内部 CA 生成的证书时,连接不会发生,客户端上的一条错误消息和代理上的一条错误消息。证书在每一侧都不同。每个都是使用与它所在的 vm 匹配的通用名称生成的,并且都是从同一个 CA 生成的。至于代码,socketFactory代码如下,
socketFactory = SslUtil.getSocketFactory(Config.caFilePath,
Config.clientCrtFilePath,
Config.clientKeyFilePath,
Config.clientKeyPass);
用于连接的特定库是 Paho。
客户端错误信息:
MqttException (0) - javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
经纪人:
1631135618: New connection from 1.1.1.1 on port 8883.
1631135618: OpenSSL Error[0]: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown
1631135618: Socket error on client <unknown>, disconnecting.
1631135618: New connection from 1.1.1.1 on port 8883.
1631135618: OpenSSL Error[0]: error:14094416:SSL routines:ssl3_read_bytes:sslv3 alert certificate unknown
1631135618: Socket error on client <unknown>, disconnecting.
我已经能够将问题缩小到与客户端进行身份验证的代理(服务器)。我这样做的方法是使用真实证书和自签名 CA 运行客户端,同时使用真实 CA 和自签名证书运行代理,如下所述。
所有自签名作品
客户 | <-----> | 经纪人 |
---|---|---|
自签名crt | 自签名crt | |
自签名密钥 | 自签名密钥 | |
自签名证书 | 自签名证书 |
客户真实证书和经纪人自签名作品
客户 | <-----> | 经纪人 |
---|---|---|
真正的crt | 自签名crt | |
真正的钥匙 | 自签名密钥 | |
自签名证书 | 真正的钙 |
所有真正的证书都不起作用
客户 | <-----> | 经纪人 |
---|---|---|
真正的crt | 真正的crt | |
真正的钥匙 | 真正的钥匙 | |
真正的钙 | 真正的钙 |
证书验证 我检查了证书是否配置正确。
- 它们的通用名称与它们运行的虚拟机的主机名相同
- 证书被 CA 接受
wireshark 数据包捕获 我使用自签名证书和一个使用真实证书的连接执行数据包捕获。它们在读取证书的方式上有所不同。在自签名证书捕获中,顺序是发送客户端问候,然后发送服务器问候、证书、服务器密钥交换、证书请求、服务器问候完成在 1 个回复中发送。在真正的证书捕获中,顺序是 Client Hello 发送,Server Hello 发送,然后 Certificate,Server Key Exchange,Certificate Request,Server Hello Done。服务器问候是单独发送的,字节表明证书值包含在此数据包中,但未被识别。似乎服务器 hello 错误地包含了证书值。
我已经用完了我能想到的选项。任何想法都会受到欢迎!