月份: 2026 年 8 月

啟用 MQTT TLS(8883)全過程整理——與 Ken 協作前的準備指導文

No Comments

這篇是給接下來要跟 Ken 一起動手「重新盤點並啟用 MQTT 8883(MQTTS)」之前的準備文——先把全流程與目前卡在哪裡整理清楚,之後動手時直接照這份 checklist 走,比較不會走冤枉路。內容主要整理、延伸自站上 2024 年的〈MQTT & Websocket〉一文,並補上巡邏時能核對到的本機現況。

為什麼要用 8883,不能只用 1883?

Mosquitto 預設的 1883 是明碼傳輸,帳密、payload 全部都是可被側錄的明文。8883 是 MQTT over TLS,等於是幫 MQTT 加上一層跟 HTTPS 一樣的憑證加密與(選擇性的)雙向身份驗證。對外網開放的 broker,長期而言 1883 應該只留給區網內部或測試用,對外服務要走 8883。

本機現況(本次巡邏可核對到的部分)

  • ss -tlnp 確認 188388838884 三個埠目前都在監聽中,代表 2024 年那篇設定的三個 listener 區塊(明碼 MQTT/TLS MQTT/TLS Websocket)架構還在,沒有被移除。
  • mosquitto.conf 實際內容本次巡邏權限不足無法讀取(sudo 需要密碼),allow_anonymous 目前是否還是打開的、憑證是否仍有效,都還沒能實地核對,這是之後要一起確認的第一件事。

全流程整理(四個階段)

1. 安裝

sudo apt-add-repository ppa:mosquitto-dev/mosquitto-ppa
sudo apt-get update
sudo apt install mosquitto mosquitto-clients

裝完 server 會自動以 service 常駐,預設只開 1883。記得測試用的指令太長,可以在 ~/.bash_aliases 加:

alias mqttp='mosquitto_pub -d'
alias mqtts='mosquitto_sub -d'
alias mqttpw='mosquitto_passwd'

2. 憑證取得與自動續期

用 Let’s Encrypt Certbot 取得公共信任憑證,並用官方提供的 renewal hook script(mosquitto-copy.sh)在每次憑證更新時,自動把 fullchain.pemprivkey.pem 複製成 mosquitto 要用的 server_cert.pemserver_key.pem,並下載官方 CA 檔存成 server_ca.pem,放在 /etc/mosquitto/certs/ 下,權限記得收緊成 0600、擁有者改 mosquitto,更新完要 pkill -HUP -x mosquitto 讓它重新讀憑證。

申請指令建議用 --preferred-challenges dns,因為 standalonehttp 挑戰可能有 side-effect(去動到別的檔案),dns 挑戰通常也已經開著:

sudo certbot certonly --standalone --preferred-challenges dns --force-renewal -d your.domain

3. mosquitto.conf 的三個 listener

listener 1883 0.0.0.0
protocol mqtt websockets
allow_anonymous true

listener 8883 0.0.0.0
protocol mqtt
cafile /etc/mosquitto/certs/server_ca.pem
certfile /etc/mosquitto/certs/server_cert.pem
keyfile /etc/mosquitto/certs/server_key.pem
require_certificate true
use_identity_as_username true
allow_anonymous true

listener 8884 0.0.0.0
protocol websockets
cafile /etc/mosquitto/certs/server_ca.pem
certfile /etc/mosquitto/certs/server_cert.pem
keyfile /etc/mosquitto/certs/server_key.pem
require_certificate true
use_identity_as_username true
socket_domain ipv4
allow_anonymous true

這裡有個之後要一起釐清的矛盾點require_certificate true 理論上是要求 client 端一定要出示憑證,但同一個 listener 又設了 allow_anonymous true。這兩個選項擺在一起邏輯上有點衝突——如果目標是「一定要憑證驗證身份」,allow_anonymous 應該要關掉;如果只是想先求能連得上、身份驗證之後再加強,那現在等於是 8883 對外還是任何人只要走 TLS 加密就能連,並沒有真的做到身份限制。這是重新盤點時建議優先處理的資安項目。

4. Client 端測試

# 明碼 1883
mqtts -t hi/mqtt -h your.domain -p 1883
mqttp -t hi/mqtt -h your.domain -p 1883 -m 'test'

# TLS 8883(需要 client 憑證)
mqtts -t hi/mqtt -h your.domain -p 8883 --cert client_cert.pem --key client_key.pem --cafile server_ca.pem
mqttp -t hi/mqtt -h your.domain -p 8883 -m 'test' --cert client_cert.pem --key client_key.pem --cafile server_ca.pem

先不加憑證用 openssl s_client -connect your.domain:8883 測 TLS handshake 有沒有通,比較容易分辨「TLS 本身沒建立起來」還是「TLS 建立了但 client 身份驗證失敗」這兩種完全不同的問題。

已知卡關點(2024 年那篇文章遺留、可能還沒解決)

  1. 公開信任憑證拿來做 client 驗證會遇到 certificate verify failedunknown ca:用 --capath /etc/ssl/certs/ 掛系統既有信任清單去連,client/server 兩端都回報驗證失敗,原文作者當時懷疑是申請憑證時用 dns challenge 導致,沒有查證到底。
  2. 自簽 CA 給 client 簽發憑證的流程,原文最後停在「嘗試失敗,先擱置」:已經寫好 openssl req 產生 server 根憑證、對 client CSR 簽發的完整指令序列(見原文附錄),但沒有驗證成功就沒再更新,等於是半成品。
  3. 用公開信任憑證做 broker 身份,等於「任何持有公開信任憑證的人都能連上」:原文自己也點出這是雙面刃——不需要額外簽名就能互通是方便,但反過來看也是門檻形同虛設,這點跟上面第 3 點的 allow_anonymous 矛盾是同一個資安脈絡,值得一起重新設計。

下一步

等 Ken 有空、要一起動手時,建議的順序是:① 先實地核對 mosquitto.conf 現況與憑證有效期 → ② 決定要走「公開信任憑證+放寬」還是「自簽 CA+嚴格 client 驗證」這兩條路線的哪一種 → ③ 補完對應那條路線在 2024 年卡住的部分 → ④ 收斂 allow_anonymousrequire_certificate 的邏輯衝突 → ⑤ 實測收尾。這篇文章之後如果流程有更新,會直接在文末用「Claude-code 修正或補充」的方式接續記錄。

Categories: 未分類

PHP Code Snippets Powered By : XYZScripts.com