BLOG | NGINX

Optimieren von MQTT-Bereitstellungen in Unternehmensumgebungen mit NGINX Plus

NGINX-Teil-von-F5-horiz-schwarz-Typ-RGB
Michael Vernik Miniaturbild
Michael Vernik
Veröffentlicht am 05. Juni 2023
Prabhat Dixit Miniaturbild
Prabhat Dixit
Veröffentlicht am 05. Juni 2023

Bei der Ankündigung der R29-Version von NGINX Plus haben wir kurz auf die neue native Unterstützung für die Analyse von MQTT- Nachrichten eingegangen. In diesem Beitrag bauen wir darauf auf und besprechen, wie NGINX Plus konfiguriert werden kann, um MQTT-Bereitstellungen in Unternehmensumgebungen zu optimieren.

Was ist MQTT?

MQTT steht für Message Queuing Telemetry Transport . Es handelt sich um ein sehr beliebtes, leichtes Publish-Subscribe-Messaging-Protokoll, das sich ideal für die Verbindung von Internet of Things (IoT)- oder Machine-to-Machine (M2M)-Geräten und -Anwendungen über das Internet eignet. MQTT ist für den effizienten Betrieb in Umgebungen mit geringer Bandbreite oder geringem Stromverbrauch konzipiert und ist daher die ideale Wahl für Anwendungen mit einer großen Anzahl von Remote-Clients. Es wird in zahlreichen Branchen eingesetzt, unter anderem in der Unterhaltungselektronik, der Automobilindustrie, im Transportwesen, in der Fertigung und im Gesundheitswesen.

NGINX Plus MQTT-Nachrichtenverarbeitung

NGINX Plus R29 unterstützt MQTT 3.1.1 und MQTT 5.0 . Es fungiert als Proxy zwischen Clients und Brokern, entlastet Kernsysteme von Aufgaben, vereinfacht die Skalierbarkeit und senkt die Rechenkosten. Insbesondere analysiert und schreibt NGINX Plus Teile von MQTT CONNECT -Nachrichten neu und ermöglicht so Funktionen wie:

  • Lastenausgleich für MQTT-Broker 
  • Sitzungspersistenz (Erneutes Verbinden von Clients mit demselben Broker) 
  • SSL/TLS-Terminierung 
  • Client-Zertifikatauthentifizierung 

Anweisungen zur MQTT-Nachrichtenverarbeitung müssen im Stream- Kontext einer NGINX-Konfigurationsdatei definiert werden und werden vom Modul ngx_stream_mqtt_preread_module bereitgestellt.
und ngx_stream_mqtt_filter_module .

Das Preread- Modul verarbeitet MQTT-Daten vor dem internen Proxying von NGINX und ermöglicht so die Lastverteilung und Upstream-Routing-Entscheidungen auf Grundlage der analysierten Nachrichtendaten.

Das Filtermodul ermöglicht das Umschreiben der Felder „Client-ID“ , „Benutzername“ und „ Passwort“ in empfangenen CONNECT-Nachrichten. Die Möglichkeit, diese Felder auf Variablen und komplexe Werte festzulegen, erweitert die Konfigurationsoptionen erheblich und ermöglicht es NGINX Plus, vertrauliche Geräteinformationen zu maskieren oder Daten wie einen eindeutigen Namen eines TLS-Zertifikats einzufügen.

MQTT-Direktiven und -Variablen

Zum Optimieren Ihrer NGINX-Konfiguration zur Optimierung der MQTT-Bereitstellungen und Erfüllung Ihrer spezifischen Anforderungen stehen jetzt mehrere neue Anweisungen und eingebettete Variablen zur Verfügung.

Vorab lesen von Modulanweisungen und eingebetteten Variablen

  • mqtt_preread – Aktiviert die MQTT-Analyse und extrahiert die Client-ID- und Benutzernamenfelder aus CONNECT-Nachrichten, die von Clientgeräten gesendet werden. Diese Werte werden über eingebettete Variablen verfügbar gemacht und unterstützen Hash-Sitzungen beim Lastenausgleich von Upstream-Servern (Beispiele unten).
  • $mqtt_preread_clientid – Stellt die vom Gerät gesendete MQTT-Clientkennung dar.
  • $mqtt_preread_username – Stellt den vom Client zu Authentifizierungszwecken gesendeten Benutzernamen dar.

