Otimizando implantações de MQTT em ambientes corporativos com NGINX Plus

NGINX | 05 de junho de 2023

Ao anunciar a versão R29 do NGINX Plus, abordamos brevemente seu novo suporte nativo à análise de mensagens MQTT. Neste artigo, aprofundaremos o assunto e discutiremos como o NGINX Plus pode ser configurado para otimizar implantações de MQTT em ambientes corporativos.

O que é MQTT?

MQTT significa Transporte de Telemetria de Enfileiramento de Mensagens. É um protocolo de mensagens leve e muito popular, baseado no modelo de publicação e assinatura, ideal para conectar dispositivos e aplicações da Internet das Coisas (IoT) ou de comunicação máquina a máquina (M2M) pela internet. O MQTT foi projetado para operar com eficiência em ambientes com baixa largura de banda ou baixo consumo de energia, sendo a escolha ideal para aplicações com um grande número de clientes remotos. Ele é usado em diversos setores, incluindo eletrônicos de consumo, automotivo, transportes, manufatura e saúde.

Processamento de mensagens MQTT do NGINX Plus

NGINX Plus R29 oferece suporte a MQTT 3.1.1 e MQTT 5.0. Ele atua como um proxy entre clientes e brokers, transferindo tarefas dos sistemas principais, simplificando a escalabilidade e reduzindo os custos computacionais. Especificamente, o NGINX Plus analisa e reescreve partes das mensagens CONNECT do MQTT, possibilitando recursos como:

  • Balanceamento de carga de brokers MQTT
  • Persistência de sessão (reconectando os clientes ao mesmo broker)
  • Terminação SSL/TLS
  • Autenticação por certificado de cliente

As diretivas de processamento de mensagens MQTT devem ser definidas no contexto stream de um arquivo de configuração do NGINX e são fornecidas pelos módulos ngx_stream_mqtt_preread_module
e ngx_stream_mqtt_filter_module.

O módulo preread processa os dados MQTT antes do proxy interno do NGINX, permitindo que as decisões de balanceamento de carga e roteamento para servidores upstream sejam tomadas com base nos dados analisados da mensagem.

O módulo filter permite reescrever os campos clientid, username e password nas mensagens CONNECT recebidas. A capacidade de definir esses campos como variáveis e valores complexos amplia significativamente as opções de configuração, permitindo que o NGINX Plus mascare informações confidenciais do dispositivo ou insira dados, como o nome distinto de um certificado TLS.

Diretivas e variáveis MQTT

Várias novas diretivas e variáveis incorporadas agora estão disponíveis para ajustar sua configuração do NGINX, otimizar implantações de MQTT e atender às suas necessidades específicas.

Diretivas e variáveis incorporadas do módulo Preread

  • mqtt_preread – Habilita a análise de MQTT, extraindo os campos clientid e username das mensagens CONNECT enviadas pelos dispositivos clientes. Esses valores são disponibilizados por meio de variáveis incorporadas e ajudam a distribuir as sessões por hash entre servidores upstream com balanceamento de carga (exemplos abaixo).
  • $mqtt_preread_clientid – Representa o identificador do cliente MQTT enviado pelo dispositivo.
  • $mqtt_preread_username – Representa o nome de usuário enviado pelo cliente para fins de autenticação.

Diretivas do módulo de filtro

  • mqtt – Define se a reescrita de MQTT está habilitada.
  • mqtt_buffers – Substitui o número máximo de buffers de processamento MQTT que podem ser alocados por conexão e o tamanho de cada buffer. Por padrão, o NGINX impõe um limite de 100 buffers por conexão, cada um com 1k de tamanho. Normalmente, essa configuração oferece o melhor desempenho, mas pode exigir ajustes em situações específicas. Por exemplo, mensagens MQTT mais longas exigem um buffer maior. Sistemas que processam um volume maior de mensagens MQTT para uma determinada conexão em um curto período podem se beneficiar de um número maior de buffers. Na maioria dos casos, o ajuste dos parâmetros de buffer tem pouco impacto no desempenho geral do sistema, pois o NGINX cria os buffers a partir de um pool de memória interno.
  • mqtt_rewrite_buffer_size – Especifica o tamanho do buffer usado para criar mensagens MQTT. Essa diretiva foi descontinuada e está obsoleta desde o NGINX Plus R30.
  • mqtt_set_connect – Reescreve os parâmetros da mensagem CONNECT enviada por um cliente. Os parâmetros compatíveis incluem: clientid, username e password.

