HomeMicroservicesCài đặt một MQTT Broker đơn giản sử dụng Mosca và MQTTnet
MQTT là gì?
MQTT [Message Queuing Telemetry Transport] là một Publish/Subscribe messaging protocol rất đơn giản, nhẹ sử dụng băng thông thấp, độ tin cậy cao và có khả năng hoạt động trong điều kiện đường truyền không ổn định.
Có nhiều cách để khởi tạo một MQTT Server như
1. Dùng các hệ thống cloud có sẵn
//www.cloudmqtt.com
//www.hivemq.com
2. Dùng các công cụ có sẵn hỗ trợ giao diện hoặc dòng lệnh [Mosquitto]
3. Dùng các thư viện hỗ trợ ở từng loại ngôn ngữ bạn sử dụng
C# : MQTTnet
JavaScript :
Mosca
Ở đây tôi sử dụng cách thứ 3 và dùng thư viện Mosca trên NodeJS
Cài đặt MQTT Server sử dụng Mosca
Yêu cầu
Máy tính có cài đặt NodeJS
Docker Desktop [Trong trường hợp muốn deploy container]
Các bạn có thể tải về tham khảo code mẫu ở đây.
Các bước thực hiện
Khởi tạo một project NodeJS
npm init
Cài đặt các thư viện
Mosca là thư viện để tạo MQTT server
//github.com/mcollina/mosca
//www.npmjs.com/package/mosca
mqtt là thư viện để tạo các tương tác từ client lên MQTT server
//www.npmjs.com/package/mqtt
npm install mosca
npm install mqtt
Trong trường hợp có lỗi liên quan đến Visual Studio Compiler có thể sử dụng câu lệnh sau để fix
npm
install --global --production windows-build-tools
npm config set msvs_version 2017
Tạo file mqtt-server.js để cấu hình MQTT server
Tạo file subscriber.js để tiến hành việc tương tác mà client đóng vai trò là subscriber nhận message từ MQTT server
Tạo file publisher.js.js để
tiến hành việc tương tác mà client đóng vai trò là publisher gửi message tới MQTT server
Mở 3 terminal tương ứng với 3 phần [server, subscriber, publisher] từ vị trí hiện tại của project
Tiến hành chạy lần lượt các phần
node mqtt-server.js
node subscriber.js
node publisher.js
Nếu bạn tải code mẫu của tôi thì sẽ chạy bằng dòng lệnh sau
npm run server
npm run
subscriber
npm run subscriber
Kiểm tra kết quả nhận được
Tạo kết nối từ client là các ứng dụng .NET
Các bạn có thể tải về tham khảo code mẫu ở đây.
Yêu cầu
Visual Studio or Visual Studio Code
.NET Core SDK
Các bước thực hiện
Tạo mới một project ở dạng Console App
dotnet new -o MQTTClientTest
Cài đặt các
thư viện cần thiết
Để kết nối tới MQTT server ở đây tôi sử dụng thư viện MQTTnet
//github.com/chkr1011/MQTTnet
cd MQTTClientTest
dotnet add package MQTTnet
Tham khảo việc gửi nhận dữ liệu trong file Program.cs dưới đây
Chạy và
kiểm tra kết quả
Tiến hành chạy MQTT server tạo ở bên trên
node mqtt-server.js hoặc npm start
dotnet run
Kết quả
Trên đây là ví dụ hết sức đơn giản cho việc tự xây dựng một MQTT server broker với phần server
dùng NodeJS và client dùng .NET.
Với các kiến thức chuyên sâu cụ thể, các bạn vui lòng tham khảo ở các bài viết khác hoặc tìm kiếm thêm thông tin trên internet.
Tham khảo thêm
//medium.com/@alifabdullah/setting-up-private-mqtt-broker-using-mosca-in-node-js-c61a3c74f952
//github.com/chkr1011/MQTTnet
Để có thể tương tác một cách dễ dàng với MQTT Server, bạn có thể sử dụng các công cụ để kiểm tra kết nối tới MQTT dùng giao diện
MQTT.fx
//www.jensd.de/apps/mqttfx/
Mosquitto
//mosquitto.org/download/
Tiếp tục cập nhật ...
Nếu bạn đang muốn tạo một mạng MQTT, bắt đầu với việc cài đặt, cấu hình và bảo mật MQTT broker thì bài viết này dành cho bạn. Linux ở đây là các bản phân phối thông dụng họ Debian như Ubuntu, đặc biệt là Raspbian và Armbian dành cho Raspberry Pi và các máy tính một bo mạch – SBC, phù hợp để vận hành các MQTT broker quy mô tương đối [các bản phân phối họ RHEL – Red Hat Enterprise Linux như Centos cũng có thể sử dụng, tuy nhiên cách cài đặt sẽ hơi khác].
Đầu tiên bạn sẽ cần một máy chủ Linux đã được cài đặt và kết nối mạng thành công. Bạn có thể tham khảo các bước đầu tiên của bài viết này nếu muốn cài đặt Raspbian/Armbian. Với Ubuntu, bạn cần tải về và theo chỉ dẫn trên trang chủ: cài đặt Ubuntu Server.
Bạn cũng cần một tài khoản với quyền root [quản trị] trên máy chủ này để cài đặt phần mềm cũng như chỉnh sửa các thiết lập của hệ thống.
Trong bài này ta sẽ thao tác toàn bộ qua giao diện dòng lệnh [command line] thông qua kết nối SSH hoặc Console [hay Terminal trên Ubuntu]. Nếu bạn chưa biết đến kết nối SSH, hãy xem bài viết này: kết nối đến máy chủ SSH rồi quay lại.
Nguyên tắc chung khi nhập các lệnh trong bài này là:
- Lệnh bắt đầu bằng sudo có nghĩa là thực thi với quyền root, có thể bạn sẽ phải nhập mật khẩu tài khoản hiện tại mỗi lần thực hiện lệnh hoặc chỉ lần đầu tiên tuỳ theo cách cấu hình sudo [đừng lo nếu màn hình không hiện gì khi nhập, cứ tiếp tục nhập cho hết].
- Bạn phải copy lệnh từ đầu đến hết dòng, trước khi số dòng thay đổi [lưu ý là số dòng ở ngay trước lệnh, không phải ngắt dòng hiển thị trên màn hình] ngoại trừ các lệnh kết thúc bằng “\” phải được copy cho đến hết dòng đầu tiên không kết thúc bằng kí tự “\” [câu lệnh trên nhiều dòng]. Mỗi lệnh này được thực hiện bằng phím Enter.
Bạn cũng có thể copy toàn bộ lệnh rồi paste một lần nhưng sẽ khó để phát hiện lỗi. - Toàn bộ lệnh trong bài này cần được thực hiện nối tiếp nhau trong cùng một phiên đăng nhập.
- Nên thực hiện các lệnh này dưới tài khoản bạn hay dùng [như Pi trong Raspbian], không nên dùng nó dưới tài khoản root.
Cài đặt Mosquitto MQTT Broker
Cài đặt trực tiếp trên Hệ điều hành
Cái lợi của việc cài đặt trực tiếp là thể quản lí, chỉnh sửa Mosquitto broker chung với các thành phần khác của hệ điều hành. Bạn cũng không cần phải cài đặt và tốn tài nguyên máy chủ cho các ứng dụng khác. Cái hại là đôi khi xảy ra xung đột giữa các gói phần mềm trên cùng hệ thống và không thể chạy nhiều broker riêng rẽ trên cùng một hệ điều hành theo cách này được.
Để cài đặt mosquitto, trước tiên cần thêm repository [kho phần mềm] của mosquitto vào danh sách của apt – phần mềm quản lý package chính trên các bản phân phối Linux họ Debian. Lệnh mẫu ở dưới, bạn chỉ sử dụng phần tương ứng với hệ điều hành của mình, đánh dấu bằng kí tự “#” [bỏ qua các dòng chú thích này khi nhập lệnh].
#Ubuntu sudo apt-add-repository ppa:mosquitto-dev/mosquitto-ppa #Raspbian/Armbian wget //repo.mosquitto.org/debian/mosquitto-repo.gpg.key sudo apt-key add mosquitto-repo.gpg.key
Với Raspbian/Armbian, cần tiếp tục thêm các lệnh ở dưới, bạn chọn lệnh tuỳ theo phiên bản hệ điều hành là Jessie [cũ nhất], Stretch hay Buster [mới nhất].
#Raspbian/Armbian cat /etc/os-release #Chọn 1 trong 3 lệnh bên dưới sudo wget //repo.mosquitto.org/debian/mosquitto-jessie.list sudo wget //repo.mosquitto.org/debian/mosquitto-stretch.list sudo wget //repo.mosquitto.org/debian/mosquitto-buster.list
Tiếp theo cập nhật apt và cài đặt mosquitto [broker] và mosquitto-client [tuỳ chọn].
#Ubuntu & Raspbian/Armbian sudo apt-get update sudo apt-get upgrade -y sudo apt-get install -y mosquitto #tuỳ chọn sudo apt-get install mosquitto-clients
Đến đây là bạn đã cài đặt xong và khởi động mosquitto. Mặc định mosquitto cũng tự khởi động cùng hệ điều hành. Có thể xem trạng thái của mosquitto bằng lệnh
systemctl status mosquitto
Ấn phím Q để trở về cửa sổ lệnh.
Cài đặt trên docker
Ưu điểm của việc cài đặt trên Docker là dễ dàng xoá bỏ, cập nhật hay chạy song song nhiều mosquitto broker khác nhau với nhiều cấu hình khác nhau. Nó cũng giúp tránh làm lộn xộn hệ điều hành của bạn với đủ loại package – phần mềm được cài đặt. Nếu bạn đang sử dụng docker để vận hành nhiều dịch vụ khác, đây là cách tốt hơn.
Cài DockerTrước tiên cần cài đặt docker cho hệ điều hành, bỏ qua nếu đang chạy docker rồi:
#Ubuntu & Raspbian/Armbian sudo apt-get install -y apt-transport-https \ ca-certificates \ curl \ gnupg-agent \ software-properties-common\ avahi-daemon \ dbus \ jq curl -fsSL //get.docker.com -o get-docker.sh && sudo sh ./get-docker.sh && rm get-docker.sh sudo usermod -aG docker `whoami`
Lưu ý sau câu lệnh cuối, cần thoát ra khỏi phiên đăng nhập hiện tại bằng lệnh exit rồi đăng nhập trở lại để thay đổi về group có hiệu lực.
Tạo container mosquittoSau khi hoàn tất, ta tiếp tục tạo container [thuật ngữ trong docker, chỉ môi trường mà ứng dụng sẽ chạy trong đó] mosquitto. Tuy nhiên, trước tiên cần tạo thư mục sẽ chứa cấu hình cũng như toàn bộ dữ liệu – data của mosquitto. Để tăng cường bảo mật, ta sẽ tạo thư mục này bên trong thư mục người dùng hiện tại [~] và ẩn nó khi đặt tên bắt đầu bằng kí tự “.“.
#Ubuntu & Raspbian/Armbian cd ~ mkdir -p .mosquitto/data && cd .mosquitto
Tiếp sau, tạo container có tên mosquitto và mount các thư mục ~/.mosquitto và ~/.mosquitto/data đã tạo ở trên vào container này. Trước đó, cần tải về file cấu hình mẫu mosquitto.conf từ github của eclipse, đơn vị phát triển mosquitto bằng ứng dụng wget.
#Ubuntu & Raspbian/Armbian wget //raw.githubusercontent.com/eclipse/mosquitto/master/mosquitto.conf docker run --name mosquitto -p 1883:1883 -v ~/.mosquitto:/mosquitto/config -v ~/.mosquitto/data:/mosquitto/data --restart unless-stopped eclipse-mosquitto
Trong đó –name là tuỳ chọn đặt tên container, -p là tuỳ chọn map port [nôm na tương tự port forwarding] 1883 của mosquitto sang port 1883 của máy chủ, -v ~/.mosquitto:/mosquitto/config là lệnh mount thư mục ~/.mosquitto vào thư mục /mosquitto/config trong container.
Nếu các lệnh đều thành công, mosquitto broker đã cài đặt và chạy thành công bên trong container có tên mosquitto. Ấn tổ hợp phím Ctrl-C để tạm ngừng container và thoát ra.
Bạn có thể chạy – start, dừng – stop hoặc xoá – rm container này với các lệnh sau, cấu hình hay dữ liệu sẽ không bị mất đi.
#Ubuntu & Raspbian/Armbian docker start mosquitto docker stop mosquitto docker rm mosquittoCập nhật mosquitto trên docker
Các bản cập nhật mosquitto sẽ được phát hành dưới dạng các image mới. Do vậy, để cập nhật, bạn cần pull – tải image mới nhất [latest] về và tạo lại container.
#Ubuntu & Raspbian/Armbian docker pull mosquitto:latest docker stop mosquitto docker rm mosquitto docker run --name mosquitto -p 1883:1883 -v ~/.mosquitto:/mosquitto/config -v ~/.mosquitto/data:/mosquitto/data --restart unless-stopped eclipse-mosquitto
Lệnh docker quá dài? Sử dụng docker compose để tạo và lưu cấu hình một lần duy nhất, tiện cập nhật về sau.
Tường lửa Ubuntu
Hệ điều hành Ubuntu đi kèm ứng dụng tường lửa UFW – Uncomplicated Firewall. Tuy mặc định tường lửa này không được kích hoạt, bạn có thể kiểm tra trạng thái của nó với lệnh sudo ufw status
.
Nếu trạng thái là active hoặc firewall loaded, bạn cần cấu hình UFW mở – allow các cổng cần thiết đối với mosquitto broker. Ví dụ nếu bạn chỉ cấu hình mosquitto sử dụng cổng 1883:
sudo ufw allow 1883 sudo ufw
Home Assistant: kết nối thiết bị Zigbee qua zigbee2mqtt
Kết nối các thiết bị Zigbee vào Hass qua Zigbee2mqtt và module CC2531, thử với Xiaomi Aqara Door Sensor
Home Assistant: MQTT
Giao thức MQTT trong Home Assistant, cấu hình và sửa lỗi
IOT: giao thức MQTT
Cơ bản về giao thức MQTT, tại sao nó hiệu quả với các thiết bị IOT và sơ lược về bảo mật MQTT
Bảo mật Mosquitto Broker
Cấu hình xác thực username/password
Cấu hình mosquitto sử dụng xác thựcCấu hình chính của mosquitto được lưu trong file mosquitto.conf. File này nằm tại:
- /etc/mosquitto/mosquitto.conf nếu bạn cài đặt trực tiếp trên hệ điều hành
- ~/.mosquitto/mosquitto.conf như ta đã tạo và tải về khi cài đặt trong Docker
Ta cần sửa file này để thay đổi một số cài đặt liên quan đến bảo mật.
#OS sudo nano /etc/mosquitto/mosquitto.conf #Docker cd ~/.mosquitto nano mosquitto.conf
Nếu nhận được kết quả nano: command not found, dùng lệnh sudo apt-get install -y nano
để cài đặt nano – trình soạn thảo văn bản trước khi chạy lại các lệnh trên.
File mosquitto.conf có thể rất ngắn hoặc rất dài [như file tải về trên docker], tuy nhiên bạn chỉ cần thêm 2 dòng bên dưới vào cuối file. Sau đó ấn Ctrl-X rồi Y để lưu lại.
#OS allow_anonymous false password_file /etc/mosquitto/passwd #Docker allow_anonymous false password_file /mosquitto/config/passwd
Với lệnh trên, ta cấu hình mosquitto:
- Chỉ cho phép kết nối khi đã xác thực
- Sử dụng nội dung file passwd để xác thực
Ta tiếp tục tạo file passwd hiện chưa có bằng tiện ích mosquitto_passwd đi cùng mosquitto đã cài, thay myuser bằng tên người dùng bạn chọn.
#OS sudo mosquitto_passwd -c /etc/mosquitto/passwd myuser #Docker docker start mosquitto docker exec -it mosquitto mosquitto_passwd -c /mosquitto/config/passwd myuser
Với -c
là tuỳ chọn tạo mới file passwd chưa có, docker exec -it mosquitto
để chạy một lệnh bên trong container mosquitto. Sau khi chạy lệnh tạo file passwd, nhập mật khẩu/xác nhận mật khẩu rồi Enter để hoàn tất.
Khởi động lại mosquitto để tải cấu hình mới. Bạn phải làm điều này mỗi khi thay đổi cấu hình, cập nhật hay thêm username/password.
#OS sudo systemctl restart mosquitto #Docker docker restart mosquitto
Bây giờ bạn có thể sử dụng mqtt client bất kỳ để publish và subscribe vào broker mới.
Thêm, xoá, sửa username/passwordThêm username có tên myuser2
#OS sudo mosquitto_passwd /etc/mosquitto/passwd myuser2 #Docker docker exec -it mosquitto mosquitto_passwd /mosquitto/config/passwd myuser2
Thay đổi password cho username myuser2
#OS sudo mosquitto_passwd -U /etc/mosquitto/passwd myuser2 #Docker docker exec -it mosquitto mosquitto_passwd -U /mosquitto/config/passwd myuser2
Xoá username/password của myuser2
#OS sudo mosquitto_passwd -D /etc/mosquitto/passwd myuser2 #Docker docker exec -it mosquitto mosquitto_passwd -D /mosquitto/config/passwd myuser2
Mosquitto ACL
ACL – Access Control List sử dụng một file cấu hình [acl] để giới hạn/cho phép mỗi username chỉ được subscribe và publish vào một số topic nhất định. ACL không phức tạp nhưng lại hạn chế các quyền truy cập của client rất mạnh [tương tự triết lý “cấm tất cả những gì không quản được“], do vậy bạn phải cẩn trọng chỉ áp dụng khi thật sự cần thiết.
Tạo file aclMosquitto đi kèm với một file aclfile.example mẫu tại /etc/mosquitto/aclfile.example nếu cài trên OS hoặc có thể tải về từ github khi cài trong Docker. Ta sẽ copy/download file này thành một file mới có tên acl.
#OS sudo cp /etc/mosquitto/aclfile.example /etc/mosquitto/acl #Docker cd ~/.mosquitto wget //raw.githubusercontent.com/eclipse/mosquitto/master/aclfile.example -O acl
Nội dung file này như ở dưới, bạn có thể sửa bằng ứng dụng nano tương tự các bước trên.
File này gồm 3 phần – section:
- Phần trên cùng là danh sách topic và quyền [read/write/readwrite] áp dụng cho tất cả client không cung cấp username khi kết nối. Các client này không có quyền đối với mọi topic không liệt kê ở đây hay ở section 3.
Trong cấu hình mẫu thì các client này được cho phép xem thông tin trạng thái của broker. - Phần 2 là danh sách topic mà một client kết nối với username có trong danh sách được phép publish và subcribe. Lưu ý rằng một username/password có thể được sử dụng bởi nhiều client.
- Phần 3 dành cho các client có cung cấp client_id hoặc user_id, cho phép một client được publish/subscribe vào danh sách topic quy định sẵn. Không như username/password, client_id không được phép dùng chung.
Bắt đầu bằng user username, tiếp theo là danh sách các topic mà username này được phép publish & subscribe trên từng dòng riêng. Bạn có thể dùng các topic # và ? để cấp quyền. [xem topic # và ?]
Ví dụ, ở đây ta sẽ cấp quyền cho user tasmota quyền truy cập đến các topic tele/#, cmnd/# và homeassistant/?/switch
# This affects access control for clients with no username. topic read $SYS/# # This only affects clients with username "roger". user tasmota topic tele/# topic cmnd/# topic homeassistant/?/switch # This affects all clients. pattern write $SYS/broker/connection/%c/stateSection 3
Bắt đầu bằng pattern, tiếp theo là quyền read/write/readwrite, cuối cùng là topic. Ngoài các topic # và ?, bạn được sử dụng %c để thay thế cho client_id và %u để thay thế cho user_id.
Ví dụ, ta cấp quyền cho client có id là tasmota_79 quyền readwrite đến mọi topic tele/tasmota_79/# và cmnd/tasmota_79/#
# This affects access control for clients with no username. topic read $SYS/# # This only affects clients with username "roger". user roger topic foo/bar # This affects all clients. pattern readwrite tele/%c/# pattern readwrite cmnd/%c/#Kích hoạt file ACL
Sau khi cấu hình xong file acl, kích hoạt bằng cách khai báo trong file mosquitto.conf rồi khởi động lại mosquitto.
Lần nữa lưu ý các bạn là ACL kiểm soát quyền rất chặt chẽ với phương châm “cấm tất cả những gì không quản được“, do vậy bạn phải cẩn trọng khi kích hoạt nó.
Thêm dòng sau vào cuối file mosquitto.conf [cách làm tương tự bước Cấu hình username/password].
#OS acl_file /etc/mosquitto/acl #Docker acl_file /mosquitto/config/acl
Sau đó khởi động lại mosquitto để áp dụng.
Cảm ơn bạn đã xem bài viết này!
konnectED Team.