MQTTでIoT通信(5)MosquittoでPSK認証

 MQTTでIoT通信するのに、平文というわけには以下なので、取りあえずの暗号化、本番だと、公開鍵暗号を使った相互認証がいいのであろうが、照明をの作成とか結構面倒くさいので取りあえず、試験的に使うので、共通鍵暗号を使ったPSKで構築することにした。

PSKなので、共有鍵がもれるとアウトなので注意が必要です。

まずはサーバー側のMosquittoの設定

まずPSKの設定を記述する

/etc/mosquitto/pskfile の作成

openssl rand -hex 32

でランダムな16進数の32バイトの文字列を生成する 。例えば以下のような

a1b2c3d4e5f67890abcdef1234567890

この文字列とクライアントを識別する識別子を /etc/mosquitto/pskfile に格納する。 デバイスごとにパス輪変えてもいいし、取りあえず一緒でもいい。


esp01:a1b2c3d4e5f67890abcdef1234567890
esp02:a1b2c3d4e5f67890abcdef1234567890

 /etc/mosquitto/pskfile の所有者と、アクセス権を変更する。

sudo chown mosquitto:mosquitto /etc/mosquitto/pskfile
sudo chmod 0600 /etc/mosquitto/pskfile

/etc/mosquitto/mosquitto.conf の編集

pid_file /run/mosquitto/mosquitto.pid

persistence true
persistence_location /var/lib/mosquitto/

log_dest file /var/log/mosquitto/mosquitto.log

include_dir /etc/mosquitto/conf.d

 だっけ設定されているのだが、以下を追加

# 暗号化通信用のポートを指定
listener 8883
# PSK通信用のヒント文字列(クライアントに通知する任意の文字列)
psk_hint my_mqtt_broker_hint
# 作成したPSKファイルのパスを指定
psk_file /etc/mosquitto/pskfile
# (推奨)PSKの識別子(Identity)をそのままMQTTのユーザー名として扱う場合
use_identity_as_username true

 mosquitto の再起動

sudo systemctl restart mosquitto 

コマンドの送信テスト

mosquitto_sub -h localhost -p 8883 --psk-identity esp01 --psk a1b2c3d4e5f67890abcdef1234567890 -t /client/m1 -m "tmp:32.12"


その前に


の時に設定した設定だと logger.py がそのままだと使えない。特にRaspberry Piの Paho MQTT ライブラリのバージョンが古いバージョン 1.x 系のためPSK通信がうまく動かない。

/usr/local/bin/logger.py を編集

import sys
import os

# --- 設定 ---
LOG_DIR = "/dev/shm/mqtt"
LOG_FILE_pre = LOG_DIR + "/mqtt-data-" # 保存ファイル名の接頭部分

# 【追加】ディレクトリが存在しない場合は作成し、権限を 777 に設定
if not os.path.exists(LOG_DIR):
    os.makedirs(LOG_DIR, exist_ok=True)
    os.chmod(LOG_DIR, 0o777) # 誰でも読み書き・アクセスできるように設定

print("Running... Waiting for data from pipe...")

# 標準入力(パイプ)から1行ずつリアルタイムに読み込む
for line in sys.stdin:
    try:
        # 改行を削除して「トピック メッセージ」に分解
        line = line.strip()
        if not line or " " not in line:
            continue
            
        topic, payload = line.split(" ", 1)

        # トピックスのデータの処理
        myTOPIC = topic.split('/')     # myTOPIC[0]がsensorで[1]がマシン名
        # ペイロードのデータの処理
        mydata = payload.split(':')    # mydata[0] = tmp  mydata[1]が温度になるはず 

        LOG_FILE = LOG_FILE_pre + myTOPIC[1] + '-' + mydata[0] + ".txt"

        # ファイルに上書き保存
        with open(LOG_FILE, "w", encoding="utf-8") as f:
            f.write(mydata[1] + "\n")

        # 【追加】書き込んだファイルのアクセス権を 666 に変更
        os.chmod(LOG_FILE, 0o666)

        print(f"Saved: {topic} -> {payload}")
        
    except Exception as e:
        # フォーマット違いなどのエラーはログを出してスキップ
        print(f"Error: {e}", file=sys.stderr)
        continue

 /usr/local/bin/mqtt-logger.service の編集

[Unit]
Description=MQTT TLS-PSK Logger Service
After=mosquitto.service
Wants=mosquitto.service

[Service]
Type=simple
# パイプ(|)を使うコマンドをサービスにするため、/bin/bash -c を噛ませます
ExecStart=/bin/bash -c '/usr/bin/mosquitto_sub -h localhost -p 8883 --psk-identity esp01 --psk a1b2c3d4e5f67890abcdef1234567890 -t "#" -v | /usr/bin/python3 /usr/local/bin/logger.py'
Restart=always
RestartSec=5
User=root

[Install]
WantedBy=multi-user.target

sudo systemctl daemon-reload
sudo systemctl enable mqtt-logger.service
sudo systemctl start mqtt-logger.service
systemctl status mqtt-logger.service
実行。

で動くようになった、次はESP32の方か

コメント