Filtermodul-Direktiven

  • mqtt – Definiert, ob MQTT-Umschreiben aktiviert ist.
  • mqtt_buffers – Überschreibt die maximale Anzahl von MQTT-Verarbeitungspuffern, die pro Verbindung zugewiesen werden können, und die Größe jedes Puffers. Standardmäßig legt NGINX ein Limit von 100 Puffern pro Verbindung mit einer Länge von jeweils 1 KB fest. Dies ist normalerweise optimal für die Leistung, in besonderen Situationen kann jedoch eine Feinabstimmung erforderlich sein. Beispielsweise erfordern längere MQTT-Nachrichten eine größere Puffergröße. Systeme, die innerhalb kurzer Zeit eine größere Menge an MQTT-Nachrichten für eine bestimmte Verbindung verarbeiten, können von einer größeren Anzahl von Puffern profitieren. In den meisten Fällen hat die Anpassung der Pufferparameter wenig Einfluss auf die Leistung des zugrunde liegenden Systems, da NGINX Puffer aus einem internen Speicherpool erstellt.
  • mqtt_rewrite_buffer_size – Gibt die Größe des Puffers an, der zum Erstellen von MQTT-Nachrichten verwendet wird. Diese Anweisung ist veraltet und seit NGINX Plus R30 obsolet.
  • mqtt_set_connect – Schreibt Parameter der von einem Client gesendeten CONNECT-Nachricht neu. Zu den unterstützten Parametern gehören: Client-ID , Benutzername und Passwort .

MQTT Beispiele

Lassen Sie uns die Vorteile der Verarbeitung von MQTT-Nachrichten mit NGINX Plus und die damit verbundenen Best Practices genauer untersuchen. Beachten Sie, dass wir in den folgenden Beispielen die Ports 1883 und 8883 verwenden. Port 1883 ist der standardmäßige ungesicherte MQTT-Port, während 8883 der standardmäßige SSL/TLS-verschlüsselte Port ist.

MQTT-Broker-Lastausgleich

Die kurzlebige Natur von MQTT-Geräten kann dazu führen, dass sich Client-IPs unerwartet ändern. Dies kann zu Problemen bei der Weiterleitung von Geräteverbindungen an den richtigen Upstream-Broker führen. Die anschließende Verschiebung von Geräteverbindungen von einem Upstream-Broker zu einem anderen kann zu aufwendigen Synchronisierungsvorgängen zwischen den Brokern führen und so zu zusätzlichen Latenzen und Kosten führen.

Durch Analysieren des Client-ID -Felds in einer MQTT CONNECT-Nachricht kann NGINX Sticky Sessions zu Upstream-Service-Brokern herstellen. Dies wird erreicht, indem die Client-ID als Hash-Schlüssel zum Aufrechterhalten der Verbindungen zu Broker-Diensten im Backend verwendet wird.

In diesem Beispiel übermitteln wir MQTT-Gerätedaten per Proxy, indem wir die Client-ID als Token zum Herstellen von Sticky Sessions mit drei Upstream-Brokern verwenden. Wir verwenden den konsistenten Parameter, damit bei einem Ausfall eines Upstream-Servers sein Anteil des Datenverkehrs gleichmäßig auf die verbleibenden Server verteilt wird, ohne die auf diesen Servern bereits hergestellten Sitzungen zu beeinträchtigen.

stream {     mqtt_preread ein; 
   
    Upstream-Backend {
        Zone TCP_Mem 64k;
        Hash $mqtt_preread_clientid konsistent;
  
        Server 10.0.0.7:1883; # Upstream-MQTT-Broker 1
        Server 10.0.0.8:1883; # Upstream-MQTT-Broker 2
        Server 10.0.0.9:1883; # Upstream-MQTT-Broker 3 
    }
  
    Server {
        hören 1883;
        Proxy-Pass-Backend;
        Proxy-Connect-Timeout 1 s;
    }
}

NGINX Plus kann auch das Benutzernamenfeld einer MQTT CONNECT-Nachricht analysieren. Weitere Einzelheiten finden Sie in der ngx_stream_mqtt_preread_module -Spezifikation

SSL/TLS-Terminierung

Die Verschlüsselung der Gerätekommunikation ist der Schlüssel zur Gewährleistung der Datenvertraulichkeit und zum Schutz vor Man-In-The-Middle-Angriffen. Allerdings können TLS-Handshake, Verschlüsselung und Entschlüsselung eine Ressourcenbelastung für einen MQTT-Broker darstellen. Um dieses Problem zu lösen, kann NGINX Plus die Datenverschlüsselung von einem Broker (oder einem Broker-Cluster) auslagern, wodurch die Sicherheitsregeln vereinfacht werden und Broker sich auf die Verarbeitung von Gerätenachrichten konzentrieren können. 

In diesem Beispiel zeigen wir, wie NGINX verwendet werden kann, um TLS-verschlüsselten MQTT-Verkehr von Geräten an einen Backend-Broker weiterzuleiten. Die Direktive ssl_session_cache definiert einen 5-Megabyte-Cache, der ausreicht, um ungefähr 20.000 SSL-Sitzungen zu speichern. NGINX versucht gemäß der Direktive „proxy_connect_timeout“ fünf Sekunden lang, den Proxy-Broker zu erreichen, bevor es zu einer Zeitüberschreitung kommt.

