1. 程式人生 > >翻譯:如何在Ubuntu16.04上安裝Mosquitto這個MQTT消息服務器並對其進行安全配置

翻譯:如何在Ubuntu16.04上安裝Mosquitto這個MQTT消息服務器並對其進行安全配置

加ss ide 特定 path cert 安裝完成 再次 應用 ron

原文地址: https://www.digitalocean.com/community/tutorials/how-to-install-and-secure-the-mosquitto-mqtt-messaging-broker-on-ubuntu-16-04

簡介

MQTT是一個在機器和機器之間傳遞消息的協議,為實現物聯網設備間輕量級的發布/訂閱通信而設計。廣泛應用於汽車地理位置追蹤,智能家居自動化,環境傳感網絡,以及各項公共事業的數據收集。

Mosquitto是一個流行的MQTT服務器(在MQTT協議中叫中繼器),擁有強大的社區支持,易於安裝、配置。

在此教程中,我們將安裝Mosquito,從Let‘s Encrypt獲取證書,搭建我們自己的中繼器,采用密碼認證,采用SSL來確保MQTT通信安全。

前提條件

在開始這個教程之前,你需要:

  • 一個Ubuntu16.04服務器,非root並且開啟了sudo的用戶,設置了基本的防火墻,具體請參考這個Ubuntu16.04服務器搭建教程。
  • 一個指向了你服務器的域名,可以參照如何在DigitalOcean上創建一個域名。這篇教程將使用mqtt.example.com代替。

步驟1 安裝Mosquitto

Ubuntu16.04默認軟件倉庫的Mosquitto版本就挺新的。用你的非root用戶登錄並使用 apt-get安裝Mosquitto.

$ sudo apt-get install mosquitto mosquitto-clients

默認情況下,Ubuntu會在安裝後啟動Mosquitto服務。我們先測試一下默認配置。使用剛安裝的Mosquitto客戶端訂閱中繼器上的一個主題。

主題是發送和訂閱消息的標簽。它們按層次設置,比如你可以將主題設置為sensors/outside/tempsensors/outside/humidity。如何設置主題取決於的你需要。教程通篇將用一個簡單的主題test來測試配置變化。

再打開一個服務器命令窗口,這樣你就有兩個並列的窗口了。在新的命令行中,使用mosquitto_sub來訂閱test主題:

mosquitto_sub -h localhost -t test

-h用於指定MQTT服務器的主機名,-t用於指定主題。當按下回車鍵之後,沒有任何輸出,這是因為mosquitto_sub正在等待消息送達。回到另外一個命令行,發布一條消息:

mosquitto_pub
-h localhost -t test -m "Hello world"

mosquitto_pub的選項和mosquitto_sub的一樣,除了這次我們用了一個-m選項來指定消息內容。按下回車,將會看到Hello world在另外一個命令行中出現。你剛剛發送了你的第一條MQTT消息。

在第二個命令行輸入CTRL + C,退出mosquitto_sub, 但保持和服務器的連接。在步驟五將再次使用到它。

接下來,我們將用通過Certbot的SSL來確保我們Mosquitto的安全,Certbot是Let‘s Encrypt的新版客戶端。

步驟2 為了獲得Let‘s Encrypt證書,安裝Certbot

Let‘s Encrypt是一個通過自動化的API,提供免費的SSL證書的服務。很多客戶端可以調用這個API。Ubuntu的默認倉庫包含了官方的客戶端,但有點過時了,並且缺少了一個我們需要的新特性。

因此,我們從一個Ubuntu PPA(Personal Package Archive)安裝官方的客戶端。很多替代倉庫的打包了更新的版本,或者是小眾軟件。首先,添加倉庫:

sudo add-apt-respository ppa:certbot/certbot

需要敲一下回車來接受安裝。接下來,更新包列表來獲取新倉庫的包信息。

sudo apt-get update

最後,安裝Let‘s Encrypt的官方客戶端,叫做certbot

