Cài Mosquitto trên Windows: cấu hình listener, tài khoản mật khẩu, TLS chứng chỉ tự tạo và ESP32

Cài broker MQTT Mosquitto trên Windows: dịch vụ, listener cho mạng nội bộ, mosquitto_passwd, mở tường lửa, TLS với CA tự tạo bằng openssl, thử mosquitto_sub/pub và ESP32 kết nối qua TLS.

Mosquitto là broker MQTT mã nguồn mở nhẹ và phổ biến nhất; cài trên một máy Windows trong nhà là có ngay một máy chủ MQTT riêng cho ESP32, Node-RED, điện thoại, không phụ thuộc broker công cộng. Bài này hướng dẫn cài Mosquitto trên Windows từ bộ cài chính thức, cấu hình cho máy khác kết nối, bắt buộc tài khoản và mật khẩu, bật TLS với chứng chỉ tự tạo, mở tường lửa, thử bằng mosquitto_sub, mosquitto_pub, và chương trình ESP32 kết nối qua TLS.

1. Mô hình: một máy Windows làm broker

Máy Windows 192.168.1.10 chạy dịch vụ Mosquitto với cổng 1883 mạng nội bộ có mật khẩu và 8883 TLS; ESP32 cảm biến và ESP32 relay kết nối TLS; điện thoại và Node-RED kết nối vào broker
Mọi thiết bị trong nhà nói chuyện qua một broker riêng (hình minh họa).

Máy chạy broker nên có IP cố định trong mạng nội bộ (đặt IP tĩnh hoặc giữ IP theo địa chỉ MAC trên router), vì thiết bị kết nối tới broker bằng IP. Khái niệm broker, topic, QoS có ở bài MQTT là gì cùng cụm chủ đề.

2. Cài Mosquitto trên Windows

Bảng sáu bước: tải bộ cài, sửa mosquitto.conf, tạo file mật khẩu, khởi động lại dịch vụ, mở cổng tường lửa, thử bằng mosquitto_sub và mosquitto_pub
Các bước chính.
  1. Tải bộ cài Windows 64 bit ở trang chính thức mosquitto.org (mục Download), chạy với quyền Administrator, để chọn mục Service khi cài. Mosquitto được cài vào C:\Program Files\mosquitto và tạo dịch vụ Windows tên mosquitto.
  2. Thêm thư mục cài đặt vào biến môi trường PATH (hoặc luôn cd vào thư mục đó) để gõ được lệnh mosquitto_sub, mosquitto_pub, mosquitto_passwd trong cửa sổ lệnh.
  3. Tạo thư mục C:\mosquitto để chứa file mật khẩu và chứng chỉ (đường dẫn không có dấu cách cho dễ viết cấu hình).

Từ Mosquitto 2.0, nếu file cấu hình không có dòng listener, broker chỉ nhận kết nối từ chính máy đó (localhost). Đây là lý do hay gặp nhất khiến ESP32 không kết nối được dù dịch vụ đang chạy.

3. Bắt buộc tài khoản và mật khẩu

Mở cửa sổ lệnh bằng Run as administrator, tạo file mật khẩu với tài khoản đầu tiên (lệnh sẽ hỏi mật khẩu hai lần):

cd "C:\Program Files\mosquitto"
mosquitto_passwd -c C:\mosquitto\passwd esp32
mosquitto_passwd C:\mosquitto\passwd nodered      # thêm tài khoản khác, không có -c

Tham số -c tạo file mới và xóa file cũ: chỉ dùng cho tài khoản đầu tiên. Mật khẩu trong file được băm, không lưu dạng chữ. Mở C:\Program Files\mosquitto\mosquitto.conf bằng Notepad chạy quyền Administrator, thêm vào cuối file:

# Cổng 1883 cho mạng nội bộ, bắt buộc đăng nhập
listener 1883
allow_anonymous false
password_file C:\mosquitto\passwd

Khởi động lại dịch vụ: net stop mosquitto rồi net start mosquitto. Nếu dịch vụ không chạy, file cấu hình có lỗi: chạy tay mosquitto -c mosquitto.conf -v trong thư mục cài đặt để xem dòng báo lỗi.

