Raspberry Pi

Pico W MQTT TLS: Conexões Seguras em MicroPython na Porta 8883 com Verificação de Certificado

Criptografe e autentique o tráfego MQTT do seu Raspberry Pi Pico W. Este guia cobre versões de firmware e biblioteca, o certificado raiz correto, o ajuste do relógio, a verificação do servidor, a medição do handshake e a correção dos erros de TLS mais comuns.

Conexão Pico W MQTT TLS com um cadeado entre o Raspberry Pi Pico W e um broker MQTT na nuvem na porta 8883
Rode isso no seu próprio broker MQTTTenha um broker MQTT privado e gerenciado no plano Free e comece com exemplos de código prontos.
Teste grátis Exemplos de código Sem cartão de crédito

Pico W MQTT TLS é o que transforma uma conexão de hobby em uma conexão confiável: o tráfego é criptografado e a placa verifica se está realmente falando com o seu broker antes de enviar uma senha. Este guia pega um sketch MQTT funcional em MicroPython e o leva para a porta 8883 com verificação completa de certificado, cobrindo as versões de firmware necessárias, o certificado raiz a carregar, por que o relógio importa, quanto tempo o handshake leva em um RP2040 e como corrigir os erros que você provavelmente vai encontrar.

Por que TLS importa em um microcontrolador

MQTT puro na porta 1883 envia tudo em texto claro, incluindo usuário e senha no pacote CONNECT. Qualquer pessoa no mesmo Wi-Fi, no provedor ou no caminho até o broker pode ler suas leituras e reutilizar suas credenciais. O TLS resolve dois problemas de uma vez:

  1. Criptografia. Payloads e credenciais ficam ilegíveis em trânsito.
  2. Autenticação do servidor. O dispositivo verifica a cadeia de certificados do broker, então um access point falso ou um sequestro de DNS não consegue se passar pelo broker e coletar credenciais.

O segundo ponto é o que a maioria dos tutoriais ignora. Ligar o TLS sem verificar o certificado dá criptografia contra bisbilhoteiros passivos, mas nenhuma proteção contra um atacante ativo. Este guia faz do jeito certo. Para o panorama completo, veja as boas práticas de segurança MQTT.

Se você nunca conectou um Pico W ao MQTT, comece pelo tutorial básico de MQTT com Raspberry Pi Pico W e volte quando ele estiver funcionando.

Versões de firmware e biblioteca

O suporte a TLS no MicroPython mudou nas últimas versões, e muitos exemplos antigos já não rodam como foram escritos.

Componente O que usar Por quê
Firmware MicroPython Uma versão atual para RPI_PICO_W (1.23 ou mais recente) Fornece ssl.SSLContext com load_verify_locations e tratamento correto de hostname
umqtt.simple A versão atual do micropython-lib via mip Versões recentes aceitam um SSLContext no argumento ssl
Certificado raiz ISRG Root X1 em formato DER A âncora de confiança dos certificados Let's Encrypt

Exemplos antigos passam ssl=True junto com um dicionário ssl_params. Se você vir um TypeError sobre argumentos nomeados inesperados, ou AttributeError: 'bool' object has no attribute 'wrap_socket', está misturando um exemplo antigo com uma biblioteca nova ou vice-versa. Atualize firmware e biblioteca e use o código baseado em contexto mostrado abaixo.

Confira o que você está rodando a partir do REPL:

import sys, os
print(sys.version)
print(os.uname().machine)

Passo 1: obtenha o certificado raiz correto

Os brokers ConnectMQ, incluindo o servidor MQTT público em broker.connectmq.com, usam certificados emitidos pela Let's Encrypt. Você mesmo pode confirmar a cadeia:

openssl s_client -connect broker.connectmq.com:8883 -servername broker.connectmq.com -showcerts </dev/null \
  | grep -E "s:|i:"

A saída lista o certificado do servidor, o intermediário da Let's Encrypt e, no final, um emissor ISRG Root X1. É nessa raiz que o Pico W deve confiar. Confiar na raiz em vez do certificado do servidor faz diferença: os certificados Let's Encrypt são renovados a cada poucos meses e os intermediários mudam de tempos em tempos, mas a raiz continua válida por anos.

Baixe a raiz em formato DER, que o MicroPython carrega diretamente:

curl -o isrgrootx1.der https://letsencrypt.org/certs/isrgrootx1.der
# ou converta uma cópia PEM que você já tenha
openssl x509 -in isrgrootx1.pem -outform DER -out isrgrootx1.der

Copie para a placa pela visualização de arquivos do Thonny ou com:

mpremote cp isrgrootx1.der :isrgrootx1.der

Passo 2: ajuste o relógio

O Pico W não tem relógio com bateria de backup. Depois de cada energização, o relógio de tempo real começa em uma data padrão no passado. Dependendo do build do firmware, os períodos de validade dos certificados podem ser verificados contra esse relógio, e um dispositivo que acredita estar anos no passado vai rejeitar um certificado emitido no mês passado como ainda não válido. Mesmo quando a verificação não é aplicada, a hora correta é útil para logs e timestamps, então ajuste-a via NTP logo após o Wi-Fi conectar:

import ntptime
ntptime.host = "pool.ntp.org"
ntptime.settime()          # ajusta o RTC para UTC

ntptime.settime() pode lançar OSError quando a requisição NTP expira, então tente algumas vezes em vez de deixar o programa travar.

Passo 3: o programa completo de Pico W MQTT TLS

Salve como main.py. Para o servidor público de testes, as credenciais podem ficar vazias e qualquer client ID único funciona. Em produção, preencha os valores gerados no portal.

# main.py - Pico W MQTT sobre TLS com verificação de certificado
import time
import gc
import ssl
import network
import machine
import ntptime
import ubinascii
from umqtt.simple import MQTTClient

WIFI_SSID = "YOUR_WIFI_SSID"
WIFI_PASSWORD = "YOUR_WIFI_PASSWORD"

BROKER = "broker.connectmq.com"
PORT = 8883
# Servidor público de testes: anônimo, qualquer client ID único.
# Produção: use os valores do portal do broker.
MQTT_USER = None                 # "YOUR_USERNAME"
MQTT_PASSWORD = None             # "YOUR_PASSWORD"
CLIENT_ID = "pico-tls-" + ubinascii.hexlify(machine.unique_id()).decode()  # or "YOUR_CLIENT_ID"

TOPIC = "connectmq/demo/tl5v8n/pico1/temperature"
CA_FILE = "isrgrootx1.der"

sensor = machine.ADC(4)


def connect_wifi():
    wlan = network.WLAN(network.STA_IF)
    wlan.active(True)
    if not wlan.isconnected():
        wlan.connect(WIFI_SSID, WIFI_PASSWORD)
        for _ in range(40):
            if wlan.isconnected():
                break
            time.sleep(0.5)
    if not wlan.isconnected():
        raise OSError("Wi-Fi failed, status %d" % wlan.status())
    print("Wi-Fi:", wlan.ifconfig()[0])


def sync_time():
    for attempt in range(5):
        try:
            ntptime.settime()
            print("Time set:", time.gmtime())
            return
        except OSError:
            time.sleep(2)
    print("Warning: NTP failed, clock may be wrong")


def make_ssl_context():
    ctx = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
    ctx.verify_mode = ssl.CERT_REQUIRED
    with open(CA_FILE, "rb") as f:
        ctx.load_verify_locations(cadata=f.read())
    return ctx


def connect_mqtt(ctx):
    gc.collect()
    print("Free RAM before TLS:", gc.mem_free())
    client = MQTTClient(
        CLIENT_ID, BROKER, port=PORT,
        user=MQTT_USER, password=MQTT_PASSWORD,
        keepalive=60, ssl=ctx,
    )
    start = time.ticks_ms()
    client.connect()
    print("TLS + MQTT connect took", time.ticks_diff(time.ticks_ms(), start), "ms")
    print("Free RAM after TLS:", gc.mem_free())
    return client