sudo apt-get install certbot

certbot已經安裝完成,接下來運行它來獲得我們所需的證書。

步驟3 運行Certbot

certbot需要響應一個Let‘s Encrypt發出的密碼質詢,用來證明我們對這個域名有控制權。它使用端口80(HTTP) 且/或 443(HTTPS)來完成。我們將僅使用端口80,所以我們需要在這個端口上允許入網流量。

$ sudo ufw allow http
Rule added

現在我們可以運行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

運行上述命令時,命令行會提示你輸入一個郵箱地址,並同意服務條款。再之後,你將會看到一條消息,告訴你處理成功,並且告知你證書的存放位置。

我們已經獲得了證書,現在我們需要確保Certot在證書快過期時自動地更新他們。

步驟4 創建Certbot的自動更新策略

Let‘s Encrypt的證書有效期僅為90天。這是為了鼓勵用戶將他們的證書更新流程自動化。我們將創建一個定期運行的命令,檢查證書過期情況並自動更新它們。

我們將通過cron每天運行更新檢查。這是運行周期性工作的一個系統服務。打開並編輯一個叫做crontab的文件,來指定cron要完成的工作。

sudo crontab -e

你將會看到選擇一個文本編輯器的提示。選一個你喜歡的,然後將會看到默認的corontab, 並且附帶一個幫助說明。在文件的最後加入下面這一行,保存並關閉文件。

15 3 * * * certbot renew --noninteractive --post-hook "systemctl restart mosquitto"

15 3 * * *表示每天上午3點15運行後面的命令。Certbot的renew命令會檢查服務器上安裝的所有證書,並更新那些過期時間不足30天的。--noninteractive告訴Certbot不要等待用戶輸入。

--post-hook "systemctl restart mosquitto"將會重啟Mosquitto,以采用最新的證書,但這條命令只會在證書被更新後才執行。這個post-hook特性是舊版的Let‘s Encrypt客戶端沒有的。這也是我們從PPA而不是默認的Ubuntu庫安裝的原因。沒有這一項,即使沒有證書更新,我們也需要每天重啟Mosquitto。

盡管MQTT客戶端需要設置了自動重連,但避免每天無端地打斷他們是非常明智的。

既然自動地更新證書已經配置妥當,我們就回過頭來配置Mosquitto,讓他更加安全。

步驟5 配置MQTT密碼

接下來配置Mosquitto,啟用密碼。Mosquitto包含了一個工具,用來生成一個特殊的密碼文件,叫做mosquitto_passwd。這個命令將提示你為指定的用戶名輸入密碼,並把結果保存在/etc/mosquitto/passwd中。

sudo mosquitto_passwd -c /etc/mosquitto/passwd sammy

接下來,為Mosquitto打開一個新的配置文件,指定所有連接登錄時所需的密碼文件。

sudo nano /etc/mosquitto/conf.d/default.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"

這條消息會被拒絕:

Output
Connection Refused: not authorised.
Error: The connection was refused.

在用密碼進行嘗試之前,轉到另一個命令行,使用用戶名和密碼訂閱test主題。

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加密來解決這一問題。

步驟6 配置MQTT的SSL

為開啟SSL加密,需要在Mosquitto配置裏制定證書存放的位置。打開剛才開始的配置文件:

sudo nano /etc/mosquitto/conf.d/default.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)的標準端口。接下來三行,certfilecafilekeyfile,都是為了將Mosquitto指向特定的Let‘s Encrypt文件,這些文件將被用於創建加密的連接。

保存並退出文件,重啟Mosquitto以更新配置:

sudo systemctl restart mosquitto

更新防火墻,使其允許連接到端口8883。

sudo ufw allow 8883

接下來,使用mosquitto_pub, 附帶幾個SSL的特定選項:

mosquitto_pub -h mqtt.example.com -t test -m "hello again" -p 8883 --capath /etc/ssl/certs/ -u "sammy" -P "password"

