MQTT TLS 连接
MQTT TLS connection
我想将测试 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}]`);
});
我可以毫无问题地使用 const server = require('net').createServer(aedes.handle)
连接到 PORT=1881
,我也可以使用 const server = require('tls').createServer(options, aedes.handle)
连接到 PORT=8881
使用工具 xca-2.4.0.msi
XCA 2.4.0 我创建了一个 ca.pem 证书文件和一个证书 server_cert.pem 和一个 server_key.pem 私钥(由 ca.pem) 作为服务器。 CA 和服务器的密钥不同:
对于我的 MQTT 客户端,我在 ADVANCED, CERTIFICATES, SERVER CERTIFICAT (CA)
下 select 编辑了 ca.pem 文件。如果我 select “加密”,它就可以工作。但是,如果 select“验证证书”,错误:Hostname/IP 与证书的别名不匹配:IP:127.0.0.1 不在证书列表中
不幸的是我不知道我做错了什么,提前致谢:(
MQTT Explorer is built using Node.js and the MQTT library MQTT.js. As per this issue:
Node.js requires the IP address to be in the subjectAltNames for the cert and not in the CN. Maybe MQTT.fx isn't requiring that, but it should.
和:
If your server's certificate says CN=localhost in the Subject field, connect using localhost and not 127.0.0.1 and it should work. If it says CN=127.0.0.1, you have to make a new one because Node.js won't validate the IP address unless it's in the SAN extension. There is a way to work around it in code (I think it's an option called checkServerIdentity), but I would prefer to fix my certificate if I had this problem.
在 this answer 中阐述了在 Node 中采用的方法的基本原理,其中包括来自 RFC2818 的以下引用:HTTP Over TLS
:
In some cases, the URI is specified as an IP address rather than a hostname. In this case, the iPAddress subjectAltName must be present in the certificate and must exactly match the IP in the URI.
当您使用基于 TLS 的 MQTT(而不是基于 TLS 的 HTTP)时,您可能会争辩说上述内容不适用,但是,考虑到 TLS 库的主要用途是用于 HTTP 流量,它是有道理的默认确认 RFC。
您有几个选项,包括:
- 在创建 certificate/connecting.
时使用主机名(例如 localhost
)而不是 IP
- 将 IP 添加为 subjectAltName
- 修改库以使用 noop
checkServerIdentity
(参见 this answer)。
- 使用另一个应用程序进行测试(不推荐,因为有些应用程序可以工作,有些则不能)。上面引用的问题提到 MQTT.fx 有效。
我想将测试 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}]`);
});
我可以毫无问题地使用 const server = require('net').createServer(aedes.handle)
连接到 PORT=1881
,我也可以使用 const server = require('tls').createServer(options, aedes.handle)
PORT=8881
使用工具 xca-2.4.0.msi
XCA 2.4.0 我创建了一个 ca.pem 证书文件和一个证书 server_cert.pem 和一个 server_key.pem 私钥(由 ca.pem) 作为服务器。 CA 和服务器的密钥不同:
对于我的 MQTT 客户端,我在 ADVANCED, CERTIFICATES, SERVER CERTIFICAT (CA)
下 select 编辑了 ca.pem 文件。如果我 select “加密”,它就可以工作。但是,如果 select“验证证书”,错误:Hostname/IP 与证书的别名不匹配:IP:127.0.0.1 不在证书列表中
不幸的是我不知道我做错了什么,提前致谢:(
MQTT Explorer is built using Node.js and the MQTT library MQTT.js. As per this issue:
Node.js requires the IP address to be in the subjectAltNames for the cert and not in the CN. Maybe MQTT.fx isn't requiring that, but it should.
和:
If your server's certificate says CN=localhost in the Subject field, connect using localhost and not 127.0.0.1 and it should work. If it says CN=127.0.0.1, you have to make a new one because Node.js won't validate the IP address unless it's in the SAN extension. There is a way to work around it in code (I think it's an option called checkServerIdentity), but I would prefer to fix my certificate if I had this problem.
在 this answer 中阐述了在 Node 中采用的方法的基本原理,其中包括来自 RFC2818 的以下引用:HTTP Over TLS :
In some cases, the URI is specified as an IP address rather than a hostname. In this case, the iPAddress subjectAltName must be present in the certificate and must exactly match the IP in the URI.
当您使用基于 TLS 的 MQTT(而不是基于 TLS 的 HTTP)时,您可能会争辩说上述内容不适用,但是,考虑到 TLS 库的主要用途是用于 HTTP 流量,它是有道理的默认确认 RFC。
您有几个选项,包括:
- 在创建 certificate/connecting. 时使用主机名(例如
- 将 IP 添加为 subjectAltName
- 修改库以使用 noop
checkServerIdentity
(参见 this answer)。 - 使用另一个应用程序进行测试(不推荐,因为有些应用程序可以工作,有些则不能)。上面引用的问题提到 MQTT.fx 有效。
localhost
)而不是 IP