天天看點

MQTT協定應用TLS

前言

做了很久的實驗,一直沒能成功,最後還是down的大佬的源碼,侵删。

正文

簡介

MQTT協定是物聯網應用中重要的應用層協定,上一次實驗開展了MQTT協定的分析,對MQTT協定的長連接配接機制、釋出/訂閱工作模式互動機制進行了分析。但如果MQTT協定不進行安全實作,黑客可以惡意釋出資訊給伺服器,特别是在工業、交通等物聯網應用場合後果不堪設想。本實驗旨建構MQTT協定安全通信。

要求

(1)掌握MQTT的安全通信的基本原理。

(2)設計MQTT安全通信的安全措施。

(3)實作基于TLS的MQTT通信。

基本步驟

(1)應用層:MQTT協定提供了客戶辨別以及使用者名密碼,以便驗證裝置。基于ACL對主題的訂閱和釋出權限設定基本的授權。

(2)傳輸層:傳輸層可使用TLS加密、驗證證書機制,防止中間人攻擊。

(3)網絡層:可以通過專線或者使用VPN來連接配接裝置與MQTT代理,以提高網絡傳輸的安全性。可以通過防火牆保護MQTT代理端,比如限制端口、限制協定、限制IP段。

注意建構一個區域網路,模拟MQTT服務端(代理端)、用戶端(分訂閱和釋出),運用Wireshark抓包分析安全通信過程。

MQTT協定應用TLS

具體過程

伺服器

var mosca = require('mosca')
var SECURE_KEY = __dirname + '/tls-key.pem';
var SECURE_CERT = __dirname + '/tls-cert.pem';
var settings = {
  logger: {
    name: "secureExample",
    level: 40,
  },
  secure : { 
    port: 9090,
    keyPath: SECURE_KEY,
    certPath: SECURE_CERT,
  }
};
var server = new mosca.Server(settings);
server.on('published', function(packet, client) {
    //當用戶端有連接配接釋出主題消息
    var topic = packet.topic;
    console.log(packet);
    switch (topic) {
        case 'test':
            console.log('收到消息:', packet.payload.toString());
            //MQTT轉發主題消息
            //MqttServer.publish({ topic: 'other', payload: 'sssss' });
            break;
        case 'other':
            console.log('message-123', packet.payload.toString());
            break;
    }
});
server.on('ready', setup);
//若使用者名與密碼有效,接受連結
var authenticate = function(client, username, password, callback) {
  var authorized = (username === 'alice' && password.toString() === 'secret');
  if (authorized) {
      client.user = username;
      console.log('通過認證登入的使用者:', username);
  }
  callback(null, authorized);
}

// 授權為alice的用戶端可以釋出/users/alice,
// 從主題中取得使用者名,并校驗與授權使用者一緻
var authorizePublish = function(client, topic, payload, callback) {
  callback(null, client.user == topic);
}

// 授權為alice的用戶端可以訂閱/users/alice,
// 從主題中取得使用者名,并校驗與授權使用者一緻
var authorizeSubscribe = function(client, topic, callback) {
  callback(null, client.user == topic);
}
//mosca配置
function setup() {
  console.log('Mosca secure server is up and running')
  server.authenticate = authenticate;
  server.authorizePublish = authorizePublish;
  server.authorizeSubscribe = authorizeSubscribe;
}
           
MQTT協定應用TLS

訂閱方**

var mqtt = require('mqtt');
var fs = require('fs')
var path = require('path')
var KEY = fs.readFileSync(path.join(__dirname, '/tls-key.pem'))
var CERT = fs.readFileSync(path.join(__dirname, '/tls-cert.pem'))
var TRUSTED_CA_LIST = fs.readFileSync(path.join(__dirname, '/crt.ca.cg.pem'))
var PORT = 9090
var HOST = "127.0.0.1"
var options = {
  port: PORT,
  host: HOST,
  key: KEY,
  cert: CERT,
  rejectUnauthorized: false,
  ca: TRUSTED_CA_LIST,
  protocol: 'mqtts',
  //訂閱者實作認證的參數
  username:"alice",
  password:"secret"
}
var client2 = mqtt.connect(options)
client2.subscribe('alice',{qos:0});//訂閱主題為alice的消息  
client2.on('message',function(top,message) {  
    console.log('收到消息:', message.toString());  
}); 
           
MQTT協定應用TLS

釋出方**

var mqtt = require('mqtt');
var fs = require('fs')
var path = require('path')
var KEY = fs.readFileSync(path.join(__dirname, '/tls-key.pem'))
var CERT = fs.readFileSync(path.join(__dirname, '/tls-cert.pem'))
var TRUSTED_CA_LIST = fs.readFileSync(path.join(__dirname, '/crt.ca.cg.pem'))
var PORT = 9090
var HOST = "127.0.0.1"
var options = {
  port: PORT,
  host: HOST,
  key: KEY,
  cert: CERT,
  rejectUnauthorized: false,
  ca: TRUSTED_CA_LIST,
  protocol: 'mqtts',
  //釋出者實作認證的參數
  username:"alice",
  password:"secret"
}
var client = mqtt.connect(options)
var num = 0;
var qtt = {}; //定義消息
qtt = 'hello world';
//一秒鐘發送一次消息setr=xxxxxxx1xx
setInterval(function() {
    client.publish('alice', qtt, { qos: 0, retain: true });  
}, 10000);
           
