Manual
do
Maker
.
com
Por padrão, o broker Mosquitto não utiliza criptografia no canal de dados, na porta 1883. Para uso interno ou para testes não há problema, além de que não é tão simples interceptar o meio na Internet. Porém, não é também uma das tarefas mais difíceis e, se feito, as credenciais serão expostas, não só as mensagens. Nesse artigo veremos como gerar certificado para o broker MQTT Mosquitto, protegendo assim os dados de tráfego. Também mostrarei o uso do certificado no client - dessa vez, por linha de comando, e em uma futura implementação, em um ESP8266 ou ESP32.
Se ainda não configurou um broker MQTT, pode começar por esse artigo. É rápido e fácil e você não precisará de conexão com Internet para fazer seus testes, o que torna o ambiente de desenvolvimento mais seguro.
Como gerar certificado é uma tarefa conhecida e praticada por administradores de sistema, provavelmente não haverá muita novidade por aqui. Além do mais, o processo é muito padronizado.
Você pode gerar as chaves onde quiser, no broker ou em outro computador, depois transportá-la para os respectivos diretórios. Eu uso Linux e recomendo que o processo seja feito diretamente no broker ou em uma máquina virtual Linux, caso esteja usando Windows. Para a virtualização, recomendo o VirtualBox (baixe aqui) - o melhor, em minha opinião.
Considerando que já esteja no Linux, instale o programa openssl:
sudo su
apt-get update
apt-get install openssl
Crie um diretório para trabalhar. Eu fiz tudo diretamente no broker, dentro do diretório /etc/mosquitto, em meu notebook.
mkdir certificado
cd certificado
Agora começa a brincadeira.
O processo consiste em uma série de comandos. Tenha paciência, porque apesar de ser uma série de comandos estranhos, o processo é simples.
openssl genrsa -des3 -out ca.key 2048
Esse comando gerará o arquivo ca.key.
Agora vamos criar um certificado, cujo nome do arquivo resultante será ca.crt.
openssl req -new -x509 -days 1826 -key ca.key -out ca.crt
Preencha os campos como na imagem a seguir. O common name deve ser o IP do broker, a URL do broker ou o nome de host, se estiver instalando localmente. Meu hostname é dobitaobyte (estou instalando em meu notebook para escrever esse artigo).
Esse já é um dos arquivos utilizados pelo broker. As cópias serão feitas quando tudo estiver concluído.
openssl genrsa -out server.key 2048
Estamos quase na metade já.
openssl req -new -out server.csr -key server.key
Não preencha os atributos extras, isso causará problemas na autenticação.
Agora para assinar o certificado do servidor, utilizaremos a chave CA.
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out server.crt -days 360
Com isso, temos os arquivos:
Três desses arquivos serão utilizados. O ca.crt deve ser colocado no diretório /etc/mosquitto/ca_certificates, enquanto os arquivos server.key e server.crt devem ser colocado no diretório /etc/mosquitto/certs.
Agora será necessária uma modificação no arquivo de configuração do broker, onde será habilitada a porta de dados seguros. Estou mantendo também a porta padrão. Além disso, devemos especificar os arquivos relacionados ao TLS. Meu arquivo de configuração (/etc/mosquitto/mosquitto.conf) ficou desse jeito:
#nao permitir acesso anonimo
allow_anonymous false
#...
autosave_interval 1800
#...
connection_messages true
#destino das msgs de log. Pode apontar pra quantas quiser, uma por linha
log_dest stderr
log_dest topic
#tipos de erro. Tem mais alguns nessa ultima versao, mas aqui ja me basta
log_type error
log_type warning
log_type notice
log_type information
log_type debug
#...
log_timestamp true
#arquivo de passwd
password_file /etc/mosquitto/dobitaobyte.pw
#arquivo de acl
acl_file /etc/mosquitto/dobitaobyte.acl
#para gravar os dados em disco
persistence true
#destino da base de dados.
persistence_location /opt/mosquitto/mosquitto_db
#nome para o arquivo de persistencia de dados
persistence_file mosquitto.db
#tempo para descarregar da memoria para o disco
persistent_client_expiration 1m
#um sinonimo de persistence, nao precisa dessa repeticao
retained_persistence true
#abre 1883 em localhost, apenas IPv4
listener 1883 192.168.1.200
#abre em todas as interfaces na 8883, IPv4 e IPv6 (e pode ter mais)
listener 8883 192.168.1.200
#certificados
#tls_version tlsv1
cafile /etc/mosquitto/ca_certificates/ca.crt
certfile /etc/mosquitto/certs/server.crt
keyfile /etc/mosquitto/certs/server.key
require_certificate false
Reinicie o serviço e verifique se houve algum erro. Normalmente é emitida uma mensagem quando há erros. De outro modo, apenas confirme com o status:
sudo su
service mosquitto stop
service mosquitto start
service mosquitto status
Os clients, sejam eles quais forem, deverão fazer uso do conteúdo do arquivo ca.crt. No teste, estou utilizando o mosquitto_pub e mosquitto_sub. Desse modo, não preciso ainda escrever um programa apenas para depurar se o broker está funcionando adequadamente.
Me subscrevi ao tópico /raspberry criado na ACL, usando a porta 1883 e em outro terminal, me subscrevi ao mesmo tópico, mas com SSL:
#Em um terminal:
mosquitto_sub -h 192.168.1.200 -u SEU_USUARIO -P SUA_SENHA -t '/raspberry/#'
#Em outro terminal:
mosquitto_sub -h 192.168.1.200 -d --cafile ca.crt -p 8883 -u SEU_USUARIO -P SUA_SENHA -t '/raspberry/#' --insecure
No caso, o uso de 'insecure' é para não validar o nome do servidor, já que está sendo feito local. Com um servidor contendo uma URL válida esse parâmetro não deve ser necessário.
Para publicar é bastante semelhante, incluindo apenas tópico e mensagem.
#Na porta 1883:
mosquitto_pub -h 192.168.1.200 -u SEU_USUARIO -P SUA_SENHA -t /raspberry/teste -m "sem TLS"
#No canal criptografado:
mosquitto_pub -d --cafile ca.crt -p 8883 -h 192.168.1.200 -u SEU_USUARIO -P SUA_SENHA -t '/raspberry/' -m 'com TLS' --insecure
Fiz o teste nos 4 terminais, como indicado:
Ok, funcionou. Mas quem garante que só não abri uma outra porta que não a 1883, sem criptografia? Vamos à prova.
Utilizando tcpdump, analisei o tráfego nas respectivas portas. Sem criptografia, tive que borrar a parte que mostra as credenciais. Circulei a área com o tópico e valor publicado:
Já com a criptografia implementada, não tem muito o que mostrar, pois não passa de um emaranhado de caracteres. Mas veja:
Se ainda tem alguma dúvida ou não sabe interpretar o tcpdump, recomendo esse artigo. Com isso, vimos como gerar certificado para aumentar a segurança nas transações dos dispositivos utilizando o protocolo MQTT.
O certificado é gerado com tempo de validade, depois precisa ser renovado. Apesar de não ser um trabalho constante, é repetitivo, por isso vou mostrar em outro artigo como automatizar a entrada de comandos com a criação de bots em shell script, só acompanhar!
Revisão: Ricardo Amaral de Andrade
Inscreva-se no nosso canal Manual do Maker no YouTube.
Também estamos no Instagram.
Autor do blog "Do bit Ao Byte / Manual do Maker".
Viciado em embarcados desde 2006.
LinuxUser 158.760, desde 1997.