4. Mở cổng trong tường lửa Windows

Tường lửa Windows chặn kết nối vào mặc định. Mở cổng cho mạng riêng (Private) bằng PowerShell chạy quyền Administrator:

New-NetFirewallRule -DisplayName "Mosquitto MQTT" -Direction Inbound -Protocol TCP -LocalPort 1883,8883 -Action Allow -Profile Private

Kiểm tra mạng Wi-Fi của máy đang ở chế độ Private (Settings → Network → Properties). Không mở cổng MQTT ra Internet qua router: muốn truy cập từ xa, dùng VPN hoặc broker có TLS và mật khẩu mạnh.

5. Bật TLS với chứng chỉ tự tạo

Sơ đồ TLS: CA tự tạo ký chứng chỉ máy chủ có SAN IP 192.168.1.10; Mosquitto dùng cafile, certfile, keyfile ở listener 8883; ESP32 dùng setCACert với ca.crt để kiểm tra máy chủ
Thiết bị chỉ cần ca.crt để tin broker (hình minh họa).

Cổng 1883 gửi mật khẩu dạng chữ trên mạng; TLS mã hóa toàn bộ kết nối. Tạo một CA riêng rồi dùng nó ký chứng chỉ cho broker, bằng lệnh openssl (có sẵn trong Git for Windows, mở Git Bash). Thay 192.168.1.10 bằng IP máy Windows:

openssl req -new -x509 -days 3650 -keyout ca.key -out ca.crt -subj "/CN=PYWORLD MQTT CA"
openssl genrsa -out server.key 2048
openssl req -new -key server.key -out server.csr -subj "/CN=192.168.1.10"
echo "subjectAltName=IP:192.168.1.10" > san.txt
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 825 -extfile san.txt

Lệnh đầu hỏi mật khẩu để bảo vệ ca.key: giữ kín file này, chỉ cần khi ký chứng chỉ mới. Chép ca.crt, server.crt, server.key vào C:\mosquitto\certs và thêm vào mosquitto.conf:

# Cổng 8883 có TLS, dùng chung tài khoản ở trên
listener 8883
cafile C:\mosquitto\certs\ca.crt
certfile C:\mosquitto\certs\server.crt
keyfile C:\mosquitto\certs\server.key

Dòng subjectAltName ghi IP của máy chủ vào chứng chỉ: máy khách kiểm tra chứng chỉ có đúng địa chỉ nó đang kết nối không. IP máy chủ đổi thì phải ký lại chứng chỉ.

6. Thử bằng mosquitto_sub, mosquitto_pub

Trên một máy khác trong mạng (cũng cài Mosquitto, hoặc dùng ứng dụng MQTT Explorer), chép ca.crt sang rồi chạy:

mosquitto_sub -h 192.168.1.10 -p 8883 --cafile ca.crt -u esp32 -P MAT_KHAU -t "pyworld/#" -v
mosquitto_pub -h 192.168.1.10 -p 8883 --cafile ca.crt -u esp32 -P MAT_KHAU -t pyworld/thu/lenh -m "xin chao"

Thử cổng 1883 thì bỏ -p 8883 --cafile ca.crt. Thử sai mật khẩu để chắc chắn broker từ chối.

7. ESP32 kết nối broker qua TLS

Chương trình dùng WiFiClientSecure của gói esp32 và thư viện PubSubClient (Library Manager). Mở ca.crt bằng Notepad, chép toàn bộ nội dung vào biến CA_CERT.

// PYWORLD.VN - ESP32 kết nối broker Mosquitto cài trên máy Windows qua TLS (cổng 8883), có tài khoản và mật khẩu
// PYWORLD.VN - Dán nội dung file ca.crt (chứng chỉ CA tự tạo) vào CA_CERT; chứng chỉ máy chủ phải ghi đúng IP trong MAY_CHU
// PYWORLD.VN - Thay TEN_WIFI, MAT_KHAU_WIFI, MAT_KHAU_MQTT; mỗi 5 giây gửi bộ đếm lên topic pyworld/thu/esp32

