SSL是一種加密協議,可通過計算機網絡提供通信安全性。 不出所料,它也可以用於MQTT消息交換。
SSL具有許多安全優勢,例如:
強認證性:創建一個SSL連接時,通信方可以檢查其夥伴的身份並確定其是否可信任。 通常,在此階段,可以使用X.509證書來確保證書持有者的身份。
隱私性:協議啓動時,通信雙方會生成唯一的會話密鑰。 該會話密鑰對通信過程進行了加密。 任何未授權用戶都無法查看交換的信息。
完整性:不可能篡改SSL上的通信。
EMQ和EMQX支持SSL。 在本文中,將展示如何在EMQ上啓用SSL。
SSL協議
SSL協議是SSL記錄協議和SSL握手協議的組合。記錄協議與任何其他數據攜帶協議非常相似,一條記錄消息包括內容類型,版本,長度和消息有效負載,其中包含加密數據。 有時,一條記錄消息還具有消息身份驗證代碼和/或填充。SSL連接啓動時使用握手協議,它控制通信方式。 握手本身也承載在SSL記錄(內容類型22)中。
一個典型的SSL握手協議:
握手的目的是創建通信通道,識別彼此的身份並協商密碼規範。 握手以“ hello”消息開始,以“ finished”消息結束。
準備工作:在EMQ中使用SSL
通常,我們使用證書進行SSL通信。 因此在啓動SSL之前,我們將需要一些證書。 它們是:CA證書,EMQ證書。如果我們要啓用雙向身份驗證,我們還將需要客戶端證書。通常在demo或實驗室環境中,我們會親自生成證書並簽名,而不是從受信任的第三方獲得證書。接下來,我們將使用OpenSSL附帶的工具來生成所需的證書。
首先,我們需要一個用於自簽名CA根證書的密鑰key,以下命令會生成密鑰長度爲2048的RSA私鑰並將其保存在文件“ MyRootCA.key”中:
openssl genrsa -out MyRootCA.key 2048
下一步是使用我們剛得到的密鑰生成根證書:
openssl req -x509 -new -nodes -key MyRootCA.key -sha256 -days 3650 -out MyRootCA.pem
根證書是信任鏈的起點,我們假定:如果從證書頒發者到鏈上根證書的所有節點都是可信的,則該鏈上的證書是可信的。擁有自簽名的CA根證書後,我們可以使用它爲其他身份(例如EMQ服務器)頒發證書。 同樣,我們首先需要一個私鑰:
openssl genrsa -out MyEMQ1.key 2048
然後生成針對EMQ1的證書請求:
openssl req -new -key ./MyEMQ1.key -out MyEMQ1.csr
然後,使用CA根證書頒發EMQ1的證書:
openssl x509 -req -in ./MyEMQ1.csr -CA MyRootCA.pem -CAkey MyRootCA.key -CAcreateserial -out MyEMQ1.pem -days 3650 -sha256
現在我們可以開始在EMQ上使用SSL。
在EMQ上啓用SSL
在EMQ上啓用SSL非常簡單,我們只需要修改“ emq.conf/emqx.conf中的一些配置。 默認的偵聽端口是8883
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
修改conf後,重新啓動EMQ,並使用mosquitto_sub對其進行測試:
mosquitto_sub -t abc -h emq1 -p 8883 -d --cafile ~/test_certs/MyRootCA.pem --insecure
Client mosqsub|10617-Zhengyus- sending CONNECT
Client mosqsub|10617-Zhengyus- received CONNACK
Client mosqsub|10617-Zhengyus- sending SUBSCRIBE (Mid: 1, Topic: abc, QoS: 0)
Client mosqsub|10617-Zhengyus- received SUBACK
Subscribed (mid: 1): 0
啓用客戶端證書
在某些情況下,有必要通過檢查客戶端證書來確保客戶端身份(雙向認證)。 通過啓用以下指令可以輕鬆完成此操作(修改emq.conf):
#enable the client side certificates
listener.ssl.external.verify = verify_peer
強制使用客戶端證書(僅允許具有客戶端證書的ssl)
#set it to 'true' to allow the ssl with client side certificate only
listener.ssl.external.fail_if_no_peer_cert = true
做了上述更改後,我們繼續使用相同的命令進行測試後,得到了一個tls錯誤
mosquitto_sub -t abc -h emq1 -p 8883 -d --cafile ~/test_certs/MyRootCA.pem --insecure
Client mosqsub|10738-Zhengyus- sending CONNECT
Error: A TLS error occurred.
雙向認證我們將需要客戶端證書,通過用生成服務器端證書的相同方式生成客戶端證書:
openssl genrsa -out MyClient1.key 2048
openssl req -new -key ./MyClient1.key -out MyClient1.csr
openssl x509 -req -in ./MyClient1.csr -CA MyRootCA.pem -CAkey MyRootCA.key -CAcreateserial -out MyClient1.pem -days 3650 -sha256
生成證書後我們可以通過以下命令驗證證書的有效性
openssl verify -CAfile MyRootCA.pem MyEMQ1.pem MyClient1.pem
MyEMQ1.pem: OK
MyClient1.pem: OK
我們用新生成的客戶端證書進行測試:
mosquitto_sub -t abc -h emq1 -p 8883 -d --key ~/test_certs/MyClient1.key --cert ~/test_certs/MyClient1.pem --cafile ~/test_certs/MyRootCA.pem --insecure
Client mosqsub|10796-Zhengyus- sending CONNECT
Client mosqsub|10796-Zhengyus- received CONNACK
Client mosqsub|10796-Zhengyus- sending SUBSCRIBE (Mid: 1, Topic: abc, QoS: 0)
Client mosqsub|10796-Zhengyus- received SUBACK
Subscribed (mid: 1): 0
一切都按預期運行