mosquitto-tls — Configure SSL/TLS support for Mosquitto

配置说明
mosquitto 为加密的网络连接和身份验证提供 SSL 支持。本手册描述了如何创建所需的文件。

注意事项
为您的 CA、服务器和客户端使用不同的证书参数很重要。如果证书看起来相同,即使是单独生成的,代理/客户端也无法区分它们,您将遇到难以诊断的错误。

生成证书
以下部分提供了可用于生成证书的 openssl 命令,但没有任何上下文。 https://asciinema.org/a/201826 上的 asciicast 完整介绍了如何使用这些命令。英文操作视频。基于linux bash 操作的。

证书颁发机构
生成证书颁发机构证书和密钥。

openssl req -new -x509 -days <duration> -extensions v3_ca -keyout ca.key -out ca.crt

服务器端
生成服务器密钥(采用des3加密保护)。

openssl genrsa -des3 -out server.key 2048

生成无密码保护的服务器密钥。

openssl genrsa -out server.key 2048

生成要发送给 CA 的证书签名请求。

openssl req -out server.csr -key server.key -new

注意事项:
当提示输入 CN(通用名称)时,请输入您的服务器(或代理)主机名或域名。

将 CSR 发送给 CA,或使用您的 CA 密钥对其进行签名:

openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days <duration>

用户端
生成客户端密钥。

openssl genrsa -des3 -out client.key 2048

生成要发送给 CA 的证书签名请求。

openssl req -out client.csr -key client.key -new

将 CSR 发送给 CA,或使用您的 CA 密钥对其进行签名:

openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client.crt -days <duration>

如果初始请求通过HTTPS是安全的,但加载了HTTPS 和 HTTP内容以显示网页,则混合内容会发生。 HTTPS内容是安全的。 HTTP内容不安全。

如果安全内容与不安全内容混合在一起,现代浏览器可能会阻止页面显示或显示警告消息。

在chrome中就会提示如标题所示的错误消息:
This request has been blocked; the content must be served over HTTPS.

所以,问题就变成了,如何在chrome浏览器中启用混合内容。

单击锁(警告)图标,然后单击​站点设置。

站点设置>>不安全的内容

滚动到​Insecure content(不安全内容),然后使用下拉列表将“Block(default)”更改为“Allow(允许)”。
chorme-insecure-content-settings.png

重新刷新网页就可以了。

firefox浏览器的话,参考这个链接:在浏览器中启用混合内容

安装软件

sudo apt install mosquitto

生成CA密钥

openssl genrsa -des3 -out ca.key 2048

签发CA证书/根证书

openssl req -new -x509 -days 3650 -key ca.key -out ca.crt

生成服务端密钥

openssl genrsa -out server.key 2048

生成证书签名请求

openssl req -new -out server.csr -key server.key

让CA签发证书

openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 360

修改mosquitto.conf内容
listener 8883
cafile /etc/mosquitto/ca_certificates/ca.crt
certfile /etc/mosquitto/certs/server.crt
keyfile /etc/mosquitto/certs/server.key
tls_version tlsv1.2

mqtt broker运行测试

mosquitto -c etc/mosquitto.conf 

1626408211: mosquitto version 2.0.11 starting
1626408211: Config loaded from etc/mosquitto.conf.
1626408211: Opening ipv4 listen socket on port 8883.

发布消息

mosquitto_pub -d -h localhost -t "topic/test" -m "hello world" --cafile /etc/mosquitto/ca_certificates/ca.crt -p 8883

订阅消息

mosquitto_sub -d -h localhost -t "topic/test" --cafile /etc/mosquitto/ca_certificates/ca.crt -p 8883

双向认证测试(需要根证书,客户证书,服务器证书以及各自的私钥)

可以使用test.mosquitto.org服务器来测试

测试命令:

openssl s_client -connect test.mosquitto.org:8884 -key test/mosquitto-client.key -cert test/mosquitto-client.crt -CAfile mosquitto.org.crt -showcerts

其中mosquitto-client.key 自己生成,mosquitto-client.crt在mosquitto的网站上签发. 可以参考这篇文章https://const.net.cn/151.html

运行结果:
Acceptable client certificate CA names
C = GB, ST = United Kingdom, L = Derby, O = Mosquitto, OU = CA, CN = mosquitto.org, emailAddress = roger@atchoo.org
Requested Signature Algorithms: ECDSA+SHA256:ECDSA+SHA384:ECDSA+SHA512:Ed25519:Ed448:RSA-PSS+SHA256:RSA-PSS+SHA384:RSA-PSS+SHA512:RSA-PSS+SHA256:RSA-PSS+SHA384:RSA-PSS+SHA512:RSA+SHA256:RSA+SHA384:RSA+SHA512:ECDSA+SHA224:RSA+SHA224
Shared Requested Signature Algorithms: ECDSA+SHA256:ECDSA+SHA384:ECDSA+SHA512:Ed25519:Ed448:RSA-PSS+SHA256:RSA-PSS+SHA384:RSA-PSS+SHA512:RSA-PSS+SHA256:RSA-PSS+SHA384:RSA-PSS+SHA512:RSA+SHA256:RSA+SHA384:RSA+SHA512
Peer signing digest: SHA256
Peer signature type: RSA-PSS
Server Temp Key: X25519, 253 bits
...
SSL handshake has read 2741 bytes and written 2690 bytes
Verification: OK
...
New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384
Server public key is 2048 bit
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
Early data was not sent
Verify return code: 0 (ok)
SSL-Session:
Protocol : TLSv1.3
Cipher : TLS_AES_256_GCM_SHA384
Session-ID: 904A1381D17A1C4432A0DE5EE0D7564C1E4AD4A3E46B7EE173E61B1034A95EB1
Session-ID-ctx:
Resumption PSK: AC27C990D68B5EE27235A5A659EA25CD2D4DE28D233175DFD7ECD09A6FFB4BE418B8C4F1FB87DDF6E666E82EC2A0BC0A
PSK identity: None
PSK identity hint: None
SRP username: None
TLS session ticket lifetime hint: 7200 (seconds)
TLS session ticket:
0000 - eb 13 3c cb 1b 08 5a 65-79 37 75 92 30 fd 47 46 ..<...Zey7u.0.GF
0010 - e8 09 6a 31 83 91 16 f8-29 9c a8 cc d3 e6 00 ad ..j1....).......

Start Time: 1626417683
Timeout : 7200 (sec)
Verify return code: 0 (ok)
Extended master secret: no
Max Early Data: 0
使用自签名证书,自己搭建服务器的话

openssl s_server -accept 8888 -key server.key -cert server.crt -CAfile ca.crt -Verify 1

verify depth is 1, must return a certificate
Using default temp DH parameters

openssl s_client -connect localhost:8883 -key client.key -cert client.crt -CAfile ca.crt

...
Start Time: 1626418308
Timeout : 7200 (sec)
Verify return code: 0 (ok)
Extended master secret: no
Max Early Data: 0
...

mosquitto 使用-q来设置qos参数

-q : quality of service level to use for the subscription. Defaults to 0.
--will-qos : QoS level for the client Will.

注意事项:
If a message is published with QoS 2 and the client is subscribed to a topic with QoS 0, then the message will be delivered to that client with QoS 0;

if a subscriber is registered with QoS 2 and the message is published with QoS 0, the message will be delivered with QoS 0.

MQTT设计了一套保证消息稳定传输的机制,包括消息应答、存储和重传。在这套机制下,提供了三种不同层次QoS(Quality of Service):

QoS0,At most once,至多一次;
QoS1,At least once,至少一次;
QoS2,Exactly once,确保只有一次。
QoS 是消息的发送方(Sender)和接受方(Receiver)之间达成的一个协议:

QoS0 代表,Sender 发送的一条消息,Receiver 最多能收到一次,也就是说 Sender 尽力向 Receiver 发送消息,如果发送失败,也就算了;
QoS1 代表,Sender 发送的一条消息,Receiver 至少能收到一次,也就是说 Sender 向 Receiver 发送消息,如果发送失败,会继续重试,直到 Receiver 收到消息为止,但是因为重传的原因,Receiver 有可能会收到重复的消息;
QoS2 代表,Sender 发送的一条消息,Receiver 确保能收到而且只收到一次,也就是说 Sender 尽力向 Receiver 发送消息,如果发送失败,会继续重试,直到 Receiver 收到消息为止,同时保证 Receiver 不会因为消息重传而收到重复的消息。
注意:
QoS是Sender和Receiver之间的协议,而不是Publisher和Subscriber之间的协议。换句话说,Publisher发布了一条QoS1的消息,只能保证Broker能至少收到一次这个消息;而对于Subscriber能否至少收到一次这个消息,还要取决于Subscriber在Subscibe的时候和Broker协商的QoS等级。

MQTT QoS 等级的选择
QoS 级别越高,流程越复杂,系统资源消耗越大。应用程序可以根据自己的网络场景和业务需求,选择合适的 QoS 级别。

以下情况下可以选择 QoS 0
可以接受消息偶尔丢失。
在同一个子网内部的服务间的消息交互,或其他客户端与服务端网络非常稳定的场景。
以下情况下可以选择 QoS 1
对系统资源消耗较为关注,希望性能最优化。
消息不能丢失,但能接受并处理重复的消息。
以下情况下可以选择 QoS 2
不能忍受消息丢失(消息的丢失会造成生命或财产的损失),且不希望收到重复的消息。
数据完整性与及时性要求较高的银行、消防、航空等行业。