#include <WiFi.h>
#include <WiFiClientSecure.h>
#include <PubSubClient.h>

const char *TEN_WIFI = "TEN_WIFI";
const char *MAT_KHAU_WIFI = "MAT_KHAU_WIFI";
const char *MAY_CHU = "192.168.1.10";       // IP máy Windows chạy Mosquitto
const uint16_t CONG_TLS = 8883;
const char *TAI_KHOAN = "esp32";
const char *MAT_KHAU_MQTT = "MAT_KHAU_MQTT";
const char *TOPIC = "pyworld/thu/esp32";

// Mở ca.crt bằng Notepad, chép toàn bộ (kể cả hai dòng BEGIN, END) vào giữa hai dấu ngoặc
const char *CA_CERT = R"EOF(
-----BEGIN CERTIFICATE-----
DAN_NOI_DUNG_FILE_CA_CRT_VAO_DAY
-----END CERTIFICATE-----
)EOF";

WiFiClientSecure mangTls;
PubSubClient mqtt(mangTls);
uint32_t dem = 0;
uint32_t lanGui = 0;

void khiCoTin(char *topic, byte *duLieu, unsigned int doDai) {
  Serial.printf("Nhan [%s]: %.*s\n", topic, (int)doDai, (const char *)duLieu);
}

void ketNoi() {
  while (!mqtt.connected()) {
    Serial.print("Ket noi TLS toi broker... ");
    if (mqtt.connect("esp32-tls-01", TAI_KHOAN, MAT_KHAU_MQTT)) {
      Serial.println("xong");
      mqtt.subscribe("pyworld/thu/lenh");
    } else {
      // -2: không mở được TLS (sai IP, cổng, chứng chỉ); 4: sai tài khoản, mật khẩu; 5: không được phép
      Serial.printf("loi %d\n", mqtt.state());
      char loi[100];
      if (mangTls.lastError(loi, sizeof(loi)) != 0) {
        Serial.printf("  TLS: %s\n", loi);
      }
      delay(5000);
    }
  }
}

void setup() {
  Serial.begin(115200);
  WiFi.begin(TEN_WIFI, MAT_KHAU_WIFI);
  while (WiFi.status() != WL_CONNECTED) {
    delay(300);
  }
  Serial.printf("Wi-Fi: %s\n", WiFi.localIP().toString().c_str());
  mangTls.setCACert(CA_CERT);                 // chỉ tin broker có chứng chỉ do CA này ký
  mqtt.setServer(MAY_CHU, CONG_TLS);
  mqtt.setCallback(khiCoTin);
}

void loop() {
  if (!mqtt.connected()) {
    ketNoi();
  }
  mqtt.loop();
  if (millis() - lanGui >= 5000) {
    lanGui = millis();
    dem = dem + 1;
    char chuoi[24];
    snprintf(chuoi, sizeof(chuoi), "dem %lu", (unsigned long)dem);
    mqtt.publish(TOPIC, chuoi);
    Serial.printf("Gui [%s]: %s\n", TOPIC, chuoi);
  }
}
Serial Monitor: Wi-Fi 192.168.1.37, kết nối TLS tới broker xong, gửi đếm 1, 2, 3 lên pyworld/thu/esp32, nhận xin chao từ pyworld/thu/lenh
Kết quả mong đợi (hình minh họa).

Kết nối TLS tốn bộ nhớ và mất khoảng một giây cho lần bắt tay đầu; PubSubClient giữ kết nối lâu dài nên chỉ tốn một lần. Ví dụ MQTT không TLS và điều khiển relay có ở bài MQTT với ESP32 bằng PubSubClient.

8. Lỗi hay gặp

Bảng lỗi: dịch vụ không khởi động do lỗi cấu hình; máy khác không kết nối được do thiếu listener hoặc tường lửa; not authorised do sai mật khẩu; ESP32 state -2 khi dùng TLS do sai chứng chỉ hoặc IP; mosquitto_passwd không mở được file do thiếu quyền Administrator
Đọc lỗi bằng chế độ -v của Mosquitto.

9. Xem thêm


Tin tức liên quan

