TLS-Unterstuetzung fuer MQTT
MqttBridge(ssl=True) / mqtt_config.SSL: umqtt.simple.MQTTClient wird mit
ssl_params={"server_hostname": ..., "cert_reqs": CERT_NONE} aufgebaut --
SNI fuer virtuelle Hosts hinter einem Reverse-Proxy, aber ohne
Zertifikatspruefung (kein CA-Bundle auf dem Geraet). Verschluesselt die
Zugangsdaten auf der Leitung, schuetzt aber nicht vor einem aktiven
Man-in-the-Middle.
Anlass: Der Broker wechselte auf einen Host, der nur noch TLS anbot --
Klartext gegen den TLS-Port endete in ECONNRESET.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017zTSXLK4w32PoCmFgSzp68
This commit is contained in:
@@ -31,6 +31,10 @@ kehrt es sofort zurueck.
|
||||
|
||||
Ohne mqtt_config.py (oder ohne umqtt) gibt connect_from_config() None zurueck --
|
||||
die Anzeige laeuft dann ohne MQTT weiter.
|
||||
|
||||
TLS (mqtt_config.SSL = True, ueblicherweise mit PORT = 8883): Serverzertifikat
|
||||
wird NICHT geprueft (kein CA-Bundle auf dem Geraet) -- schuetzt die Zugangsdaten
|
||||
auf der Leitung, nicht vor einem aktiven Man-in-the-Middle. Siehe _neuer_client.
|
||||
"""
|
||||
|
||||
import settings
|
||||
@@ -61,7 +65,8 @@ class MqttBridge:
|
||||
|
||||
def __init__(self, broker=None, port=1883, user="", password="",
|
||||
prefix="grossanzeige", client_id="grossanzeige",
|
||||
client=None, log=None, on_change=None, on_ota=None):
|
||||
client=None, log=None, on_change=None, on_ota=None,
|
||||
ssl=False):
|
||||
self._broker = broker
|
||||
self._port = port
|
||||
self._user = user
|
||||
@@ -72,6 +77,7 @@ class MqttBridge:
|
||||
self._log = log or (lambda *a: None)
|
||||
self._on_change = on_change # wird nach jeder Aenderung gerufen
|
||||
self._on_ota = on_ota # wird bei cmd/ota gerufen (Payload = URL)
|
||||
self._ssl = ssl
|
||||
|
||||
self.connected = False
|
||||
self._retry = RETRY_START
|
||||
@@ -92,10 +98,20 @@ class MqttBridge:
|
||||
def _neuer_client(self):
|
||||
if MQTTClient is None:
|
||||
raise OSError("umqtt.simple nicht verfuegbar")
|
||||
return MQTTClient(self._client_id, self._broker, port=self._port,
|
||||
user=self._user or None,
|
||||
password=self._password or None,
|
||||
keepalive=60)
|
||||
kwargs = dict(port=self._port, user=self._user or None,
|
||||
password=self._password or None, keepalive=60)
|
||||
if self._ssl:
|
||||
# server_hostname fuers SNI -- ohne das weisen manche TLS-Server
|
||||
# (virtuelle Hosts hinter einem Reverse-Proxy) die Verbindung ab.
|
||||
# CERT_NONE, weil auf dem Geraet kein CA-Bundle liegt: die Leitung
|
||||
# ist verschluesselt, aber ein aktiver Man-in-the-Middle waere
|
||||
# nicht nachweisbar. Reicht fuer den hiesigen Zweck (Zugangsdaten
|
||||
# nicht im Klartext), ist aber keine volle Zertifikatspruefung.
|
||||
import ssl as _ssl
|
||||
kwargs["ssl"] = True
|
||||
kwargs["ssl_params"] = {"server_hostname": self._broker,
|
||||
"cert_reqs": _ssl.CERT_NONE}
|
||||
return MQTTClient(self._client_id, self._broker, **kwargs)
|
||||
|
||||
def connect(self):
|
||||
"""Verbinden, Set-Topics abonnieren, online melden.
|
||||
@@ -288,6 +304,7 @@ def connect_from_config(log=None, on_change=None, on_ota=None):
|
||||
log=log,
|
||||
on_change=on_change,
|
||||
on_ota=on_ota,
|
||||
ssl=getattr(mqtt_config, "SSL", False),
|
||||
)
|
||||
bridge.connect() # scheitert es, versucht check() es spaeter erneut
|
||||
return bridge
|
||||
|
||||
Reference in New Issue
Block a user