Tags :UbuntuMosquittoMQTT
  • MQTT 的全名為 Message Queuing Telemetry Transport,為 IBM 和 Eurotech 共同製定出來的協定,MQTT 是為了物聯網設計的協定,透過Publish/Subscribe 的方式來做訊息傳送。

  • Publish/Subscribe 有三種主要的組成元件,分別為Publisher、Subscriber 以及 Topic。

  • mosquitto 為 Eclipse 所開發的開源 MQTT broker 和給用戶端使用C語言的API介面,目前最新版本為 V1.4.9。

Prerequisites

1
2
3
4
5
6
7
8
9
sudo wget http://repo.mosquitto.org/debian/mosquitto-repo.gpg.key
sudo apt-key add mosquitto-repo.gpg.key
cd /etc/apt/sources.list.d/
sudo wget http://repo.mosquitto.org/debian/mosquitto-wheezy.list
sudo apt-get update

Install Mosquitto Broker

1
sudo apt-get install mosquitto

Install Mosquitto Client

1
sudo apt-get install mosquitto-clients

測試

開啟兩個終端機分別輸入

終端機1(Subscribe)

1
mosquitto_sub -d -t hello/world

-d :debug 模式 , -t :訂閱的主題名稱 , -h :Broker's IP , -p :Broker's port

終端機2(Publish)

1
mosquitto_pub -d -t hello/world -m "Hello from Terminal window 2!"

-m :發送的文字內容

當兩個command line 都輸入完後終端機分別會看到

終端機1(Subscribe)

1
2
3
4
5
6
7
Client mosqsub/83-MQTT1 sending CONNECT
Client mosqsub/83-MQTT1 received CONNACK
Client mosqsub/83-MQTT1 sending SUBSCRIBE (Mid: 1, Topic: hello/world, QoS: 0)
Client mosqsub/83-MQTT1 received SUBACK
Subscribed (mid: 1): 0
Client mosqsub/83-MQTT1 received PUBLISH (d0, q0, r0, m0, 'hello/world', ... (29 bytes))
Hello from Terminal window 2!

終端機2(Publish)

1
2
3
4
5
MQTT@MQTT:~$ mosquitto_pub -d -t hello/world -m "Hello from Terminal window 2!"
Client mosqpub/82-MQTT sending CONNECT
Client mosqpub/82-MQTT received CONNACK
Client mosqpub/82-MQTT sending PUBLISH (d0, q0, r0, m1, 'hello/world', ... (29 bytes))
Client mosqpub/82-MQTT sending DISCONNECT

mosquitto.conf 參數說明

設定檔設置於 /etc/mosquitto/mosquitto.conf

詳細的參數說明如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
# ================================================= ================
# General configuration
# ================================================= ================
  
# 客戶端心跳的間隔時間
#retry_interval 20
  
# 系統狀態的刷新時間
#sys_interval 10
  
# 系統資源的回收時間,0表示盡快處理
#store_clean_interval 10
  
# 服務進程的PID
#pid_file /var/run/mosquitto.pid
  
# 服務進程的系統用戶
#user mosquitto
  
# 客戶端心跳消息的最大並發數
#max_inflight_messages 10
  
# 客戶端心跳消息緩存隊列
#max_queued_messages 100
  
# 用於設置客戶端長連接的過期時間,默認永不過期
#persistent_client_expiration
  
# ================================================= ================
# Default listener
# ================================================= ================
  
# 服務綁定的IP地址
#bind_address
  
# 服務綁定的端口號
#port 1883
  
# 允許的最大連接數,-1表示沒有限制
#max_connections -1
  
# cafile:CA證書文件
# capath:CA證書目錄
# certfile:PEM證書文件
# keyfile:PEM密鑰文件
#cafile
#capath
#certfile
#keyfile
  
# 必須提供證書以保證數據安全性
#require_certificate false
  
# 若require_certificate值為true,use_identity_as_username也必須為true
#use_identity_as_username false
  
# 啟用PSK(Pre-shared-key)支持
#psk_hint
  
# SSL/TSL加密算法,可以使用“openssl ciphers”命令獲取
# as the output of that command.
#ciphers
  