stream {     server {
        abhören 8883 ssl;
        SSL-Zertifikat /etc/nginx/certs/tls-cert.crt;
        SSL-Zertifikatsschlüssel /etc/nginx/certs/tls-key.key;
        SSL-Session-Cache gemeinsam genutzt: SSL: 5 m;
        Proxy-Passwort 10.0.0.8:1883;
        Proxy-Verbindungstimeout 5 s;
    }
} 

Client-ID-Ersetzung

Aus Sicherheitsgründen können Sie sich dafür entscheiden, keine kundenidentifizierbaren Informationen in der Datenbank des MQTT-Brokers zu speichern. Beispielsweise kann ein Gerät eine Seriennummer oder andere vertrauliche Daten als Teil einer MQTT CONNECT-Nachricht senden. Durch Ersetzen der Kennung eines Geräts durch andere bekannte statische Werte, die von einem Client empfangen wurden, kann für jedes Gerät, das versucht, Proxy-Broker von NGINX Plus zu erreichen, ein alternativer eindeutiger Schlüssel erstellt werden.

In diesem Beispiel extrahieren wir eine eindeutige Kennung aus dem Client-SSL-Zertifikat eines Geräts und verwenden sie, um dessen MQTT-Client-ID zu maskieren. Die Client-Zertifikatauthentifizierung (gegenseitiges TLS) wird mit der Direktive ssl_verify_client gesteuert. Wenn der Parameter auf „on“ gesetzt ist, stellt NGINX sicher, dass Client-Zertifikate von einer vertrauenswürdigen Zertifizierungsstelle (CA) signiert sind. Die Liste der vertrauenswürdigen CA-Zertifikate wird durch die Direktive ssl_client_certificate definiert. 

stream {     mqtt on; 
  
    server {
        listen 8883 ssl;
        ssl_certificate /etc/nginx/certs/tls-cert.crt;
        ssl_certificate_key /etc/nginx/certs/tls-key.key;
        ssl_client_certificate /etc/nginx/certs/client-ca.crt;
        ssl_session_cache shared:SSL:10m;
       ssl_verify_client ein;
        proxy_pass 10.0.0.8:1883;
        proxy_connect_timeout 1s;
        
        mqtt_set_connect Client-ID $ssl_client_serial;
    }
}

Client-Zertifikat als Authentifizierungsnachweis

Ein gängiger Ansatz zur Authentifizierung von MQTT-Clients besteht darin, in einem Client-Zertifikat gespeicherte Daten als Benutzernamen zu verwenden. NGINX Plus kann Client-Zertifikate analysieren und das MQTT-Benutzernamenfeld neu schreiben, wodurch diese Aufgabe von Backend-Brokern übernommen wird. Im folgenden Beispiel extrahieren wir den Subject Distinguished Name (Subject DN) des Client-Zertifikats und kopieren ihn in den Benutzernamenteil einer MQTT CONNECT-Nachricht.

stream {     mqtt on; 
   
    server {
        listen 8883 ssl;
        ssl_certificate /etc/nginx/certs/tls-cert.crt;
        ssl_certificate_key /etc/nginx/certs/tls-key.key;
        ssl_client_certificate /etc/nginx/certs/client-ca.crt;
        ssl_session_cache shared:SSL:10m;
       ssl_verify_client ein;
        proxy_pass 10.0.0.8:1883;
        proxy_connect_timeout 1s;
        
        mqtt_set_connect Benutzername $ssl_client_s_dn;
    }
} 

Eine vollständige Spezifikation zum Umschreiben von NGINX Plus MQTT CONNECT-Nachrichten finden Sie in der Spezifikation ngx_stream_mqtt_filter_module .

Legen Sie noch heute los

Zukünftige Entwicklungen von MQTT in NGINX Plus können das Parsen anderer MQTT-Nachrichtentypen sowie ein tieferes Parsen der CONNECT-Nachricht umfassen, um Funktionen wie die folgenden zu ermöglichen:

  • Zusätzliche Authentifizierungs- und Zugriffskontrollmechanismen
  • Schutz von Brokern durch Ratenbegrenzung „gesprächiger“ Kunden
  • Nachrichtentelemetrie und Verbindungsmetriken

Wenn Sie bei NGINX Plus neu sind, melden Sie sich für eine kostenlose 30-Tage-Testversion an, um mit MQTT zu beginnen. Wir würden uns auch über Ihr Feedback zu den Funktionen freuen, die Ihnen am wichtigsten sind. Teilen Sie uns in den Kommentaren Ihre Meinung mit.


„Dieser Blogbeitrag kann auf Produkte verweisen, die nicht mehr verfügbar und/oder nicht mehr unterstützt werden. Die aktuellsten Informationen zu verfügbaren F5 NGINX-Produkten und -Lösungen finden Sie in unserer NGINX-Produktfamilie . NGINX ist jetzt Teil von F5. Alle vorherigen NGINX.com-Links werden auf ähnliche NGINX-Inhalte auf F5.com umgeleitet."