👋Giới thiệu
Hi, mình là Quân. Ở bài biết trước, mình đã chia sẻ tới các bạn cách xây dựng một Mqtt Broker trên máy chủ local Ubuntu 22.04, dựa trên Mosquitto (chi tiết bài viết ở đây). Bài viết này mình sẽ chia sẻ cách tích hợp cơ chế xác thực và ủy quyển cho Mosquitto Broker dựa trên gói mosquitto-go-auth, và đưa máy chủ Mqtt Broker lên internet.
🚀Cài đặt
⚠️Yêu cầu đã cài đặt Mosquitto Broker từ phiên bản 2.0 trở lên.
- Cài đặt Go:
$ sudo add-apt-repository ppa:longsleep/golang-backports
$ sudo apt update
$ sudo apt install golang-go
Kiểm tra version golang (phiên bản Go tối thiếu của plugin là 1.18):
$ go version
go version go1.22.5 linux/amd64
- Tải plugin mosquito-go-auth:
$ git clone https://github.com/iegomez/mosquitto-go-auth
$ cd mosquitto-go-auth
- Xây dựng plugin:
ℹ️ Mình giả định các tệp mosquitto.h, mosquitto_plugin.h, mosquitto_broker.h này đã được cài đặt trong thư mục "/usr/include". 💁Trong trường hợp các tệp trên không có sẵn, các bạn có thể tự tải (tại đây) và đặt chúng vào thư mục bạn muốn. Khi đó các bạn hay sửa lại cờ "CFLAGS" trong tệp MakeFile để thay đổi đường dẫn tới thư mục chứa các tệp header:
# Ví dụ
CFLAGS := -I/usr/include -fPIC
Lưu lại tệp MakeFile và gọi make
để xây dựng file go-auth.so
- Liên kế tệp go-auth.so vào Mosquitto:
Copy file go-auth.so vào thư mục "/etc/mosquitto/"
$ sudo cp go-auth.so /etc/mosquitto/
Ở bài viết trước, mình đã tạo file "default.conf" để cấu hình bảo mật cho Mosquitto dựa trên file passwd và acls. Bài viết này mình sẽ thay thế chúng bằng plugin mosquitto-go-auth sử dụng MySQL.
Sửa file /etc/mosquitto/conf.d/default.conf
:
# Cổng kết nối tới Mosquitto Broker
listener 1885 # Liên kết plugin xác thực của Mosquitto tới file go-auth.so
auth_plugin /etc/mosquitto/conf.d/go-auth.so # Cài đặt file để lưu debug log
auth_opt_log_level debug
auth_opt_log_dest file
auth_opt_log_file /var/log/mosquitto/mosquitto.log # Cấu hình kết nối tới MySQL
auth_opt_backends mysql
auth_opt_mysql_host localhost
auth_opt_mysql_port 3306
auth_opt_mysql_user <your_database_username>
auth_opt_mysql_password <your_database_password>
auth_opt_mysql_dbname go_auth_test # Cài đặt các truy vấn để xác thực và ủy quyền người dùng
auth_opt_mysql_userquery SELECT password_hash FROM test_user WHERE (username = ?) limit 1
auth_opt_mysql_superquery SELECT COUNT(*) FROM test_user WHERE (username = ?) AND (is_admin = 1)
auth_opt_mysql_aclquery SELECT topic FROM test_acl INNER JOIN test_user ON test_user.id=test_acl.test_user_id WHERE (username = ?) AND (rw = ? OR rw=3) # Cấu hình hàm băm mật khẩu
auth_opt_hasher bcrypt
auth_opt_hasher_cost 10
Trong đó:
Tùy chọn | Ý nghĩa |
---|---|
auth_opt_mysql_host | Địa chỉ máy chủ MySQL (mặc định là localhost). |
auth_opt_mysql_port | Cổng kết nối tới MySQL (mặc định là 3306). |
auth_opt_mysql_user | Tên người dùng để kết nối tới MySQL. |
auth_opt_mysql_password | Mật khẩu của người dùng MySQL. |
auth_opt_mysql_dbname | Tên Database dùng để lưu trữ dữ liệu. |
auth_opt_mysql_userquery | Truy vấn để lấy mật khẩu băm của người dùng từ bảng test_user dựa trên username. |
auth_opt_mysql_superquery | Truy vấn để kiểm tra xem người dùng có phải là quản trị viên hay không. Nếu người dùng là quản trị viên, người đó có quyền đọc ghi tất cả các chủ đề |
auth_opt_mysql_aclquery | Truy vấn để lấy danh sách các chủ đề (topics) mà người dùng có quyền truy cập. Trong đó rw = 1 (chỉ đọc), rw = 2 (chỉ ghi), rw = 3 (đọc và ghi), đặc biệt rw = 4 (topic đó có thể được đăng kí). Nếu trường này không được chỉ định thì tất cả các user xác thực sẽ có quyền đọc ghi mọi chủ đề. |
- Tiến hành thử nghiệm thôi nào😍:
- Tạo cơ sở sử liệu MySQL mẫu:
CREATE DATABASE go_auth_test;
USE go_auth_test;
- Tạo hai bảng test_user và test_acl để xác thực người dùng và phân quyền truy cập vào các chủ đề dựa theo các câu lệnh truy vấn đã cấu hình:
CREATE TABLE test_user(
id mediumint not null auto_increment,
username varchar(100) not null,
password_hash varchar(200) not null,
is_admin boolean not null,
primary key(id)
);
CREATE TABLE test_acl(
id mediumint not null auto_increment,
test_user_id mediumint not null,
topic varchar(200) not null,
rw int not null,
primary key(id),
foreign key(test_user_id) references test_user(id)
ON DELETE CASCADE
ON UPDATE CASCADE
);
Kết quả:
mysql> SHOW TABLES;
+------------------------+
| Tables_in_go_auth_test |
+------------------------+
| test_acl |
| test_user |
+------------------------+
2 rows in set (0.00 sec)
- Thêm dữ liệu mẫu cho hai bảng:
Tạo người dùng "admin" và "user1", các bạn sử dụng tools để lấy mật khẩu hashed trước khi thêm vào cơ sở dữ liệu :
INSERT INTO test_user VALUES (NULL, "admin", "mật khẩu sau khi hashed", 1);
INSERT INTO test_user VALUES (NULL, "user1", "mật khẩu sau khi hashed", 0);
Thêm các topics mới (user1 trong bảng test_user có id = 2):
INSERT INTO test_acl VALUES (NULL, 2, "sub_topic", 1);
INSERT INTO test_acl VALUES (NULL, 2, "pub_topic", 2);
INSERT INTO test_acl VALUES (NULL, 2, "read_write_topic", 3);
Vì người dùng "admin" có quyền truy cập mọi chủ đề nên mình không test nó nữa.