MQTT-Broker
Wir benötigen einen MQTT-Broker welchen wir per API User, Queues und ACLs füttern können. In diesem Issue geht es um die Auswahl möglicher Broker und kurze Abwägung der Vor-/Nachteile sowie Schätzung wie kompliziert der API-Zugriff ist.
Der Broker muss cluster-fähig sein: eine Instanz lokal auf der Veranstaltung, eine remote im Internet (DoS-Potenzial bzw. unnötigen Traffic über die Internetanbindung der Veranstaltung reduzieren).
Anforderungen:
- Authentifizierung auf Topic-Ebene (ACL)
- Custom User per user/PW oder Cert
- Anlegen/Löschen/sperren von Usern per API/Datei - @runtime
- Readonly auf Topics
- WriteOnly (publish)?
- Für so etwas wie Saal-Pong sicher nicht unwichtig
- Custom User per user/PW oder Cert
- Skalierbar (mind. zwei bridged Cluster (Instanzen) um im Konferenznetz und im Internet anbieten zu können)
- Übertragung von Text und Binärdaten
- Rate Limiting (Per user/Topic)
- Topic-Basiertes Replay von Messages wäre schön
Mögliche Kandidaten
Emitter
Einfacher (skaliertbarer) MQTT-Server für Broadcast Messages.
- Pro
- MQTT (more or less)
- Unterstützt Transportverschlüsselung
- Gut skalierbar
- Kümmert sich im Zweifel selbst um Zertifikate (Let's Encrypt)
- Einfaches Erstellen von Channels mit dedizierten Rechten (s.u.)
- Contra
- Wird seit drei Jahren nicht mehr aktiv weiter entwickelt
- Unterstützt nicht das komplette MQTT Protokoll
RabbitMQ mit MQTT Plugin
RabbitMQ ist unbestritten ein sehr erprobtes Tool.
MQTT wird jedoch nur recht halbherzig per Plugin angebunden und die interne Verarbeitung läuft via AMQP. Bedeuted im Zweifel doppelten Konfigurationsaufwand.
auch wird MQTT nicht vollständig implementiert.
Mosquito
Quasi die Referenziplementierung für MQTT und wahrscheonlich auch der am weitesten verbreitete Broker.
Vorteile:
- Weite Verbreitung
- Sehr performant
- Skalierbar (allerdings mit schmerzen)
- Mehrere Authentifizierungsmethoden
- Auch dynamische Nutzerverwaltung möglich
- Dynamische Authentifizierung via DB
- Auth: https://github.com/iegomez/mosquitto-go-auth#postgresql
- Mit sehr vielen parallelen Messages wird es sehr langsam und es kommt zu Verbindungsabbrüchen
- Auth: https://github.com/iegomez/mosquitto-go-auth#postgresql
Nachteile:
- Etwas Altbacken
- Skalierung ist nur kommerziell verfügbar
HiveMQ
Ist ein teilw. kommerzielles Produkt, welches als Community Edition unter Apache 2 Lizenz verfügbar ist.
Leider sind Features, wie Clustering den Bezahl-Versionen (contact sales) vorbehalten.
ejabberd
Bietet seit 2019 auch MQTT-Support.
Vorteile:
- Ist hoch skalierbar
- Kann Postgres für die Benutzerverwaltung nutzen
Nachteile:
- primärer Einsatzzweck ist eigentlich xmpp
Offene Punkte:
-
Kann der Hub die User direkt in der DB anlegen? See SCRAM -
Ist SCRAM mit SHA512 evt. ein wenig overkill
-
-
MQTT-Skalierung per mod_mqtt_bridge? Seemod_mqtt_bridge -
Cluster Test. See Clustering Should work for MQTT regarding to this bug
ejabberd Config
DB schema: https://github.com/processone/ejabberd/blob/master/sql/pg.new.sql
Working example
###
### ejabberd configuration file
###
### The parameters used in this configuration file are explained at
###
### https://docs.ejabberd.im/admin/configuration
###
###
hosts:
- localhost
loglevel: debug
## If you already have certificates, list them here
# certfiles:
# - /etc/letsencrypt/live/domain.tld/fullchain.pem
# - /etc/letsencrypt/live/domain.tld/privkey.pem
listen:
-
port: 5443
ip: "::"
module: ejabberd_http
tls: true
request_handlers:
/admin: ejabberd_web_admin
/api: mod_http_api
/mqtt: mod_mqtt
-
port: 5280
ip: "::"
module: ejabberd_http
request_handlers:
/admin: ejabberd_web_admin
/.well-known/acme-challenge: ejabberd_acme
/mqtt: mod_mqtt
-
port: 1883
ip: "::"
module: mod_mqtt
backlog: 1000
-
port: 8883
module: mod_mqtt
backlog: 1000
tls: true
s2s_use_starttls: optional
acl:
local:
user_regexp: ""
loopback:
ip:
- 127.0.0.0/8
- ::1/128
access_rules:
local:
allow: local
c2s:
deny: all
allow: admin
announce:
allow: admin
configure:
allow: admin
muc_create:
allow: local
pubsub_createnode:
allow: local
trusted_network:
allow: loopback
api_permissions:
"console commands":
from:
- ejabberd_ctl
who: all
what: "*"
"admin access":
who:
access:
allow:
- acl: loopback
- acl: admin
oauth:
scope: "ejabberd:admin"
access:
allow:
- acl: loopback
- acl: admin
what:
- "*"
- "!stop"
- "!start"
"public commands":
who:
ip: 127.0.0.1/8
what:
- status
- connected_users_number
shaper:
normal:
rate: 3000
burst_size: 20000
fast: 100000
shaper_rules:
max_user_sessions: 10
max_user_offline_messages:
5000: admin
100: all
c2s_shaper:
none: admin
normal: all
s2s_shaper: fast
modules:
#mod_adhoc: {}
mod_admin_extra: {}
mod_fail2ban: {}
mod_http_api: {}
# mod_mqtt: {}
# mod_mqtt_bridge: {} #TODO
auth_password_format: scram
# TODO discuss if sha512 is a bit to much?
auth_scram_hash: sha512
auth_use_cache: true
default_ram_db: mnesia
default_db: sql
sql_type: pgsql
sql_server: localhost
sql_database: ejabberd
sql_username: ejabberd
sql_password: A+27Twp6DTloMzulSw+O2/TYtyS+KJoyS9t8/BlDkho
new_sql_schema: true
auth_method: [sql]
sql_pool_size: 5
include_config_file:
/opt/homebrew/etc/ejabberd/ejabberd.d/acl.yml:
disallow: [listen, modules]
### Local Variables:
### mode: yaml
### End:
### vim: set filetype=yaml tabstop=8
Included ACL File
# ejabberd acl file
append_host_config:
localhost:
acl:
admin:
user:
- rehlein@localhost
- admin@localhost
# ACL_DEF
publish_test1:
user:
- test1@localhost
# /ACL_DEF
modules:
mod_mqtt:
max_topic_depth: 8 # Default is 8
session_expiry: 1 # Default is 5 minutes
use_cache: true
access_publish:
# ACCESS_RULES
"test1/#": # resricted to one user
- allow: publish_test1
- deny
# /ACCESS_RULES
"#":
- allow: admin
- deny
access_subscribe:
# PUBLISH_RULES
"test1/#": # resricted to one user
- allow: publish_test1
- deny
"test1/public":
- allow: all
# /PUBLISH_RULES
"#":
- allow: admin
- deny
This config is proofed on a apply silicon mac using a native installed ejabberd. Next step is to use a docker image instead.
