说在前面html
数据在网络上传输,若是是明文传输,确定是不安全的,因此得将数据进行加密。如今主流的加密方式,就是利用SSL/TLS协议加密,其实SSL和TLS能够看作是一个协议,它运行在传输层和应用层之间的一层协议,经过将TCP/UDP传输的数据加密以后,再传送到另外一端。这样数据就安全了。node
如今的https传输,底层就是利用了SSL/TLS协议进行了加密。固然,Mail,FTP等其余基于TCP/UDP传输协议之上构建的应用程序,也都是可使用这种加密协议的。那么MQTT在数据传输中,是否也能够进行传输加密呢?答案是确定的,由于MQTT也是基于TCP协议之上实现的,因此想要实现起来,并不难。git
在开始进行MQTT数据传输加密的实操以前,咱们先来储备点SSL/TLS协议的知识,以便于更好的进行理解。github
说道SSL/TLS协议,其诞生能够追溯到前浏览器霸主NetScape,为了解决数据传输安全问题而发明了SSL协议,先是产生了SSL1.0,而后产生了SSL2.0,以后是SSL3.0,因为协议成熟且使用量大,后来被IETF对SSL3.0进行了标准化并添加了少许其余机制,改名成了TLS1.0。更多的细节,能够百度“RFC2246-TLS加密协议详解”,也能够去www.rfc-editor.org网站,经过搜索RFC2246来了解更多细节。算法
OPENSSL,是对SSL/TLS协议进行实现的开源软件,其中包含了加解密所用到的各类算法,算是密码学这块的集大成者。浏览器
今天咱们要用它来经过特定的流程来生产出咱们须要的加密机制,从而使得MQTT的传输更安全。安全
握手流程服务器
首先来讲明一下SSL/TLS协议的经典握手流程,只有经过此流程,后续的数据传输才能正常的进行加密并传输。总体流程以下:网络
因为上图描述都是英文,理解起来比较困难,我就拿阮一峰的描述来进行,Vistor咱们称为Alice,CloudFlare咱们称为Bob,描述以下:session
第一步,爱丽丝给出协议版本号、一个客户端生成的随机数(Client random),以及客户端支持的加密方法。
第二步,鲍勃确认双方使用的加密方法,并给出数字证书、以及一个服务器生成的随机数(Server random)。
第三步,爱丽丝确认数字证书有效,而后生成一个新的随机数(Premaster secret),并使用数字证书中的公钥,加密这个随机数,发给鲍勃。
第四步,鲍勃使用本身的私钥,获取爱丽丝发来的随机数(即Premaster secret)。
第五步,爱丽丝和鲍勃根据约定的加密方法,使用前面的三个随机数,生成"对话密钥"(session key),用来加密接下来的整个对话过程。
能够看到总体流程比较复杂,并且涉及到了加密方法,数字证书,公钥,私钥等名词,我大概作一下解释。
加密方法:数据传输加密,能够用多种方法,图例中选用的是RSA,即非对称加密算法。
公钥:公开的密匙文件,任何用户均可以自由访问,一般以.pem结尾
私钥:非公开的密匙文件,一般由加密方本身保管,必须得保证其私密性,一般以.key结尾
数字证书:包含数字签名和公钥的证书,客户端能够经过CA来验证数字签名,一般以.cer, .crt结尾
大体知道这些名词的意思后,接下来咱们经过更加具体的流程讲解,来逐渐清晰化。
受权流程
CA中心的受权流程
因为CA证书要进行证书受权,因此必须先建立一个本身的私钥,而后经过此私钥生成本身的自签证书。因为这里咱们没法真正的CA中心来模拟,由于是收费的,好在openssl为咱们提供了自建CA中心的选项,使得可使用以下的命令来模拟。
1.建立私钥,执行命令:
openssl genrsa -out D:/sslkey/ca/MyRootCA.key 2048
能够看到在文件夹中生成了私钥
2.生成自签证书,执行命令:
openssl req -x509 -new -nodes -key D:/sslkey/ca/MyRootCA.key -sha256 -days 3650 -subj "/CN=www.scy.com" -out D:/sslkey/ca/MyRootCA.pem
填写好相关信息后,最终在文件夹中生成了自签证书。须要说明的是,因为是模拟的CA中心,因此这里稍显繁琐,若是使用的是外部CA中心,则无需关心这些问题。同时,若是用户想自定义本身的信息,请把-subj配置去掉便可,后面的请求也相似。
CA证书总体的准备工做到此。
Server端的受权流程
Server端的受权流程也比较简单,首先是建立server端使用的私钥,而后经过此私钥建立证书请求,请求会被推送到CA中心进行处理,处理完毕后,会将证书颁发给Server端。
1.建立私钥,执行命令:
openssl genrsa -out D:/sslkey/server/MyEMQ1.key 2048
2.建立证书请求,执行命令:
openssl req -new -key D:/sslkey/server/MyEMQ1.key -out D:/sslkey/server/MyEMQ1.csr -subj "/CN=127.0.0.1"
3.CA中心颁发证书,执行命令:
openssl x509 -req -in D:/sslkey/server/MyEMQ1.csr -CA D:/sslkey/ca/MyRootCA.pem -CAkey D:/sslkey/ca/MyRootCA.key -CAcreateserial -out D:/sslkey/server/MyEMQ1.pem -days 3650 -sha256
执行这三步完毕以后,总体流程完毕,咱们接下来将这些文件配置到EMQ的配置文件中来启动SSL。
打开etc目录中的emqx.conf文件,修改选项为如下三个配置(须要提早将受权文件拷贝到certs目录):
#ssl port:
listener.ssl.external = 8883
#private key for emq cert:
listener.ssl.external.keyfile = etc/certs/MyEMQ1.key
#emq cert:
listener.ssl.external.certfile = etc/certs/MyEMQ1.pem
#CA cert:
listener.ssl.external.cacertfile = etc/certs/MyRootCA.pem
之后,重启EMQX服务器便可。
这样,此根证书生成完毕,而后就能为后续进来的请求进行受权操做。
接下来打开MQTTX客户端程序,创建SSL连接来试试是否能够正常操做:
配置好以后,点击链接按钮,进行链接,能够看到已经链接到服务器且在在ssl端口8883进行监听了。
而后尝试向/test/say管道发送消息,能够看到订阅者已经能接收到了:
发布者界面以下:
订阅者界面以下:
双向认证流程
上面配置好Server端的受权流程后,咱们成功的使用客户端经过SSL链接上了服务端并进行了消息操控。可是上面只是单向认证流程,由于Client端并未作认证操做。这里咱们未来说下怎么进行双向认证流程。
Server端的受权流程,我就不用说了,上面有讲解到。按照流程操做便可。
Client端的受权流程,其实和Server端的受权流程如出一辙,咱们来依葫芦画瓢一下,进入C:\Program Files\OpenSSL-Win64\bin目录,执行下面的命令。
1.建立私钥,执行命令:
openssl genrsa -out D:/sslkey/client/MyClient1.key 2048
2.建立证书请求,执行命令:
openssl req -new -key D:/sslkey/client/MyClient1.key -out D:/sslkey/client/MyClient1.csr -subj "/CN=127.0.0.1"
3.CA中心颁发证书,执行命令:
openssl x509 -req -in D:/sslkey/client/MyClient1.csr -CA D:/sslkey/ca/MyRootCA.pem -CAkey D:/sslkey/ca/MyRootCA.key -CAcreateserial -out D:/sslkey/client/MyClient1.pem -days 3650 -sha256
所有执行完毕,则Client端的受权流程完毕,结果以下:
文件生成以下:
以后,咱们须要配置一下,以便于启动EMQ的客户端SSL认证,一样的打开etc目录中的emqx.conf文件,修改以下配置:
#enable the client side certificates
listener.ssl.external.verify = verify_peer
#set it to 'true' to allow the ssl with client side certificate only
listener.ssl.external.fail_if_no_peer_cert = true
而后从新启动EMQX便可。
上图为配置方式,配置完毕以后,点击链接按钮,就能够链接到Server了。以后模拟信息收发:
题外话
单向认证和双向认证,少了一个认证步骤,通常在物联网Client设备较多的状况下,使用单向认证则能够得到更好的性能。若是数据很是重要且不会有性能问题的时候,使用双向设备则更合适。
考虑到CA颁发的证书都有时效性,物联网设备特别多的状况下,这种状况显得尤其明显,因此针对本身的设备规模,选择合适的认证,也是很是重要的。
本节就到这里,但愿能抛砖引玉。
参考资料: