A segurança MQTT se resume a um punhado de hábitos que a maioria das equipes conhece e, mesmo assim, deixa de lado sob pressão de prazo. Este guia os transforma em um checklist de 12 pontos que você pode aplicar a qualquer implantação, com código pronto para copiar e colar que verifica TLS em Python e na linha de comando. Em cada ponto, também dizemos o que um broker MQTT gerenciado como o ConnectMQ já faz por você e o que continua sendo responsabilidade sua.
Por Que a Segurança MQTT Precisa de um Checklist Próprio
O MQTT foi projetado para ser leve. O protocolo em si define campos de usuário e senha no CONNECT e deixa todo o resto — criptografia, autorização, proteção contra abuso — para o broker e a camada de rede. Essa flexibilidade é ótima para dispositivos com recursos limitados, mas também significa que uma implantação MQTT é exatamente tão segura quanto a sua escolha de configuração mais fraca.
As falhas típicas são banais e evitáveis:
- Dispositivos falando TCP puro na porta 1883 pela internet aberta.
- Uma única senha compartilhada gravada no firmware de todos os dispositivos.
- Topics como
customers/jane.doe@example.com/location, que vazam dados só pelo nome do topic. - Subscribers que confiam em qualquer payload e travam (ou coisa pior) com entradas malformadas.
- Clientes que "resolvem" um erro de TLS desligando a verificação de certificado.
Se você ainda não sabe como os brokers roteiam mensagens, comece por O Que É um Broker MQTT? e volte aqui depois.
O Checklist de Segurança MQTT em Resumo
| # | Prática | Sua responsabilidade | O que o ConnectMQ oferece |
|---|---|---|---|
| 1 | Sempre use TLS | Conectar na 8883 / 8084 | TLS na 8883, WSS na 8084, certificado Let's Encrypt |
| 2 | Mantenha dados reais fora da área pública | Usar credenciais do portal em produção | Topics do tenant isolados da área pública |
| 3 | Credenciais únicas por broker/dispositivo | Não reutilizar a mesma senha em todo lugar | Usuário, senha e client ID gerados por broker |
| 4 | Restrinja os client IDs | Usar o ID emitido e sufixos | Só o client ID emitido e suas variantes _suffix são aceitos |
| 5 | Guarde segredos com segurança nos dispositivos | Armazenamento criptografado, nada de segredos no Git | — |
| 6 | Projete topics que não vazam nada | Nada de dados pessoais nos nomes de topics | Isolamento multi-tenant |
| 7 | Valide todo payload | Validação de schema nos subscribers | Limites de tamanho de mensagem por plano |
| 8 | Aplique rate limits e cotas | Limitar a taxa dos publishers | Cotas por plano, reason code 0x97 Quota exceeded |
| 9 | Defenda-se de força bruta e floods | Recuar após falhas | Bloqueio de IP após credenciais inválidas repetidas, proteção contra flood de conexões |
| 10 | Monitore o estado das conexões | Alertar sobre desconexões inesperadas | $SYS/broker/connection/{clientId}/state |
| 11 | Valide certificados nos clientes | Nunca desativar a verificação | Cadeia de certificados publicamente confiável |
| 12 | Autorize no nível de topic | Separar brokers ou apps por fronteira de confiança | Isolamento no nível do tenant |
O restante deste artigo detalha cada ponto.
1. Sempre Use TLS (Portas 8883 e 8084)
MQTT puro na porta 1883 envia usuários, senhas e payloads em texto claro. Qualquer um no caminho — o Wi-Fi de uma cafeteria, um roteador comprometido, uma porta de switch espelhada — pode lê-los e reproduzi-los. O TLS resolve isso criptografando a conexão e comprovando a identidade do broker.
No ConnectMQ, todo broker aceita:
- MQTT sobre TLS em
mqtts://broker.connectmq.com:8883 - MQTT sobre WebSocket seguro em
wss://broker.connectmq.com:8084/mqtt
Ambos usam um certificado Let's Encrypt, então os repositórios de confiança padrão dos sistemas operacionais já confiam nele. Trate as portas 1883 e 8083 como exclusivas de desenvolvimento. Aplicações de navegador precisam usar WSS de qualquer forma; veja MQTT sobre WebSocket para um exemplo completo.
2. Nunca Coloque Dados Reais na Área Pública
O servidor MQTT público (gratuito) em broker.connectmq.com oferece uma área pública anônima para experimentos: conecte sem usuário, com um client ID único, e você já pode publicar e assinar. Ela é fantástica para aprender, e é totalmente pública. Qualquer pessoa que assine o topic certo pode ler suas mensagens.
Regras para a área pública:
- Use um prefixo aleatório como
connectmq/demo/<your-random-id>/...para não colidir com outros usuários. - Nunca publique dados pessoais, credenciais, localizações ou qualquer coisa que você não postaria em um fórum.
- Migre para credenciais do portal antes que usuários ou dispositivos reais entrem em cena.
Tenants autenticados no ConnectMQ são isolados: seus topics não ficam visíveis para outros tenants nem para a área pública, e clientes públicos só enxergam outros clientes públicos. Mais detalhes no nosso guia do servidor MQTT público (gratuito).
3. Use Credenciais Únicas por Broker e por Dispositivo
Uma única senha compartilhada por toda a frota significa que uma imagem de firmware extraída compromete todos os dispositivos. Busque credenciais que possam ser revogadas sem mexer no restante da frota.
No portal do ConnectMQ (https://app.connectmq.com), cada broker criado recebe usuário, senha e client ID gerados automaticamente. Segredos gerados evitam as escolhas fracas clássicas (admin/admin, iot123) e mantêm os ambientes separados: crie um broker para staging e outro para produção em vez de compartilhar credenciais entre eles.
Independentemente do broker, rotacione as credenciais quando um dispositivo for desativado e nunca cole segredos de produção em tickets, chats ou capturas de tela.
4. Restrinja os Client IDs
O client ID MQTT identifica uma sessão. Se qualquer pessoa puder se conectar com qualquer client ID, um atacante que conheça o ID de um dispositivo pode derrubá-lo (o broker desconecta a sessão existente quando um ID duplicado se conecta) ou sequestrar sua sessão persistente.
O ConnectMQ restringe as conexões autenticadas ao client ID emitido para o broker, mais as variantes com _sufixo dele. Se o seu ID emitido é YOUR_CLIENT_ID, você pode conectar YOUR_CLIENT_ID_sensor1, YOUR_CLIENT_ID_dashboard e assim por diante, mas não IDs arbitrários. Isso garante nomes de sessão previsíveis e auditáveis e impede que estranhos se passem pelas suas sessões.
Dica prática: derive o sufixo de algo estável no dispositivo, como o número de série ou o endereço MAC, para que as reconexões reutilizem a mesma sessão.
5. Guarde Segredos com Segurança nos Dispositivos
As credenciais precisam ficar em algum lugar do dispositivo. Torne esse lugar o mais difícil de alcançar possível:
- Não faça commit de credenciais no controle de versão. Use um header de configuração ou arquivo de ambiente separado e ignorado pelo Git.
- Use o armazenamento protegido da plataforma quando existir (flash criptografada / criptografia de NVS no ESP32, um TPM ou secure element em gateways, um gerenciador de segredos em servidores).
- Desative portas de debug e consoles seriais no firmware de produção para que os segredos não possam ser extraídos facilmente.
- Planeje uma etapa de provisionamento que grave segredos por dispositivo na fabricação, em vez de compilá-los em uma imagem compartilhada.
6. Projete Topics Que Não Vazam Informação
Nomes de topics são metadados, e metadados vazam. Mesmo com payloads criptografados, um topic como hospital/ward3/patient-4471/heart-rate revela muito para quem consegue observá-lo.
Diretrizes:
- Use identificadores opacos (
site-07/dev-3fa9/telemetry) em vez de nomes, e-mails ou endereços. - Mantenha uma hierarquia consistente, por exemplo
site/area/line/device/kind, para que permissões e wildcards continuem gerenciáveis. - Evite assinaturas amplas com wildcard como
#em consumidores de produção; assine apenas o que você precisa. - Mantenha um número modesto de níveis. A área pública, por exemplo, permite no máximo 8 níveis de topic.
7. Valide Todo Payload
O broker transporta bytes; ele não sabe se o seu JSON está bem formado nem se uma temperatura de 9.000 °C é plausível. Todo subscriber deve tratar os payloads recebidos como entrada não confiável.
import json
ALLOWED_KEYS = {"temperature", "humidity", "ts"}
def parse_telemetry(raw: bytes):
if len(raw) > 4096:
raise ValueError("payload too large")
data = json.loads(raw.decode("utf-8"))
if not isinstance(data, dict) or not set(data) <= ALLOWED_KEYS:
raise ValueError("unexpected fields")
t = float(data["temperature"])
if not -40.0 <= t <= 125.0:
raise ValueError("temperature out of range")
return data
Rejeite, registre e siga em frente. Nunca passe o conteúdo do payload diretamente para SQL, comandos de shell ou HTML. O ConnectMQ impõe tamanhos máximos de mensagem por plano (por exemplo, 256 KB no plano Serverless gratuito e 64 KB na área pública), o que limita o pior caso, mas a validação de schema continua sendo trabalho seu.
8. Aplique Rate Limits e Cotas
Um loop de firmware com bug que publica o mais rápido possível é um ataque de negação de serviço escrito por você mesmo. Limite a taxa no dispositivo (publique quando houver mudança ou em intervalo fixo) e espere que o broker também imponha limites.
O ConnectMQ aplica cotas por plano e por área. A área pública permite, por exemplo, 10 mensagens por segundo e 10 assinaturas por cliente. Quando um cliente MQTT 5 ultrapassa uma cota, o broker responde com o reason code 0x97 Quota exceeded; sob carga pesada, pode responder com 0x89 Server busy. Trate esses códigos explicitamente: recue, registre e alerte em vez de tentar de novo em um loop apertado. O guia de recursos do MQTT 5 explica os reason codes com mais profundidade.
9. Proteja-se contra Força Bruta e Floods de Conexão
Brokers expostos sofrem tentativas constantes de adivinhar senhas e tempestades de reconexão. No ConnectMQ:
- Endereços IP são bloqueados após tentativas repetidas com credenciais inválidas.
- Floods de conexão disparam banimentos temporários.
- A proteção adaptativa contra sobrecarga mantém o cluster responsivo durante picos.
No lado do cliente, implemente backoff exponencial com jitter. Se uma frota inteira reconecta no mesmo instante depois de uma instabilidade de rede, até dispositivos legítimos parecem um flood.
10. Monitore o Estado das Conexões com $SYS
Não dá para proteger o que você não vê. O ConnectMQ publica o estado de conexão de cada cliente em $SYS/broker/connection/{clientId}/state: 1 quando o cliente se conecta e 0 quando se desconecta. Assine a partir de um serviço de monitoramento e gere alertas para quedas inesperadas ou para um dispositivo que se conecta em horários estranhos.
mosquitto_sub -h broker.connectmq.com -p 1883 -i monitor-7c2e \
-t '$SYS/broker/connection/my-device-7c2e/state' -v
# $SYS/broker/connection/my-device-7c2e/state 1
# $SYS/broker/connection/my-device-7c2e/state 0
Combine isso com mensagens de Last Will do MQTT para que o resto do sistema fique sabendo de desconexões não limpas.
11. Valide Certificados em Todos os Clientes
TLS sem validação de certificado é criptografia para um interlocutor desconhecido. Um atacante no meio do caminho pode apresentar qualquer certificado, e o cliente vai enviar as credenciais para ele sem pestanejar. Infelizmente, "desativar a verificação" é uma correção copiada e colada muito comum para erros de TLS.
Python (paho-mqtt 2.x com o módulo ssl)
import ssl
import paho.mqtt.client as mqtt
def on_connect(client, userdata, flags, reason_code, properties):
print("Connected:", reason_code)
ctx = ssl.create_default_context() # CAs do sistema, verificação de hostname ativa
ctx.minimum_version = ssl.TLSVersion.TLSv1_2
client = mqtt.Client(mqtt.CallbackAPIVersion.VERSION2, client_id="YOUR_CLIENT_ID")
client.username_pw_set("YOUR_USERNAME", "YOUR_PASSWORD")
client.tls_set_context(ctx)
client.on_connect = on_connect
client.connect("broker.connectmq.com", 8883)
client.loop_forever()
Nunca entregue código com ctx.check_hostname = False, ssl.CERT_NONE ou client.tls_insecure_set(True).
mosquitto_pub e mosquitto_sub
No Linux, aponte o CLI para o diretório de CAs do sistema. Em qualquer plataforma, você pode, alternativamente, baixar o certificado ISRG Root X1 (isrgrootx1.pem) da Let's Encrypt e passá-lo com --cafile:
# Linux: repositório de CAs do sistema
mosquitto_sub -h broker.connectmq.com -p 8883 --capath /etc/ssl/certs \
-u YOUR_USERNAME -P YOUR_PASSWORD -i YOUR_CLIENT_ID_cli \
-t "site-07/#" -v
# Qualquer sistema: certificado raiz explícito
mosquitto_pub -h broker.connectmq.com -p 8883 --cafile isrgrootx1.pem \
-u YOUR_USERNAME -P YOUR_PASSWORD -i YOUR_CLIENT_ID_pub \
-t "site-07/dev-3fa9/telemetry" -m '{"temperature":22.5}'
Se o hostname ou a cadeia não baterem, a conexão falha. Essa falha é justamente o recurso.
12. Autorize no Nível de Topic Onde For Necessário
Como prática geral de MQTT, o princípio do menor privilégio se aplica aos topics: um sensor de temperatura deve publicar apenas no seu próprio topic de telemetria e assinar apenas o seu próprio topic de comandos. Muitas arquiteturas garantem isso com regras de autorização por topic ou colocando dispositivos com níveis de confiança diferentes atrás de credenciais e brokers separados.
No ConnectMQ, a fronteira de isolamento é o tenant: os topics de um tenant nunca ficam visíveis para outro tenant nem para a área pública. Se você precisa de separação rígida entre grupos de dispositivos, crie brokers separados para eles no portal e mantenha as verificações no nível da aplicação (quem pode enviar qual comando) no seu backend.
Uma Conexão Segura de Ponta a Ponta
Juntando tudo, um cliente ConnectMQ pronto para produção se conecta na porta 8883 (ou WSS 8084) com a validação de certificado ativa, autentica com credenciais geradas no portal e um client ID YOUR_CLIENT_ID_<device>, publica em topics opacos a uma taxa razoável, recua ao receber 0x97 e 0x89 e é monitorado via $SYS.
Para um passo a passo do lado do dispositivo, veja o tutorial de ESP32 com MQTT, que termina com uma versão do sketch protegida por TLS.
Comece com o ConnectMQ
O ConnectMQ entrega endpoints TLS e WSS, credenciais geradas, restrições de client ID, isolamento entre tenants e proteção contra abuso prontos para uso, para que sua equipe possa se concentrar nas partes da segurança MQTT que só vocês podem assumir. Crie um broker no plano Serverless gratuito em https://app.connectmq.com — sem cartão de crédito — e conecte seu primeiro cliente seguro em minutos.
Perguntas frequentes
O MQTT é seguro por padrão?
Não. O protocolo MQTT define campos de autenticação, mas deixa a criptografia e a autorização para o broker e o transporte. Você precisa de TLS, credenciais fortes por dispositivo e limites sensatos no broker para torná-lo seguro.
Qual porta devo usar para MQTT seguro?
Use 8883 para MQTT sobre TLS e 8084 para MQTT sobre WebSocket seguro (WSS). No ConnectMQ, ambas usam um certificado Let's Encrypt publicamente confiável.
Posso usar o servidor MQTT público broker.connectmq.com em produção?
Não. A área pública é anônima e pode ser lida por qualquer pessoa que assine seus topics. Use credenciais do portal do ConnectMQ para qualquer dado real; tenants autenticados ficam isolados da área pública e uns dos outros.
O que significa o reason code 0x97?
0x97 é o reason code do MQTT 5 para "Quota exceeded". O ConnectMQ o retorna quando um cliente ultrapassa um limite do plano ou da área; seu cliente deve recuar em vez de tentar de novo imediatamente.
Tudo bem desativar a verificação de certificado para testes?
Só em uma máquina de desenvolvimento descartável, e nunca em firmware entregue ou código de produção. Desativar a verificação remove a proteção contra ataques man-in-the-middle, que é o principal motivo para usar TLS.