Đồng hồ và dự báo thời tiết trên OLED: ESP32 lấy dữ liệu Open-Meteo qua HTTP API
Đồng hồ và dự báo thời tiết trên OLED: ESP32 lấy dữ liệu Open-Meteo qua HTTP API

ESP32 lấy giờ NTP và thời tiết Open-Meteo qua HTTPS mỗi 15 phút, đọc JSON bằng ArduinoJson, hiện nhiệt độ, độ ẩm, gió và dự báo 3 ngày trên OLED 0.96 inch.

Đo tốc độ động cơ bằng encoder và bộ đếm xung PCNT của ESP32: vòng/phút và số vòng
Đo tốc độ động cơ bằng encoder và bộ đếm xung PCNT của ESP32: vòng/phút và số vòng

Hướng dẫn đọc encoder Hall hai kênh của động cơ DC bằng bộ đếm xung PCNT của ESP32: đếm 4 cạnh, tính vòng/phút và số vòng, lập bảng tốc độ theo duty trong giờ học STEM.

Nhà kính mini với ESP32: đo nhiệt độ, độ ẩm đất, ánh sáng; tự tưới, bật quạt, đèn trồng cây
Nhà kính mini với ESP32: đo nhiệt độ, độ ẩm đất, ánh sáng; tự tưới, bật quạt, đèn trồng cây

Làm nhà kính mini với ESP32: DHT22, cảm biến độ ẩm đất, quang trở; relay điều khiển bơm, quạt, đèn trồng cây 12 V có khoảng trễ, tưới từng đợt, hạn mức bơm, trang web tự động và bằng tay.

ESP32-CAM là gì: sơ đồ chân, cách nạp code, xem video trên trình duyệt, chụp ảnh lưu thẻ nhớ
ESP32-CAM là gì: sơ đồ chân, cách nạp code, xem video trên trình duyệt, chụp ảnh lưu thẻ nhớ

Giới thiệu mạch ESP32-CAM AI Thinker, sơ đồ chân, nạp code bằng đế MB hoặc USB-TTL, chương trình xem video MJPEG trên trình duyệt, chụp ảnh có đèn flash và lưu vào thẻ microSD.

Hướng dẫn ESP32 điều khiển module relay 4 kênh an toàn
Hướng dẫn ESP32 điều khiển module relay 4 kênh an toàn

Hướng dẫn ESP32 điều khiển relay 4 kênh: chọn GPIO an toàn, cấp nguồn 5 V phù hợp, xác định active LOW và lưu ý khi đóng cắt tải.

Hướng dẫn dùng Deep Sleep trên ESP32: tiết kiệm pin, đánh thức bằng timer và nút nhấn
Hướng dẫn dùng Deep Sleep trên ESP32: tiết kiệm pin, đánh thức bằng timer và nút nhấn

Hướng dẫn đưa ESP32 vào Deep Sleep trên Arduino IDE để tiết kiệm pin: các chế độ nguồn, đánh thức bằng timer và nút nhấn, giữ biến trong bộ nhớ RTC và ước tính thời lượng pin.

Phased array siêu âm 40 kHz với ESP32 (phần 2): mạch đệm 12 V, đầu thu và quét búp sóng
Phased array siêu âm 40 kHz với ESP32 (phần 2): mạch đệm 12 V, đầu thu và quét búp sóng

Phần 2 của loạt phased array siêu âm: thêm mạch đệm 12 V bằng hai module L298N, lắp mạch thu dùng LM358, đo biên độ 40 kHz bằng ADC của ESP32 và chạy chương trình tự quét góc lái để xem búp sóng.

Bãi giữ xe thông minh: đếm chỗ trống bằng cảm biến và ESP32
Bãi giữ xe thông minh: đếm chỗ trống bằng cảm biến và ESP32

Làm bãi giữ xe thông minh mẫu: ESP32 đọc cảm biến siêu âm từng ô, lọc người đi ngang, gửi ESP-NOW về trạm OLED, mô phỏng chọn thời gian lọc, so sánh với đếm ở cổng.


Bình luận
Đã thêm vào giỏ hàng