# ================================================= ================
# Persistence
# ================================================= ================
  
# 消息自動保存的間隔時間
#autosave_interval 1800
  
# 消息自動保存功能的開關
#autosave_on_changes false
  
# 持久化功能的開關
persistence true
  
# 持久化DB文件
#persistence_file mosquitto.db
  
# 持久化DB文件目錄
#persistence_location /var/lib/mosquitto/
  
# ================================================= ================
# Logging
# ================================================= ================
  
# 4種日誌模式:stdout、stderr、syslog、topic
# none 則表示不記日誌,此配置可以提升些許性能
log_dest none
  
# 選擇日誌的級別(可設置多項)
#log_type error
#log_type warning
#log_type notice
#log_type information
  
# 是否記錄客戶端連接信息
#connection_messages true
  
# 是否記錄日誌時間
#log_timestamp true
  
# ================================================= ================
# Security
# ================================================= ================
  
# 客戶端ID的前綴限制,可用於保證安全性
#clientid_prefixes
  
# 允許匿名用戶
#allow_anonymous true
  
# 用戶/密碼文件,默認格式:username:password
#password_file
  
# PSK格式密碼文件,默認格式:identity:key
#psk_file
  
# pattern write sensor/%u/data
# ACL權限配置,常用語法如下:
# 用戶限制:user <username>
# 話題限制:topic [read|write] <topic>
# 正則限制:pattern write sensor/%u/data
#acl_file
  
# ================================================= ================
# Bridges
# ================================================= ================
  
# 允許服務之間使用“橋接”模式(可用於分佈式部署)
#connection <name>
#address <host>[:<port>]
#topic <topic> [[[out | in | both] qos-level] local-prefix remote-prefix]
  
# 設置橋接的客戶端ID
#clientid
  
# 橋接斷開時,是否清除遠程服務器中的消息
#cleansession false
  
# 是否發布橋接的狀態信息
#notifications true
  
# 設置橋接模式下,消息將會發佈到的話題地址
# $SYS/broker/connection/<clientid>/state
#notification_topic
  
# 設置橋接的keepalive數值
#keepalive_interval 60
  
# 橋接模式,目前有三種:automatic、lazy、once
#start_type automatic
  
# 橋接模式automatic的超時時間
#restart_timeout 30
  
# 橋接模式lazy的超時時間
#idle_timeout 60
  
# 橋接客戶端的用戶名
#username
  
# 橋接客戶端的密碼
#password
  
# bridge_cafile:橋接客戶端的CA證書文件
# bridge_capath:橋接客戶端的CA證書目錄
# bridge_certfile:橋接客戶端的PEM證書文件
# bridge_keyfile:橋接客戶端的PEM密鑰文件
#bridge_cafile
#bridge_capath
#bridge_certfile
#bridge_keyfile
  
# 自己的配置可以放到以下目錄中
include_dir /etc/mosquitto/conf.d

參考來源 :

  1. Mosquitto簡要教程(安裝/使用/測試)
  2. Tutorial: IOT / Installing and Testing Mosquitto MQTT on the Raspberry Pi

認證方式

Broker的認證方式,Mosquitto端提供了四種認證方法分別為

  • 無認證
  • 帳號/密碼
  • 預先共享密鑰(Pre-shared Key)加密
  • 憑證加密

無認證

要打開 /etc/mosquitto/mosquitto.conf 設定檔將allow_anonymous設定為true即可。此時我們可以利用mosquitto_sub來測試

Subscribe

1
mosquitto_sub -h "<IP address>" -v -t "<Topic's name>"

Publish

1
mosquitto_pub -h "<IP address>" -v -t "<Topic's name>" -m "<Message>"

-t :訂閱的主題,-v :連主題名稱也列印在銀幕上。

