MQTT是一種機器到機器消息協議,旨在為“物聯網”設備提供輕量級發布/訂閱通信。 Mosquitto是一個受歡迎的MQTT服務器(或代理,在MQTT中的用法),具有良好的社區支持,易于安裝和配置。在本教程中,我們將安裝Mosquitto,從Let's Encrypt檢索SSL證書,并設置我們的代理使用SSL來保護受密碼保護的MQTT通信。
介紹
MQTT是一種機器到機器消息協議,旨在為“物聯網”設備提供輕量級發布/訂閱通信。它通常用于車輛的地理跟蹤車隊,家庭自動化,環境傳感器網絡和公用事業規模的數據收集。 Mosquitto是一個受歡迎的MQTT服務器(或代理 ,在MQTT中的用法),具有良好的社區支持,易于安裝和配置。 在本教程中,我們將安裝Mosquitto,從Let's Encrypt檢索SSL證書,并設置我們的代理使用SSL來保護受密碼保護的MQTT通信。
先決條件
在開始本教程之前,您需要:
具有非root,啟用sudo的用戶和基本防火墻的CentOS 7服務器。這個(和更多)在新的CentOS 7服務器清單中有所有。
指向您的服務器的域名,按照如何使用DigitalOcean設置主機名 。本教程將使用mqtt.example.com。
可選,
nano
文本編輯器。 安裝您喜歡的文本編輯器。 本教程將使用nano
整個,你可以隨時安裝它與sudo yum -y install nano
。
第1步 - 安裝Mosquitto
默認情況下,CentOS 7沒有mosquitto包。要安裝它,我們將首先安裝一個名為Extra Packages for Enterprise Linux或EPEL的額外軟件存儲庫。這個存儲庫包含了在CentOS,Red Hat和其他面向企業的Linux發行版上安裝的附加軟件。 使用非root用戶登錄,并使用yum軟件包管理器安裝epel-release軟件包。
sudo yum -y install epel-release
這將EPEL存儲庫信息添加到我們的系統。-y選項會在整個過程中自動為yes回答幾個提示。 現在我們可以安裝mosquitto包。
sudo yum -y install mosquitto
該包有一個簡單的默認配置,所以讓我們運行它來測試我們的安裝。
sudo systemctl start mosquitto
我們還需要啟用服務,以確保它啟動時,我們重新啟動系統:
sudo systemctl enable mosquitto
現在讓我們測試默認配置。mosquitto包附帶一些命令行MQTT客戶端。我們將使用其中一個訂閱我們的經紀人的主題。 主題是您向其發布消息和訂閱的標簽。 它們被布置為層次結構,因此,例如,您可以具有sensors/outside/temp和sensors/outside/humidity 。如何安排主題取決于你和你的需要。在本教程中,我們將使用一個簡單的測試主題來測試我們的配置更改。 第二次登錄到您的服務器,因此您有兩個端子并排。在新終端中,使用mosquitto_sub訂閱測試主題:
mosquitto_sub -h localhost -t test
-h用于指定MQTT服務器的主機名, -t是主題名。 由于mosquitto_sub正在等待消息到達,因此在按ENTER后沒有輸出。切換回您的其他終端并發布消息:
mosquitto_pub -h localhost -t test -m "hello world"
mosquitto_pub的選項與mosquitto_pub相同,但是這次我們使用附加的-m選項來指定我們的消息。 按ENTER ,你應該看到hello world彈出在另一個終端。您發送了第一個MQTT消息! 在第二個終端中輸入CTRL+C ,退出mosquitto_sub ,但保持與服務器的連接打開。我們將在第5步中再次使用它進行另一個測試。 接下來,我們將使用Certbot(新的Let's Encrypt客戶端)使用SSL保護我們的安裝。
第2步 - 安裝并運行Certbot讓我們加密證書
Let's Encrypt是一項新服務,通過自動API提供免費的SSL證書。官方Let's Encrypt客戶端稱為Certbot,它包含在我們在上一步中安裝的EPEL存儲庫中。 用yum安裝Certbot。
sudo yum -y install certbot
Certbot需要回答Let's Encrypt API發出的加密挑戰,以證明我們控制我們的域。它使用端口80
(HTTP)和/或443
(HTTPS)來完成此操作。 我們只使用端口80
,所以讓我們允許在該端口上的傳入流量。 使用firewall-cmd
添加HTTP服務。
sudo firewall-cmd --permanent --add-service=http
重新加載防火墻,以使更改生效。
sudo firewall-cmd --reload
我們現在可以運行Certbot獲取我們的證書。我們將使用--standalone
選項告訴Certbot自己處理HTTP質詢請求,以及--standalone-supported-challenges http-01
將通信限制為端口80
。 -d
用于指定您想要證書的域,并且certonly
告知Certbot只是檢索證書,而不執行任何其他配置步驟。
sudo certbot certonly --standalone --standalone-supported-challenges http-01 -d mqtt.example.com
運行命令時,系統將提示您輸入電子郵件地址并同意服務條款。這樣做后,您應該會看到一條消息,告訴您進程成功以及您的證書存儲在何處。 我們有我們的證書。現在我們需要確保Certbot在它們即將到期時自動更新它們。
第3步 - 設置Certbot自動續訂
讓我們加密的證書只有九十天有效。這是為了鼓勵用戶自動執行證書續訂過程。我們需要設置一個定期運行的命令來檢查到期的證書并自動更新。 為了每天運行更新檢查,我們將使用cron
作為運行周期性作業的標準系統服務。 我們通過打開和編輯名為crontab
的文件告訴cron
要做什么。
sudo EDITOR=nano crontab -e
EDITOR=nano
將使nano
編輯器中的crontab文件打開。 如果您希望使用默認vi
編輯器,請將其關閉。 您現在應該看到默認的crontab
,一個空白文件。粘貼到以下行,然后保存并關閉文件。
crontab
15 3 * * * certbot renew --noninteractive --post-hook "systemctl restart mosquitto"
該行的15 3 * * *
部分表示“每天上午3:15運行以下命令”。 Certbot的renew
命令將檢查系統上安裝的所有證書,并更新任何設置為在三十天內到期的證書。 --noninteractive
告知Certbot不要等待用戶輸入。 --post-hook "systemctl restart mosquitto"
將重新啟動Mosquitto以獲取新證書,但前提是證書已更新。 現在,自動證書更新已設置,我們將回到配置Mosquitto更安全。
第4步 - 配置MQTT密碼
讓我們配置Mosquitto使用密碼。 Mosquitto包含一個實用程序來生成一個名為mosquitto_passwd
的特殊密碼文件。 此命令將提示您輸入指定用戶名的密碼,并將結果放在/etc/mosquitto/passwd
。
sudo mosquitto_passwd -c /etc/mosquitto/passwd sammy
現在我們將替換默認配置文件,并告訴Mosquitto使用此密碼文件要求所有連接登錄。首先,刪除現有的mosquitto.conf
。
sudo rm /etc/mosquitto/mosquitto.conf
現在打開一個新的,空白的配置。
sudo nano /etc/mosquitto/mosquitto.conf
粘貼在以下。
/etc/mosquitto/mosquitto.conf
allow_anonymous false
password_file /etc/mosquitto/passwd
allow_anonymous false
將禁用所有未驗證的連接, password_file
行告訴Mosquitto在哪里查找用戶和密碼信息。保存并退出文件。 現在我們需要重新啟動Mosquitto并測試我們的更改。
sudo systemctl restart mosquitto
嘗試發布不帶密碼的郵件。
mosquitto_pub -h localhost -t "test" -m "hello world"
該郵件應該被拒絕:
Connection Refused: not authorised.
Error: The connection was refused.
在我們再次嘗試使用密碼,再次切換到您的第二個終端窗口,并訂閱'測試'主題,使用用戶名和密碼這次:
mosquitto_sub -h localhost -t test -u "sammy" -P "password"
它應該連接和坐,等待消息。您可以將此終端保持打開并連接到本教程的其余部分,因為我們將定期發送測試消息。 現在與您的其他終端發布消息,再次使用用戶名和密碼:
mosquitto_pub -h localhost -t "test" -m "hello world" -u "sammy" -P "password"
消息應該通過,如第1步中所示。我們已成功添加密碼保護Mosquitto。不幸的是,我們通過互聯網發送密碼未加密。我們將通過添加SSL加密到Mosquitto來解決。
第5步 - 配置MQTT SSL
要啟用SSL加密,我們需要告訴Mosquitto我們的加密證書存儲在哪里。打開我們以前啟動的配置文件。
sudo nano /etc/mosquitto/mosquitto.conf
粘貼到文件末尾的下面,留下我們已經添加的兩行:
/etc/mosquitto/mosquitto.conf
. . .
listener 1883 localhost
listener 8883
certfile /etc/letsencrypt/live/mqtt.example.com/cert.pem
cafile /etc/letsencrypt/live/mqtt.example.com/chain.pem
keyfile /etc/letsencrypt/live/mqtt.example.com/privkey.pem
我們在配置中添加了兩個獨立的listener
塊。 第一個, listener 1883 localhost
更新端口1883
上的默認MQTT監聽器,這是我們一直連接到目前為止。 1883
是標準的未加密MQTT端口。 該行的localhost
部分指示Mosquitto僅將此端口綁定到localhost接口,因此無法從外部訪問。外部請求將被我們的防火墻阻止,但是很好明確。 listener 8883
在端口8883
上設置加密的監聽器。 這是MQTT + SSL的標準端口,通常稱為MQTTS。 接下來的三行, certfile
, cafile
和keyfile
,都將Mosquitto指向相應的Let's Encrypt文件來設置加密連接。 保存并退出文件。 在我們重新啟動Mosquitto加載新的配置之前,我們需要修復默認mosquitto
服務文件中的一件事。 這是systemd
用來確定如何運行mosquitto
。在您喜歡的編輯器中打開它。
sudo nano /etc/systemd/system/multi-user.target.wants/mosquitto.service
查找一條表示User=mosquitto
并將其刪除的行,然后保存并退出該文件。 Mosquitto仍將作為mosquitto用戶運行,但是當它首次啟動時,它將具有root權限,并且將能夠加載我們的Let's Encrypt證書(出于安全原因,它被限制為root訪問權限)。 加載證書后,它將下載到蚊子用戶。 我們需要重新加載systemd
本身,所以它注意到我們對服務文件所做的更改。
sudo systemctl daemon-reload
現在我們可以重新啟動Mosquitto更新設置。
sudo systemctl restart mosquitto
更新防火墻以允許連接到端口8883
。
sudo firewall-cmd --permanent --add-port=8883/tcp
并重新加載防火墻。
sudo firewall-cmd --reload
現在我們再次使用mosquitto_pub
測試,有幾個不同的SSL選項。
mosquitto_pub -h mqtt.example.com -t test -m "hello again" -p 8883 --cafile /etc/ssl/certs/ca-bundle.crt -u "sammy" -P "password"
請注意,我們使用完整的主機名而不是localhost
。 因為我們的SSL證書是針對mqtt.example.com
發出的,如果我們嘗試到localhost
的安全連接,我們會收到一個錯誤,指出主機名與證書主機名不匹配(即使它們都指向同一個Mosquitto服務器)。 --cafile /etc/ssl/certs/ca-bundle.crt
為--cafile /etc/ssl/certs/ca-bundle.crt
啟用S??SL,并告知它在哪里查找根證書。 這些通常由操作系統安裝,因此對于Mac OS,Windows等, mosquitto_pub
使用根證書來驗證Mosquitto服務器的證書是否由Let's Encrypt證書頒發機構正確簽名。 請注意,即使您連接到8883
的標準安全端口, mosquitto_pub
和mosquitto_sub
也不會嘗試使用此選項(或類似的--capath
選項)的SSL連接。 如果一切順利的測試,我們會看到你好再次出現在另一個mosquitto_sub
終端。這意味著您的服務器已完全設置!如果你想擴展MQTT協議來使用websockets,你可以按照最后一步。
第6步 - 通過WebSocket配置MQTT(可選)
為了使用Web瀏覽器中的JavaScript來講MQTT,協議適用于在標準websockets上工作。如果您不需要此功能,則可以跳過此步驟。 我們需要添加一個listener
塊到我們的Mosquitto配置。
sudo nano /etc/mosquitto/mosquitto.conf
在文件的末尾,添加以下內容:
/etc/mosquitto/mosquitto.conf
. . .
listener 8083
protocol websockets
certfile /etc/letsencrypt/live/mqtt.example.com/cert.pem
cafile /etc/letsencrypt/live/mqtt.example.com/chain.pem
keyfile /etc/letsencrypt/live/mqtt.example.com/privkey.pem
這protocol websockets
與上一個塊相同,除了端口號和protocol websockets
行。 沒有用于MQTT的官方標準化端口通過websockets,但8083
是最常見的。 保存并退出文件,然后重新啟動Mosquitto。
sudo systemctl restart mosquitto
現在,打開防火墻中的端口8083
。
sudo firewall-cmd --permanent --add-port=8083/tcp
并且最后一次重新加載防火墻。
sudo firewall-cmd --reload
為了測試這個功能,我們將使用一個基于瀏覽器的公共MQTT客戶端。有幾個,但是mqtt-admin是簡單和直接。 在瀏覽器中打開mqtt-admin 。您將看到以下內容:
按如下所示填寫連接信息:
- 協議應該是wss (這代表web的ocket s ecure)。
-
主機應該是您的Mosquitto服務器的域,
mqtt.example.com
。 -
端口應為
8083
。 - 用戶應該是您的Mosquitto用戶名; 在這里,我們使用sammy 。
- 密碼應該是您選擇的密碼。
- ClientId可以保留默認值mqtt-admin 。
按下保存設置后 , mqtt-admin
將連接到您的Mosquitto服務器。 在下一個屏幕中,填寫Topic作為測試 ,輸入任何有關Payload的消息,然后按發布 。 該消息將顯示在mosquitto_sub
終端中。
結論
我們現在已經設置了一個安全的,密碼保護的MQTT服務器,使用來自Let's Encrypt服務的自動更新SSL證書。這將作為一個強大和安全的消息平臺,用于任何項目你夢想。一些流行的軟件和硬件與MQTT協議工作良好包括:
- OwnTracks是一個開源的地理跟蹤應用,您可以在手機上安裝。 OwnTracks將定期向MQTT服務器報告位置信息,然后您可以將其存儲和顯示在地圖上,或根據您的位置創建警報并激活物聯網硬件。
- Node-RED是一個基于瀏覽器的圖形界面,用于將物聯網“布線”在一起。您將一個節點的輸出拖動到另一個節點的輸入,并可以通過過濾器,在各種協議之間將信息路由到數據庫等。 MQTT得到了Node-RED的很好的支持。
- ESP8266是一個具有MQTT功能的便宜的wifi微控制器。你可以連接一個發布溫度數據到一個主題,或者訂閱氣壓壓力主題,并在暴風雨來臨時發出蜂鳴聲!
這些只是MQTT生態系統中的幾個流行示例。有更多的硬件和軟件在那里說的協議。如果你已經有一個喜歡的硬件平臺或軟件語言,它可能有MQTT功能。有樂趣讓你的“東西”彼此交談!