def read_temperature():
    v = sensor.read_u16() * 3.3 / 65535
    return round(27 - (v - 0.706) / 0.001721, 2)


def main():
    connect_wifi()
    sync_time()
    ctx = make_ssl_context()
    client = connect_mqtt(ctx)
    while True:
        payload = '{"value": %s, "unit": "C"}' % read_temperature()
        client.publish(TOPIC, payload, qos=1)
        print("Published", payload)
        time.sleep(30)           # publicar a cada 30 s mantém o keepalive de 60 s satisfeito


while True:
    try:
        main()
    except OSError as e:
        print("Error:", e, "- reconnecting in 10 s")
        time.sleep(10)

O umqtt.simple envolve o socket com o contexto e passa o nome do broker como hostname do servidor. É isso que permite ao mbedTLS verificar que o certificado foi emitido para broker.connectmq.com, e também envia o SNI, de que muitos servidores TLS precisam para escolher o certificado certo.

Acompanhe a saída a partir do seu computador, também via TLS:

mosquitto_sub -h broker.connectmq.com -p 8883 --cafile isrgrootx1.pem \
  -i laptop-tl5v8n -v -t "connectmq/demo/tl5v8n/#"

Tempo de handshake e memória no RP2040

O RP2040 não tem aceleração criptográfica em hardware, então o mbedTLS faz todo o trabalho em software nos núcleos Cortex-M0+. Espere um handshake TLS claramente perceptível, muitas vezes da ordem de um segundo ou mais, comparado a uma conexão TCP pura quase instantânea. O programa imprime o valor exato na sua rede, e vale registrá-lo, porque ele depende da troca de chaves negociada, do tamanho da cadeia de certificados e da latência do Wi-Fi.

O que isso significa na prática:

  1. Conecte uma vez e permaneça conectado. Com alimentação da rede elétrica, mantenha uma sessão TLS de longa duração e envie muitas mensagens por ela. O custo do handshake só é pago na reconexão.
  2. Cuidado com projetos de deep sleep. Um dispositivo a bateria que acorda, conecta, publica e dorme paga o handshake completo a cada ciclo, o que custa tempo e energia. Nosso guia de Pico W a bateria com MQTT discute intervalos maiores e agrupamento de leituras para esse caso.
  3. Libere memória primeiro. Uma sessão TLS precisa de dezenas de kilobytes de RAM para buffers. Chame gc.collect() antes de conectar, evite criar objetos grandes antes do handshake e compare os valores de memória livre impressos antes e depois.
  4. Considere o Pico 2 W. O RP2350 dele usa núcleos Cortex-M33 mais rápidos, o que encurta o handshake e deixa mais folga. Veja Pico W vs. Pico 2 W.

Solução de erros de TLS no Pico W

Erro ou sintoma Causa provável Correção
OSError: (-9984, 'MBEDTLS_ERR_X509_CERT_VERIFY_FAILED') Certificado raiz errado ou ausente, ou hostname errado Carregue o ISRG Root X1, conecte pelo hostname e não pelo IP
A verificação falha só após a energização Relógio não ajustado Rode ntptime.settime() antes de conectar
OSError: [Errno 12] ENOMEM RAM contígua insuficiente para os buffers TLS gc.collect() antes de conectar, reduza buffers e variáveis globais
TypeError em MQTTClient(... ssl_params=...) Exemplo antigo com umqtt.simple novo Passe um SSLContext como ssl=
Conecta na 1883, mas dá timeout na 8883 A rede bloqueia a 8883 Teste de um notebook na mesma rede; use outra rede ou peça à TI para liberar a saída na 8883
MQTTException: 5 Não autorizado Verifique usuário, senha e o client ID exato do portal
O handshake demora muito Sinal Wi-Fi fraco ou pressão de RAM Verifique o RSSI com wlan.status("rssi") e a memória livre

Uma observação sobre CERT_NONE: definir ctx.verify_mode = ssl.CERT_NONE faz os erros desaparecerem, e é por isso que ele aparece em tantas respostas de fórum. Ele também remove a autenticação do servidor. Use apenas para um diagnóstico pontual, nunca em código implantado.