註意,這次使用了完整的主機名,而不是localhost。因為SSL證書是對mqtt.example.com發放的,如果我們嘗試對localhost創建一個安全鏈接,將會收到一條消息,說當前主機名和證書的主機名不一致。即便他們都指向了同一個Mosquitto服務器。

--capath /etc/ssl/certsmosquitto_pub啟動了SSL,並指定了去何處尋找根證書。這些證書被你的操作系統安裝在特定的位置,所以這個地址在MacOS、Windows等系統上是不一樣的。mosquitto_pub采用根證書來來檢查Mosquitto服務器的證書是否是否被Let‘s Encrypt的證書授權機構認證過。有一點需要註意的是,沒有這個選項,mosquitto_pubmosquitto_sub是不會嘗試使用SSL鏈接的,即使你嘗試連接到一個標準的安全端口8883。一個類似的選項為--cafile

如果測試順利的話,會看到hello again出現在命令行中。到這裏,意味著已經完成了服務器搭建!如果你對拓展MQTT協議,使其可以基於websocket協議工作的話,請參考下面最終一步。

步驟7 配置通過WebSockets來使用MQTT(可選)

為了在web瀏覽器中通過JavaScript調用MQTT,協議通過適配,可以支持標準的WebSockets。如果你不需要這項功能,可以跳過此步驟。

我們需要在配置文件添加一個新的listener塊:

sudo nano /etc/mosquitto/conf.d/default.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那一行。對於通過websockets方式提供的MQTT服務,沒有官方的標準。但8083是最常用的。

保存並退出這個文件,然後重啟Mosquitto。

sudo systemctl restart mosquitto

接下來,在防火墻開啟8083端口。

sudo ufw allow 8083

為測試此功能,需要用到一個公開的,基於瀏覽器的MQTT客戶端。這種客戶端有很多,但mqtt-admin是最簡單直接的。在瀏覽器打開mqtt-admin。將會看到設置窗口。

填入如下連接信息:

  • Protocol選擇wss(websocket secure)。
  • Host填入Mosquitto服務器的域名。
  • Port填入8083
  • User填入Mosquitto的用戶名。
  • Password填入你設置的密碼。
  • ClientID保持默認。

點擊保存設置之後,mqtt-admin會連接到Mosquitto服務器。接下來,在Topic處填入test,在Payload處填入任意信息,然後點擊Publish。將會在mosquitto_sub命令行顯示消息。

結語

到現在為止,我們已經建立起了一個安全,有密碼保護機制的MQTT服務器,並設置了從Let‘s Encrypt服務自動更新SSL證書的方法。這對於你未來的任何項目都能夠提供穩健和安全的消息平臺。一些流行的軟件和硬件在MQTT協議下運轉良好:

  • OwnTracks, 是一個開源的地理位置追蹤APP。OwnTracks會定期向服務器報告位置信息。隨後你可以存儲並將這些信息展示在底圖上,創建警報器,基於地理位置激活你的物聯網設備。
  • Node-RED, 一個基於瀏覽器的圖形界面,用於將物聯網設備連接起來。可以將一個節點的輸出連接到另一個節點的輸入上,並可以通過過濾器在不同的協議之間路由信息。存入數據庫等等。
  • ESP8266是一個便宜的WiFi微控制器,並具備MQTT能力。可以通過它發布溫度信息到一個主題上,或者可以訂閱大氣壓主題再或者當暴風雨來臨時讓蜂鳴器響起來。

這僅是MQTT生態系統的一部分知名案例。有更多的一些硬件或者軟件采用了這種協議。如果你已經有了一個自己喜愛的硬件平臺,或者軟件編程語言,它可能就已經具備了MQTT能力。在讓你的“物”彼此通信的過程中享受樂趣吧。

翻譯:如何在Ubuntu16.04上安裝Mosquitto這個MQTT消息服務器並對其進行安全配置