3

参考文章

  1. Mosquitto服务器的搭建以及SSL/TLS安全通信配置
  2. Mosquitto SSL Configuration -MQTT TLS Security 读者Abhinav Saxena的评论
  3. OpenSSL - error 18 at 0 depth lookup:self signed certificate

系统版本: CentOS7

mosquitto版本: 1.4.15

openssl版本: 1.0.1e

参考文章1对mosquitto的TLS配置步骤讲解得十分详细, 包含了openssl生成证书及密钥, mosquitto的配置, 及其内置pub/sub客户端对证书及密钥的使用等.

其实关于mosquitto的自签名SSL/TLS配置, 在用yum安装后可以使用man mosquitto-tls查看, 其中也有详细的操作步骤.

按照这样的流程走下来, mosquitto启动正常, 相关配置如下.

cafile /etc/mosquitto/certs/ca.crt
certfile /etc/mosquitto/certs/server.crt
keyfile /etc/mosquitto/certs/server.key
tls_version tlsv1

没什么问题, 但是在执行mosquitto_pub, mosquitto_sub命令时, 得到了Error: A TLS error occurred.错误.

$ mosquitto_pub  -t 'room01/sensors' -m '我的消息' --cafile /etc/mosquitto/certs/ca.crt --cert /etc/mosquitto/certs/client.crt --key /etc/mosquitto/certs/client.key -h 172.32.100.10 --tls-version tlsv1
Error: A TLS error occurred

对应的, mosquitto服务端的日志如下.

1523024283: New connection from 172.32.100.10 on port 1883.
1523024283: OpenSSL Error: error:14094418:SSL routines:SSL3_READ_BYTES:tlsv1 alert unknown ca
1523024283: OpenSSL Error: error:140940E5:SSL routines:SSL3_READ_BYTES:ssl handshake failure
1523024283: Socket error on client <unknown>, disconnecting.
--tls-version tlsv1选项要加的, 因为pub/sub两个客户端使用的tls版本默认为tls1.2, 不加这个选项的话, mosquitto服务会得到SSL routines:SSL3_READ_BYTES:tlsv1 alert protocol version错误.

网上关于这个问题有说是因为mosquitto与两个客户端版本不一致的, 或者mosquitto指定ca.crt与客户端不是同一个的, 也有说是server.csr填写的Common Name与服务器IP不同的...

呵呵, 可笑, 我怎么可能会犯这种低级错误.

我也尝试过为mosquitto_pub加上--insecure选项, 但是这是让mosquitto_pub不去验证服务端证书中Common Name与其地址是否匹配的, 无效.

后来按照参考文章2中Abhinav Saxena的提示, 把--cafile的值改成了server.crt, 竟然成功了...成功了...

$ mosquitto_pub  -t 'room01/sensors' -m '我的消息' --cafile /etc/mosquitto/certs/ca.crt --cert /etc/mosquitto/certs/client.crt --key /etc/mosquitto/certs/client.key -h 172.32.100.10 --tls-version tlsv1

mosquitto_sub的命令如下

$ mosquitto_sub  -t 'room01/sensors' -h 172.32.100.10 --tls-version tlsv1 --cafile /etc/mosquitto/certs/server.crt --cert /etc/mosquitto/certs/client.crt --key /etc/mosquitto/certs/client.key
我的消息

服务端的日志如下

1523175367: New connection from 172.32.100.10 on port 1883.
1523175368: New client connected from 172.32.100.10 as mosqpub|6211-localhost. (c1, k60).
1523175368: Sending CONNACK to mosqpub|6211-localhost. (0, 0)
1523175368: Received PUBLISH from mosqpub|6211-localhost. (d0, q0, r0, m0, 'room01/sensors', ... (12 bytes))
1523175368: Received DISCONNECT from mosqpub|6211-localhost.
1523175368: Client mosqpub|6211-localhost. disconnected.

如果加了--insecure选项, 命令应该是这样的

$ mosquitto_pub  -t 'room01/sensors' -m '我的消息' -h 172.32.100.10 --tls-version tlsv1 --cafile /etc/mosquitto/certs/server.crt --insecure

对应的, moquitto_sub的命令应该写做

$ mosquitto_sub  -t 'room01/sensors' -h 172.32.100.10 --tls-version tlsv1 --cafile /etc/mosquitto/certs/server.crt --insecure
我的消息

我的世界观都崩塌了...

之后的实验里, 认识到上面的TLS只是mosquitto的单向认证, 这种情况下, 是要客户端判断服务端是否可信的, 就是说, 这种认证是为了客户端的安全而不是服务端安全.

mosquitto还有一个require_certificate字段, 表示是否验证客户端传来的证书, 默认为fasle.

...呵呵, 如果没验证客户端证书, 那上面的错误是怎么来的???

不过, 将这个字段设置为true后, 上面两种订阅/发布命令都没用了.

心累.jpg, md一定是mosquitto_pub/sub两个命令有问题!


隐隐觉得还是和证书的Common Name字段有关, 之前的测试中, mosquitto服务与pub/sub客户端是在同一台服务器上. 尝试在另一台服务器运行mosquitto_pub命令, 所以重新为其签发了证书与密钥对, 然后运行成功了.

于是猜测, 是不是CACommon Name不能与被其签发的证书的相同? 因为之前测试时, CA, server与client的Common Name都是172.32.100.10(之前也试过localhost, 127.0.0.1的).

然后重新生成CA证书, Common Name填的是0.0.0.0, server与client的依然是服务器本身的IP172.32.100.10.

事实证明我的猜测是对的.

网上大家人都只说mosquitto与其客户端的证书Common Name要与其所在服务器IP相符, 却没有人说过自签名的CA证书Common Name应该取什么, 总有人踩坑的.

关于这一点, 可以看一下参考文章3的最佳答案, 一票人来感谢这个回答...

When OpenSSL prompts you for the Common Name for each certificate, use different names.

general
22 声望1 粉丝