Networking|在MQTT中使用SSL/TLS提高安全性

翻译自:http://rockingdlabs.dunmire.org/exercises-experiments/ssl-client-certs-to-secure-mqtt
在MQTT中使用SSL/TLS提高安全性 当我开始使用MQTT时, 发现比较容易找到使用SSL/TLS验证去加密与代理之间的数据的相关资料。OwnTracks项目甚至提供了一个设置CA及签名的一个脚本, 不过证书是给代理服务器而不是客户端用的。
在按照其说明去使用SSL验证MQTT客户端身份时我遇到了一些问题, 这皮按文章主要是想弥补一下原有文档的一些不足。
术语说明:TLS(传输层安全)是SSL的新名称(安全套接层)。StackExchange对于SSL, TLS, and HTTPS三者的区别提供了更详尽的解析
准备

  • 使用openssl来生成证书(我在Ubuntu 14.04 LTS上进行开发并亲测了这个过程).
  • 将使用开源代理mosquitto来演示这个过程。 通过apt-get来安装:
$ sudo apt-get install mosquitto
步骤
提示: 该过程在同一个系统中进行
1. 创建一个受保护的workspace
警告: 对证书的密钥并没有使用密码保护。也许这不是最好的做法,但它确实使它更容易在守护进程和嵌入式设备中使用。你隐藏好它们这很重要。
在当前示例中,我们将创建并使用其他用户没有权限访问的目录。
$ mkdir myCA
$ chmod 700 myCA
$ cd myCA
2. 创建CA并生成server端证书
从OweTracks项目下载并运行generate-CA.sh脚本。该脚本创建CA文件,生成服务器证书,并使用CA来签名证书。
注:在生产环境中使用此实例之前,你应该定制thegenerate-CA.sh脚本,而这些这超出了本章节要讲解的范围。
$ wget https://github.com/owntracks/tools/raw/master/TLS/generate-CA.sh .
$ bash ./generate-CA.sh
generate-CA.sh会产生6个文件:ca.crt,ca.key,ca.srl,myhost.crt,myhost.csr和myhost.key。分别为: 证书(.CRT),钥匙(.KEY),请求(.csr文件),并在签名过程中的一系列记录文件(.slr)。注意myhost文件在您的系统上或许是不同的名字。
其中有三个文件会拷贝到/etc/mosquitto目录:
$ sudo cp ca.crt /etc/mosquitto/ca_certificates/
$ sudo cp myhost.crt myhost.key /etc/mosquitto/certs/

配置文件/etc/mosquitto/mosquitto.conf大概是这个样子:
# mosquitto.conf pid_file /var/run/mosquitto.pid persistence true persistence_location /var/lib/mosquitto/ log_dest file /var/log/mosquitto/mosquitto.log cafile /etc/mosquitto/ca_certificates/ca.crt certfile /etc/mosquitto/certs/myhost.crt keyfile /etc/mosquitto/certs/myhost.key

在拷贝证书文件和修改mosiquitto.conf后, 重启服务:
$ sudo service mosquitto restart
3. 检验
您可以通过使用客户端mosquitto_sub来进行验证:
$ mosquitto_sub -t \$SYS/broker/bytes/\# -v --cafile ca.crt
$SYS/broker/bytes/received 65
$SYS/broker/bytes/sent 67
$SYS/broker/bytes/received 130
$SYS/broker/bytes/sent 196

这些topic每10秒更新一次。如果需要调试,你可以这样mosquitto_sub -d或者看/var/logs/mosquitto/mosquitto.log日志记录。
4. 生成证书
在这一点上,你可以尝试我做过的步骤,并使用generate-CA.sh生成另一个证书,但还是别这样做!它不会生效,因为它创建证书nsCertType设置为服务器有效,因此在客户端上使用无效。用脚本试了一下,同时阅读手册页的OpenSSL后,我发现以下三个命令将创建我所需要的证书:
$ openssl genrsa -out client.key 2048
$ openssl req -new -out client.csr
-key client.key -subj "/CN=client/O=example.com"

$ openssl x509 -req -in client.csr -CA ca.crt
-CAkey ca.key -CAserial ./ca.srl -out client.crt
-days 3650 -addtrust clientAuth

关键的参数为-addtrust clientAuth, 它使得签名的证书同样适用与客户端。
这很简单,但你可能会希望有一定量的不同客户端的证书。用这样的方式来实现一个客户端一个证书是不靠谱的。所以附加的脚本是generate-CA.sh的一个补充。可以这样使用:
$ bash ./generate-client.sh client2
5. 重新配置
更改mosquitto配置, 在/etc/mosquitto/mosquitto.conf文件末尾加上这几行,用来要求客户端添加安全认证:
# mosquitto.conf pid_file /var/run/mosquitto.pid persistence true persistence_location /var/lib/mosquitto/ log_dest file /var/log/mosquitto/mosquitto.log cafile /etc/mosquitto/ca_certificates/ca.crt certfile /etc/mosquitto/certs/SVE14A1HFXB.crt keyfile /etc/mosquitto/certs/SVE14A1HFXB.key require_certificate true

然后重启服务:
$ sudo service mosquitto restart
6. 测试
这时这样使用mosquitto_sub命令会失败:
$ mosquitto_sub -t \$SYS/broker/bytes/\# -v --cafile ca.crt
//Error: Protocol error Error: A TLS error occurred.

指定参数–cert和–key来满足服务器要求:
$ mosquitto_sub -t \$SYS/broker/bytes/\# -v --cafile ca.crt --cert client.crt --key client.key
$SYS/broker/bytes/received 65
$SYS/broker/bytes/sent 67
$SYS/broker/bytes/received 130
$SYS/broker/bytes/sent 136

第二个client也这样做:
$ mosquitto_sub -t \$SYS/broker/bytes/\# -v --cafile ca.crt --cert client2.crt --key client2.key
$SYS/broker/bytes/received 130
$SYS/broker/bytes/sent 198
$SYS/broker/bytes/received 195
$SYS/broker/bytes/sent 269

总结
使用客户端证书,在另一层次也给您的MQTT系统提供安全保护。现在除了有一个加密的通信通道,服务器也将只接受正确签名证书的连接。
在MQTT系统上的安全工作还有很多, 而加密通信信息是一个好的开始。
Follow-up
【Networking|在MQTT中使用SSL/TLS提高安全性】需要联系我的话, 可以在我的google+文章下留言。

    推荐阅读