Exemplos de MQTT

Vamos explorar mais detalhadamente os benefícios do processamento de mensagens MQTT com o NGINX Plus e as práticas recomendadas relacionadas. Observe que usamos as portas 1883 e 8883 nos exemplos abaixo. A porta 1883 é a porta MQTT padrão não segura, enquanto a 8883 é a porta padrão criptografada com SSL/TLS.

Balanceamento de carga de brokers MQTT

A natureza efêmera dos dispositivos MQTT pode fazer com que os IPs dos clientes mudem inesperadamente. Isso pode gerar dificuldades ao encaminhar as conexões dos dispositivos para o broker upstream correto. A migração subsequente das conexões dos dispositivos de um broker upstream para outro pode resultar em operações dispendiosas de sincronização entre brokers, aumentando a latência e os custos.

Ao analisar o campo clientid em uma mensagem MQTT CONNECT, o NGINX pode estabelecer sessões persistentes com os brokers de serviço upstream. Isso é feito usando o clientid como chave de hash para manter as conexões com os serviços de broker no backend.

Neste exemplo, fazemos proxy dos dados de dispositivos MQTT usando o clientid como token para estabelecer sessões persistentes com três brokers upstream. Usamos o parâmetro consistent para que, se um servidor upstream falhar, sua parcela do tráfego seja distribuída uniformemente entre os servidores restantes, sem afetar as sessões já estabelecidas nesses servidores.

stream {      mqtt_preread on; 
     
      upstream backend {
          zone tcp_mem 64k;
          hash $mqtt_preread_clientid consistent;
    
          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 {
          listen 1883;
          proxy_pass backend;
          proxy_connect_timeout 1s;
      }
  }

NGINX Plus também pode analisar o campo de nome de usuário de uma mensagem MQTT CONNECT. Para mais detalhes, consulte a especificação do ngx_stream_mqtt_preread_module specification.

Terminação SSL/TLS

Criptografar as comunicações dos dispositivos é fundamental para garantir a confidencialidade dos dados e protegê-los contra ataques man-in-the-middle. No entanto, o handshake TLS, a criptografia e a descriptografia podem sobrecarregar os recursos de um broker MQTT. Para resolver esse problema, o NGINX Plus pode transferir a criptografia de dados de um broker (ou de um cluster de brokers), simplificando as regras de segurança e permitindo que os brokers se concentrem no processamento das mensagens dos dispositivos.

Neste exemplo, mostramos como o NGINX pode ser usado como proxy para encaminhar o tráfego MQTT criptografado por TLS dos dispositivos para um broker de backend. A diretiva ssl_session_cache define um cache de 5 megabytes, suficiente para armazenar aproximadamente 20.000 sessões SSL. O NGINX tentará se conectar ao broker por meio do proxy durante cinco segundos antes de atingir o tempo limite, conforme definido pela diretiva proxy_connect_timeout.

stream {      server {
          listen 8883 ssl;
          ssl_certificate /etc/nginx/certs/tls-cert.crt;
          ssl_certificate_key /etc/nginx/certs/tls-key.key;
          ssl_session_cache shared:SSL:5m;
          proxy_pass 10.0.0.8:1883;
          proxy_connect_timeout 5s;
      }
  } 

Substituição do ID do cliente

Por motivos de segurança, você pode optar por não armazenar informações que permitam identificar o cliente no banco de dados do broker MQTT. Por exemplo, um dispositivo pode enviar um número de série ou outros dados confidenciais como parte de uma mensagem MQTT CONNECT. Ao substituir o identificador de um dispositivo por outros valores estáticos conhecidos recebidos de um cliente, é possível estabelecer uma chave exclusiva alternativa para cada dispositivo que tente acessar brokers com proxy do NGINX Plus.

Neste exemplo, extraímos um identificador exclusivo do certificado SSL de cliente de um dispositivo e o usamos para mascarar seu ID de cliente MQTT. A autenticação por certificado de cliente (TLS mútuo) é controlada pela diretiva ssl_verify_client. Quando definida com o parâmetro on, o NGINX garante que os certificados de cliente sejam assinados por uma autoridade certificadora (CA) confiável. A lista de certificados de CA confiáveis é definida pela diretiva ssl_client_certificate.

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 on;
          proxy_pass 10.0.0.8:1883;
          proxy_connect_timeout 1s;
          
          mqtt_set_connect clientid $ssl_client_serial;
      }
  }