MQTT協定應用TLS

抓包分析

MQTT協定應用TLS

1 用戶端送出請求(ClientHello)

MQTT協定應用TLS

(1) 用戶端與服務端通過tcp三次握手建立tcp連接配接後,用戶端首先向伺服器發出建立加密通信的請求,發送ClientHello請求,從消息體結構看,tls/ssl是基于tcp連接配接之上,應用層之下的協定。

2 伺服器響應(SeverHello)

MQTT協定應用TLS
MQTT協定應用TLS

伺服器收到用戶端請求後,向用戶端發出響應,叫做Sever Hello。

從消息體中,可以看到伺服器的響應包含以下内容:

(1) 确認使用的加密通信協定版本,這裡确認使用tls1.2,而不是client hello中的tls1.1。響應握手協定消息 server hello。如果浏覽器與伺服器支援的版本不一緻,伺服器關閉加密通信。

(2) 一個伺服器生成的随機數,稍後用于生成"對話密鑰"。

(3) 确認使用的加密套件,這裡為rsa+aes128+sha256

(4) 壓縮方法為空。

(5) 一些列擴充資訊

3 服務端發送服務端電子證書(CA),密鑰交換(server key exchange),及server hello done三個握手消息

MQTT協定應用TLS

用戶端接收到server hello握手消息後,及時回報ack消息。服務端接收用戶端ack消息後,發送服務端電子證書,密鑰交換,及server hello done三個握手消息

從封裝内容看,包含兩層ssl協定體資訊,頭一個為服務端證書,後面跟着公共密鑰交換和hello done消息體,具體如下:

(1)詳細的電子證書資訊和CA認證機構資訊

(2)密鑰交換資訊,包括DH算法計算出的pubkey公鑰,電子簽名的hash算法值

(3)server hello done消息體

4 用戶端發送密鑰交換資訊(client key exchange)、編碼改變協定消息(change cipher spec)

MQTT協定應用TLS

用戶端發送ack消息給服務端,确認收到server hello done消息,然後發送用戶端的密鑰交換資訊和修改密鑰的協定消息

主要内容如下:

(1) 發送DH算法計算的pubkey,用于服務端計算生成解密私鑰

(2) 發送編碼改變通知,表示随後的資訊都将用雙方商定的加密方法和密鑰發送。

(3) 發送加密後的握手消息,一個随機數。該随機數用伺服器公鑰加密,防止被竊聽

(4) 用戶端握手結束通知,表示用戶端的握手階段已經結束。這一項同時也是前面發送的所有内容的hash值,用來供伺服器校驗。(可能在加密消息中,未确認)

用戶端收到伺服器所有響應消息後,首先驗證伺服器證書。如果證書不是可信機構頒布、或者證書中的域名與實際域名不一緻、或者證書已經過期,就會向通路者顯示一個警告,由其選擇是否還要繼續通信。

如果證書沒有問題,用戶端就會從證書中取出伺服器的公鑰,即server key exchange消息中攜帶的pubkey值。然後,根據根據已經收到的三個随機數計算書加密密鑰,對握手資訊進行加密通信,然後向伺服器發送上面抓包中三項資訊内容。

​ 至此,整個握手階段全部結束。接下來,用戶端與伺服器進入加密通信,就完全是使用普通的HTTP協定,隻不過用”會話密鑰”加密資料内容。

五 實驗體會(不少于300字)

​ TLS(Transport Layer Security,安全傳輸層),TLS是建立在傳輸層TCP協定之上的協定,服務于應用層,它的前身是SSL(Secure Socket Layer,安全套接字層),它實作了将應用層的封包進行加密後再交由TCP進行傳輸的功能。

​ TLS協定主要解決如下三個網絡安全問題。

1、保密(message privacy),保密通過加密encryption實作,所有資訊都加密傳輸,第三方無法嗅探;

2、完整性(message integrity),通過MAC校驗機制,一旦被篡改,通信雙方會立刻發現;

3、認證(mutual authentication),雙方認證,雙方都可以配備證書,防止身份被冒充;

下面是TLS的握手過程。詳細步驟上面也說過了。

MQTT協定應用TLS

Client1:TLS版本号 + 所支援加密套件清單 + 希望使用的TLS選項

Server1:選擇一個用戶端的加密套件 + 自己的公鑰 + 自己的證書 + 希望使用的TLS選項 +(要求用戶端證書)

Client2:(自己的證書) + 使用伺服器公鑰和協商的加密套件加密一個對稱密鑰

Server2:使用私鑰解密出對稱密鑰後,發送的加密的Finish消息,表明完成握手

任何事物都是有利有弊,引入TLS機制固然是能夠保證安全,但卻在TCP握手和HTTP通信之間,多加了兩個往返的TLS握手過程。

安全問題:

​ 可能存在中間人攻擊。

iot

繼續閱讀