0

我想将测试 MQTT-Client 作为 MQTT-Broker 连接到我的 Node.js 应用程序。我正在使用moscajs的 aedes 库

我的 MQTT-Client 是工具“MQTT-Explorer”,这是我的 Node.js 应用程序:

const fs = require('fs');
const aedes = require('aedes')();

const options = {
  key: fs.readFileSync('certs/server_key.pem'),
  cert: fs.readFileSync('certs/server_cert.pem'),
};

// const server = require('net').createServer(aedes.handle);
const server = require('tls').createServer(options, aedes.handle);

const PORT = 8881;

server.listen(PORT, () => {
  console.log(`server is up and running: PORT [${PORT}] - ID [${aedes.id}]`);
});

我可以毫无问题地PORT=1881与 withconst server = require('net').createServer(aedes.handle)连接,我也可以与PORT=8881withconst server = require('tls').createServer(options, aedes.handle)

使用工具xca-2.4.0.msi XCA 2.4.0,我创建了一个 ca.pem 证书文件和一个证书 server_cert.pem 和一个 server_key.pem 私钥(从 ca.pem 签名)作为服务器。CA 和服务器的密钥不同:

XCA

对于我的 MQTT 客户端,ADVANCED, CERTIFICATES, SERVER CERTIFICAT (CA)我选择了 ca.pem 文件。如果我选择“加密”,它可以工作。但如果选择“验证证书”,则会出现错误:主机名/IP 与证书的替代名称不匹配:IP:127.0.0.1 不在证书列表中

MQTT 浏览器

不幸的是,我不知道我做错了什么,在此先感谢:(

4

1 回答 1

1

MQTT Explorer是使用Node.js和 MQTT 库MQTT.js 构建的。根据这个问题

Node.js 要求 IP 地址位于证书的 subjectAltNames 中,而不是 CN。也许 MQTT.fx 不需要,但它应该。

和:

如果您的服务器证书在主题字段中显示 CN=localhost,请使用 localhost 而不是 127.0.0.1 进行连接,它应该可以工作。如果它说 CN=127.0.0.1,你必须创建一个新的,因为 Node.js 不会验证 IP 地址,除非它在 ​​SAN 扩展中。有一种方法可以在代码中解决它(我认为这是一个名为 checkServerIdentity 的选项),但如果我遇到这个问题,我更愿意修复我的证书。

此答案中列出了 Node 中采用的方法的基本原理,其中包括来自 RFC2818 的以下引用:HTTP Over TLS

在某些情况下,URI 被指定为 IP 地址而不是主机名。在这种情况下,iPAddress subjectAltName 必须出现在证书中,并且必须与 URI 中的 IP 完全匹配。

当您使用基于 TLS 的 MQTT(而不是基于 TLS 的 HTTP)时,您可能会争辩说上述内容不适用,但是鉴于 TLS 库的主要用途是用于 HTTP 流量,因此它通过以下方式向 RFC 确认是有道理的默认。

您有几个选择,包括:

  • 创建证书/连接时使用主机名(例如localhost)而不是 IP。
  • 将 IP 添加为 subjectAltName
  • 修改库以使用 noop checkServerIdentity(请参阅此答案)。
  • 使用另一个应用程序进行测试(不推荐,因为某些应用程序可以工作,而另一些则不能)。上面引用的问题提到 MQTT.fx 有效。
于 2022-03-01T20:20:31.103 回答