Certificado do cliente como credencial de autenticação

Uma abordagem comum para autenticar clientes MQTT é usar como nome de usuário os dados armazenados em um certificado de cliente. O NGINX Plus pode analisar certificados de cliente e reescrever o campo de nome de usuário do MQTT, liberando os brokers de backend dessa tarefa. No exemplo a seguir, extraímos o Nome Distinto do Titular (Subject DN) do certificado de cliente e o copiamos para a parte do nome de usuário de uma mensagem MQTT CONNECT.

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 on;
          proxy_pass 10.0.0.8:1883;
          proxy_connect_timeout 1s;
          
          mqtt_set_connect username $ssl_client_s_dn;
      }
  } 

Para obter a especificação completa sobre a reescrita de mensagens MQTT CONNECT no NGINX Plus, consulte a especificação do módulo ngx_stream_mqtt_filter_module specification.

Comece hoje mesmo

Desenvolvimentos futuros do MQTT no NGINX Plus podem incluir a análise de outros tipos de mensagens MQTT, bem como uma análise mais aprofundada da mensagem CONNECT para habilitar funções como:

  • Mecanismos adicionais de autenticação e controle de acesso
  • Proteção dos brokers por meio da limitação da taxa de clientes que geram tráfego excessivo
  • Telemetria de mensagens e métricas de conexão

Se você ainda não conhece o NGINX Plus, inscreva-se para uma avaliação gratuita de 30 dias e comece a usar o MQTT. Também adoraríamos receber seu feedback sobre os recursos que mais importam para você. Conte-nos o que você acha nos comentários.


Compartilhar
Tags: F5 NGINX, Tech

Publicações relacionadas no blog

Como o F5 NGINX One aprimora o gerenciamento e a observabilidade
NGINX | 10/10/2024

Como o F5 NGINX One aprimora o gerenciamento e a observabilidade

Descubra como o F5 NGINX One aprimora o gerenciamento e a observabilidade de ambientes híbridos e multicloud ao oferecer um console web centralizado baseado em SaaS, com insights em tempo real, conformidade automatizada e gerenciamento simplificado de configurações.

Do OpenAPI ao NGINX como gateway de API usando uma API declarativa
NGINX | 17/06/2024

Do OpenAPI ao NGINX como gateway de API usando uma API declarativa

Descubra como transformar uma definição de esquema OpenAPI em uma configuração NGINX totalmente funcional, operando como um API Gateway com a segurança de um Web Application Firewall e um Portal do Desenvolvedor, usando uma abordagem declarativa de API.

Como gerenciar picos repentinos de tráfego e sobrecarga do servidor
NGINX | 14/07/2021

Como gerenciar picos repentinos de tráfego e sobrecarga do servidor

Picos de tráfego e sobrecarga de servidores são preocupações sérias para varejistas online em qualquer época, mas especialmente durante a “Cyber Season” de compras de fim de ano. Detalhamos como você pode aproveitar as soluções de entrega de aplicações de nível de produção da NGINX para se preparar para aumentos repentinos de tráfego.

Distribuição segura de chaves privadas SSL com o NGINX
NGINX | 02/04/2019

Distribuição segura de chaves privadas SSL com o NGINX

Descrevemos três maneiras progressivamente mais seguras de proteger chaves privadas SSL ao configurar o NGINX para processar tráfego HTTPS: permitir acesso de leitura apenas ao usuário root, criptografar as chaves com senhas armazenadas separadamente e distribuir as senhas a partir de um repositório central.

Agrupando solicitações de API em lotes com NGINX Plus e o módulo JavaScript do NGINX
NGINX | 24/05/2018

Agrupando solicitações de API em lotes com NGINX Plus e o módulo JavaScript do NGINX

O módulo JavaScript do NGINX lançado com o NGINX Plus R15 oferece suporte a subsolicitações, possibilitando uma classe totalmente nova de casos de uso para o NGINX Plus. Este exemplo completo também usa a API do NGINX Plus e os módulos de chave-valor para converter solicitações de API dos clientes em solicitações separadas para as APIs dos microsserviços que compõem um aplicativo.

Como superar o esgotamento de portas efêmeras no NGINX e no NGINX Plus
NGINX | 19/04/2016

Como superar o esgotamento de portas efêmeras no NGINX e no NGINX Plus

Confira dicas para evitar o esgotamento de portas efêmeras com ajustes no kernel do Linux, conexões keepalive e conexões vinculadas dinamicamente a endereços IP locais.