Migrando para o seu próprio broker privado

O servidor público aceita conexões TLS anônimas na 8883, o que é perfeito para testar este código. Para dispositivos reais, crie um broker privado no ConnectMQ e copie as credenciais geradas para as três configurações no início do programa. O broker vincula os client IDs às credenciais emitidas, então use exatamente o client ID do portal. Como o certificado é da Let's Encrypt, o mesmo arquivo isrgrootx1.der funciona tanto para o servidor público quanto para o seu broker privado, e as renovações de certificado do lado do broker não exigem nenhuma mudança no dispositivo.

Um broker MQTT gerenciado também bloqueia endereços IP após repetidas falhas de login e aplica cotas por plano, o que protege seu broker de clientes com mau comportamento ou comprometidos sem nenhum trabalho da sua parte. Para saber mais sobre brokers na nuvem, veja nosso guia de broker MQTT na nuvem e, para outros projetos com Raspberry Pi, o tutorial de MQTT com Raspberry Pi.

Proteja seu Pico W com o ConnectMQ

Crie um broker Serverless gratuito em app.connectmq.com, sem cartão de crédito, copie usuário, senha e client ID para o main.py, e seu Pico W passa a publicar via TLS verificado na porta 8883. O explorador de topics ao vivo do portal mostra as mensagens chegando, para você confirmar o caminho seguro de ponta a ponta.

Perguntas frequentes

Qual certificado o Pico W precisa para o ConnectMQ?

O ISRG Root X1, a raiz da Let's Encrypt, em formato DER. Confiar na raiz significa que as renovações rotineiras de certificado no broker não exigem atualizar o dispositivo.

Por que meu Pico W rejeita um certificado válido?

As causas mais comuns são um relógio que nunca foi ajustado, fazendo o certificado parecer ainda não válido, a conexão por endereço IP em vez de hostname, ou o carregamento do certificado raiz errado.

Quanto tempo leva um handshake TLS no Pico W?

É visivelmente mais lento do que em chips com hardware criptográfico, porque o RP2040 faz toda a criptografia em software. Meça com time.ticks_ms() em volta do connect(), como mostrado acima, e mantenha as conexões abertas em vez de reconectar a cada mensagem.

Posso usar certificados de cliente no Pico W?

O SSLContext do MicroPython suporta load_cert_chain para certificados de cliente. O broker autentica os dispositivos com usuário, senha e client ID emitidos no portal, então uma conexão TLS com verificação do servidor e essas credenciais é a configuração padrão.

Artigos relacionados

Registro de Acessos Raspberry Pi RFID MQTT com o Leitor RC522

Ligue um leitor RFID RC522 a um Raspberry Pi, leia tags em Python, confira-as em uma lista de permissões local e publique cada tentativa de acesso como um evento MQTT que loggers, dashboards e ferramentas de alerta podem consumir.

8 min de leitura

Confiabilidade do Raspberry Pi: Rodando um Pi 24/7 como Gateway IoT

Um guia prático para manter um gateway MQTT com Raspberry Pi rodando por meses: desgaste do armazenamento, sistemas de arquivos somente leitura, alimentação, refrigeração, watchdogs de hardware e software e monitoramento remoto de saúde.

9 min de leitura

Pico W vs Pico 2 W para MQTT: Desempenho, Memória e TLS do RP2040 vs RP2350

O Pico 2 W mantém o formato e o chip Wi-Fi do Pico W, mas troca o RP2040 pelo RP2350, mais rápido. Esta comparação mostra o que isso significa para dispositivos MQTT: CPU, memória, TLS, recursos de segurança, suporte de software e qual placa comprar para cada projeto.

9 min de leitura

Todos os artigos →

Seu broker MQTT privado está a poucos cliques de distância

Crie uma conta, receba as credenciais do seu broker e conecte seu primeiro dispositivo — sem servidores para instalar, atualizar ou escalar.