帳號/密碼

  • 新增帳號密碼

    使用此方式需利用上述的 mosquitto_passwd 產生密碼,並將密碼檔案名稱設定到password_file此欄位。

    1
    mosquitto_passwd -c "<passwordfile>" "<username>"

    如果passwordfile檔案已經存在,則下次新增使用者則不需要加 -c

    下列命令將新產生一個密碼檔案/etc/mosquitto/passwd,並建立一個帳號名稱為easy,使用者輸入密碼後即可建立帳號與密碼

    1
    2
    3
    sudo mosquitto_passwd -c /etc/mosquitto/passwd easy
    Password: xxxx
    Reenter password: xxxx
  • 設定ACL(Access Control List)

    Path : /etc/mosquitto/acl 內容如下:

    1
    2
    3
    4
    5
    6
    7
    # 用戶easy 對於主題hello/world 能夠進行寫入
    user easy
    topic write hello/world
    # 用戶easy 對於主題hello/world 能夠進行讀取
    user easy
    topic read hello/world
  • 最後更改 /etc/mosquitto/mosquitto.conf 設定檔

    1
    2
    3
    4
    5
    allow_anonymous false #不允許匿名傳輸
    password_file /etc/mosquitto/passwd #配置用戶(username)密碼
    acl_file /etc/mosquitto/acl #設置用戶與主題(topic)存取權限
  • 測試

    Subscribe

    1
    mosquitto_sub -h "<IP address>" -v -d -t "<topic's name'>" -u "<User>" -P "<Possword>"

    Publish

    1
    mosquitto_pub -h "<IP address>" -v -t "<Topic's name>" -m "<Message>" -u "<User>" -P "<Possword>"

預先共享密鑰(Pre-shared Key)加密

這個認證方式需要使用到OpenSSL中的預先共享密鑰加密方式,而在OpenBSD開發的LibreSSL專案中,因為SSL/TLS安全性的問題,預先共享密鑰加密方式暫時被移除了。

未移除之前的修改方式如下:

  • 設定PSK(Pre-Shared Key)

    Path : /etc/mosquitto/psk 內容如下:

    每一行有兩個欄位以’:’隔開,第一個欄位為帳號而第二個欄位即為密鑰

    1
    2
    #帳號:密鑰
    easy:b7ecaa34a9dbd7bfb8e9ee707427176d04d19eb3
  • 修改 /etc/mosquitto/mosquitto.conf 設定檔

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    #不允許匿名傳輸
    allow_anonymous false
    # 取消 MQTT username for access
    require_certificate true
    # 開啟 pre-shared-key based encryption
    use_identity_as_username true
    # 設置 psk_file
    psk_file /mosquitto/psk
  • 測試

    Subscribe

    1
    mosquitto_sub -h "<IP address>" -v -d -t "<topic's name'>" --psk-identity "<id>" -psk "<key>"

    Publish

    1
    mosquitto_pub -h "<IP address>" -v -t "<Topic's name>" --psk-identity "<id>" -psk "<key>" -m "<Message>"

憑證加密

TLS是非常成熟的安全協議,在握手的時候便可以創建安全連接,使得駭客無法竊聽或者篡改內容。使用TLS的時候有以下注意點:

  1. 盡可能使用高版本的TLS。
  2. 驗證X509憑證連結防止中間人攻擊。
  3. 儘量使用有CA發佈的證書。

產生憑證的方法可以參考如下

  • 產生憑證

    建立CA(Certificate Authority)所需的證書及密鑰

    1
    openssl req -new -x509 -days 365 -extensions v3_ca -keyout ca.key -out ca.crt

    系統端的憑證

    1
    2
    3
    4
    5
    6
    7
    8
    # 產生不加密的金鑰
    openssl genrsa -out server.key 2048
    # 產生憑證簽發請求檔案(Certificate Signing Request)
    openssl req -new -key server.key -out server.csr
    # 憑證簽發
    openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 365
  • 修改 /etc/mosquitto/mosquitto.conf 設定檔

    1
    2
    3
    4
    5
    6
    7
    listener 8883
    cafile /etc/mosquitto/ca.crt
    certfile /etc/mosquitto/server.crt
    keyfile /etc/mosquitto/server.key
  • 測試

    Subscribe

    1
    mosquitto_sub -d -h "<IP address>" -p 8883 -t topic --cafile ca.crt

    Publish

    1
    mosquitto_pub -d -h "<IP address>" -p 8883 -t topic -m “Hello World!” --cafile ca.crt

參考來源:

  1. Mosquitto - an Open Source MQTT broker
  2. mosquitto介紹 · MQTT and mosquitto