mTLS na Prática: Da Modelagem de Ameaças a Ataques Reais em Servidores
Esta é a segunda parte de um ciclo sobre mTLS. Na primeira, abordamos a teoria: como funciona o handshake, contra quais ataques ele protege e onde é fundamentalmente ineficaz. Aqui, focaremos na prática. Analisaremos um cenário real: um homelab em um único servidor com Traefik e Dokploy. Percorreremos o caminho desde a modelagem de ameaças até tentativas concretas de atacar nosso próprio servidor, com comandos e explicações detalhadas.
Se você não leu a primeira parte, não se preocupe. Abaixo, há uma seção concisa com os conceitos essenciais, suficiente para acompanhar o restante.
Resumo: O que é mTLS e por que usá-lo?
Mutual TLS (mTLS) é uma extensão do protocolo TLS onde ambas as partes de uma conexão apresentam e validam certificados criptográficos. Se o cliente não apresentar certificados ou apresentar um certificado inválido, a conexão é encerrada no nível de transporte, antes de qualquer interação HTTP.
As principais razões para sua integração em um homelab incluem:
- Proteção nas "portas de entrada" (Drop antes do HTTP): Bloqueia acessos maliciosos antes mesmo que cheguem à camada de aplicação.
- Proteção de serviços sem login/senha embutidos: Garante acesso seguro a aplicações que não possuem mecanismos de autenticação nativos.
- Acesso seguro sem VPN: Permite acesso remoto seguro sem a necessidade de configurar e gerenciar uma VPN.
- "Exclusão" de listas de escaneamento por bots: Dificulta a detecção por bots que escaneiam a internet em busca de vulnerabilidades.
- Gerenciamento de acesso conveniente: Facilita o controle de quem pode acessar quais recursos.
Terminologia de mTLS:
- CA (Certificate Authority - Autoridade Certificadora): No contexto de mTLS, a organização utiliza sua própria CA. Ela cria um certificado raiz e assina os certificados de cliente. Diferente do TLS público, onde a CA (como Let's Encrypt) verifica a posse do domínio, a CA de mTLS está totalmente sob o controle do administrador. Em resumo, você cria um certificado e depois o distribui para os dispositivos que precisam de acesso.
- Certificado de Cliente: Um certificado X.509 instalado em um dispositivo ou navegador específico.
- Chave Privada: Usada durante o handshake TLS para provar a posse do certificado.
O que o mTLS protege:
| Tipo de Ataque | Como o mTLS Bloqueia | Eficácia |
|---|---|---|
| Man-in-the-Middle (MitM) | O atacante não possui a chave privada do cliente e não consegue completar o handshake TLS. | Alta |
| Credential Stuffing | Sem o certificado do cliente, o servidor não prossegue para HTTP, tornando a página de login inacessível. | Total |
| Brute Force/Senha | Da mesma forma, sem o certificado, não há acesso ao HTTP. | Total |
| Phishing (roubo de senha) | Mesmo com a senha, o atacante não consegue logar sem o certificado da vítima. | Alta |
| Spoofing/Impersonation | A identidade é vinculada ao certificado criptográfico, impossível de falsificar sem a CA. | Alta |
| Session Hijacking | O token de sessão pode ser vinculado ao certificado mTLS (certificate-bound tokens). | Média (depende da implementação) |
| L7 DDoS de bots sem certificado | Bots sem certificado são descartados no nível do handshake TLS, sem sobrecarregar a aplicação. | Alta |
| Descoberta de serviço (Shodan, Censys) | Servidores em modo STRICT não retornam banners para clientes não autorizados; o scanner vê um erro TLS. | Parcial |
| Vulnerabilidades de aplicação | Sem o certificado, é impossível interagir com o site/serviço. | Alta (enquanto o atacante não possuir o certificado) |
Antes de abrir o terminal
Antes de configurar, é crucial responder a quatro perguntas fundamentais:
- O que você tem? Desenhe um diagrama, mesmo que em papel. Quais serviços estão expostos externamente, quais funcionam apenas internamente, e como eles se comunicam? No meu caso, a configuração era: um único servidor, Traefik como ponto de entrada, Dokploy na porta 3000, PostgreSQL e Redis na rede Docker interna, com apenas as portas 80 e 443 expostas externamente.
- Quem usa? Um único usuário ou uma equipe representam modelos de segurança drasticamente diferentes. Um único usuário implica um certificado de cliente: gerenciamento simples, revogação rápida. Uma equipe exige um certificado para cada membro, um processo de emissão e revogação, e logs detalhados de quem acessou e quando.
- O que acontece se for invadido? Isso define o nível de "paranóia" necessário. Um homelab pessoal com experimentos é diferente de um painel de controle com segredos de produção de clientes.
- De quem você está se protegendo? Existem três níveis de ameaça reais: um bot/scanner aleatório (o mais comum), um ataque direcionado (alguém querendo especificamente acessar seu servidor) e um insider (alguém que já tem acesso). O mTLS lida bem com o primeiro nível, parcialmente com o segundo e não com o terceiro.
Estas são perguntas obrigatórias. Outras questões podem surgir, como a compatibilidade com seu stack tecnológico. O principal desafio é o reverse proxy e seu suporte a mTLS. É essencial encontrar um proxy com suporte completo a mTLS. A escolha do reverse proxy ideal dependerá do seu servidor específico, mas considere os seguintes pontos:
- Mecanismo de atualização de certificados e CRL: O proxy suporta atualização de dados sem reinicialização (Hot Reload)? Se você tem muitos certificados, a reinicialização da configuração (como no Nginx clássico) pode causar picos de carga ou micro-latências. Como funciona a "revogação de certificados" (Certificate Revocation)? No caso do Traefik, a revogação de certificados não é nativamente suportada, o que significa que um certificado revogado ainda pode funcionar. Uma solução paliativa é criar uma CA intermediária separada para cada certificado de cliente.
- Suporte a OCSP Stapling: A verificação de certificados em grandes listas CRL (arquivos) é lenta. Verifique se o proxy pode solicitar e armazenar em cache esses dados.
- Profundidade da verificação mTLS (Client Auth): Às vezes, uma simples "verificação de assinatura" não é suficiente. O proxy pode verificar a Certificate Chain (cadeia de confiança) até uma raiz específica? Ele pode verificar SAN (Subject Alternative Name) ou campos específicos no certificado do cliente para roteamento? Ele pode extrair dados do certificado e repassá-los para o backend em cabeçalhos (X-Client-Cert-DN)?
- Desempenho da criptografia: TLS consome recursos de CPU. É crucial configurar o proxy (e/ou o stack de proteção) corretamente para evitar sobrecarga a cada tentativa de conexão. Implemente proteções e limites de tentativas de conexão para mitigar ataques de DoS/DDoS na camada TLS.
- Observabilidade: Você precisa saber por que uma conexão foi encerrada. Um bom proxy deve fornecer métricas detalhadas: número de erros TLS, recusas por expiração, recusas por certificado revogado.
Estes são requisitos essenciais para mTLS. Se algum ponto não funcionar, será necessário encontrar soluções alternativas.
Cenário Real
Um mini-homelab para gerenciar Docker e outros serviços/ferramentas de GitHub, etc. Abaixo, um screenshot onde o stack foi escolhido e testado quanto à resistência a ataques típicos, mas com suas desvantagens.
Após testar um número considerável de ataques, o único vetor de ataque viável encontrado com o stack atual é DoS/DDoS na camada TLS e roubo de certificados. Um certificado autoassinado não funcionará se a CA estiver configurada corretamente, pois o servidor aceitará apenas certificados assinados pela sua CA. Testamos isso e, sem o certificado correto, a conexão é interrompida no handshake.
Um pouco sobre o stack: Dokploy atua como plataforma de gerenciamento para Docker e repositórios (e outros serviços). O Webmin está planejado para ser usado como ferramenta de gerenciamento do próprio servidor (não totalmente, mas é um começo), por isso está presente, mas com um aviso: o acesso à internet deve ser muito bem protegido (para o Webmin) ou completamente bloqueado. Também vale mencionar que, neste cenário, todas as ferramentas, serviços e contêineres devem estar sob mTLS, pois é um homelab onde o acesso é restrito a uma única pessoa com 1-3 dispositivos (telefone, PC e talvez outro para acessar seus serviços).
Este stack também tem suas desvantagens. Por exemplo, se você decidir remover o Traefik (e instalar Nginx), também precisará remover o Dokploy devido à sua integração nativa com o Traefik (algumas funcionalidades deixarão de funcionar). Portanto, ao "construir seu servidor", é importante considerar o que você ganha e o que perde.
Segurança
Chegamos à parte mais interessante: testar a proteção com base no nosso cenário. Quais ferramentas usar e o que verificar?
O mais importante é o firewall, e precisamos verificar o que está acessível da internet. Recomendo usar o nmap para isso. Idealmente, tudo deve estar fechado, exceto as portas 80/443. "Portas específicas" (como SSH ou outras) devem ser cuidadosamente protegidas. No meu caso, não uso SSH, apenas 80/443. O Docker gerencia o iptables diretamente e contorna o UFW (ou outro firewall). Isso significa que, mesmo com o UFW configurado corretamente, o Docker pode abrir portas externamente através de suas próprias regras, sem que o UFW saiba. Portanto, o bloqueio deve ser feito através da cadeia DOCKER-USER. Este é um método confiável para fechar portas do Docker. Exemplo abaixo:
bash# Permitir redes Docker e localhost iptables -I DOCKER-USER 1 -p tcp -s 172.16.0.0/12 --dport 3000 -j ACCEPT iptables -I DOCKER-USER 2 -p tcp -s 127.0.0.1 --dport 3000 -j ACCEPT # Bloquear todos os outros iptables -I DOCKER-USER 3 -p tcp --dport 3000 -j DROP # Salvar regras para não serem perdidas após reinicialização apt install iptables-persistent -y netfilter-persistent save
Como verificar quais portas estão abertas após essas configurações? Use nmap com os seguintes comandos:
bash# Rápido – top 1000 portas nmap --top-ports 1000 seu-ip # Verificação completa de todas as 65535 portas (levará ~2 minutos) nmap -p- -T4 seu-ip
No nosso caso, o resultado após a configuração será apenas as portas 80/443 abertas.
O mTLS está funcionando?
Primeiramente, certifique-se de que todas as funcionalidades estão operando corretamente: o certificado está sendo criado corretamente, um certificado revogado não funciona, etc. – tudo relacionado ao mTLS.
O acesso aos serviços está configurado corretamente?
Idealmente, o servidor não deve responder sem um certificado. Exemplo: você adicionou acesso mTLS ao seu serviço/domínio – o serviço sem mTLS não responderá. Correto. Mas se você fizer requisições para o IP do seu servidor, ele responderá, pois o mTLS não está fechado. Isso é incorreto, pode ser uma falha de segurança e deve ser corrigido!
Como corrigir essa falha?
No meu cenário, adicionei um roteador "catch-all" que rejeitará todas as requisições que não forem para o domínio, aplicando mTLS globalmente no entrypoint e no firewall.
Tentativas de Ataque
Aqui estão os tipos de ataques usados para testar o servidor:
-
Acesso por IP direto – deve retornar 403.
bashcurl -sk -o /dev/null -w "%{http_code}\n" https://seu-ipExplicação: Envio de requisições para o IP, ignorando o domínio, para verificar se o servidor não responde sem o domínio. Resultado:
403. Indica que a conexão existe, mas o acesso é negado. -
Substituição do cabeçalho Host – deve retornar 421.
bashcurl -sk -o /dev/null -w "%{http_code}\n" \ -H "Host: seu-dominio" https://seu-ipExplicação: Acessamos o IP, mas falsificamos os cabeçalhos para verificar se é possível contornar o mTLS apenas especificando o domínio correto no cabeçalho.
421significa que o servidor exigiu uma conexão direta. -
Domínio sem certificado de cliente – deve interromper o TLS.
bashcurl -vk https://seu-dominioExplicação: Verificação comum para saber se é possível acessar sem o certificado de cliente.
-
TLS Downgrade – deve rejeitar a conexão.
bashcurl -sk --tls-max 1.2 -o /dev/null -w "%{http_code}\n" https://seu-dominio curl -sk --tls-max 1.1 -o /dev/null -w "%{http_code}\n" https://seu-dominioExplicação: Tentativas de forçar a negociação de versões TLS antigas. O servidor deve aceitar apenas TLS 1.3.
-
Tentativa de acesso a caminhos – todos devem retornar
000(TLS é interrompido antes do HTTP).bashfor path in /admin /.env /api /dashboard /health /metrics; do code=$(curl -sk --max-time 3 -o /dev/null -w "% {http_code}" https://seu-dominio$path) echo "$code $path" done -
Endpoints internos do Traefik – todos devem retornar 403.
bashfor path in /dashboard/ /api/ /api/rawdata /metrics /ping; do code=$(curl -sk --max-time 3 -o /dev/null -w "% {http_code}" https://seu-ip$path) echo "$code $path" done -
Flood sem certificado.
bash# wrk – HTTP/2 flood wrk -t4 -c100 -d30s https://seu-dominio # Resultado esperado: 0 requests, ~2000+ read errors # h2load – HTTP/2 rapid reset apt install nghttp2-client -y h2load -n 100 -c 10 https://seu-ip # Resultado esperado: 100 failed, 0 succeededExplicação: Usando
wrkeh2load, criamos múltiplas conexões simultâneas sem certificado. Isso testa o comportamento do servidor sob carga. Todas as conexões devem falhar. -
Cabeçalhos de resposta:
bashsudo curl -sk \ --cert /path/to/client.crt \ --key /path/to/client.key \ -I https://seu-dominio | grep -iE "server|x-powered|strict-transport|x-frame"
É recomendável realizar esses testes a partir de outro dispositivo (como um telefone via Termux) e seguir as recomendações de um auditor TLS.
bashapt install testssl.sh -y testssl https://seu-dominio
O que observar idealmente:
- SSLv2/3, TLS 1.0/1.1/1.2: não oferecidos
- TLS 1.3: oferecido (OK)
- Forward Secrecy: oferecido (OK)
- Heartbleed, POODLE, BEAST: não vulnerável
- Rating: A+
Resta verificar se o Fail2ban está funcionando. Podem existir outros vetores de ataque (específicos para este stack), então estes são o mínimo para verificação. Você também pode usar ferramentas DAST para encontrar problemas no servidor, mas tenha cuidado ao usá-las! (Você pode aprender sobre ferramentas DAST aqui).
Conclusão
Temos uma boa proteção com consumo mínimo de recursos. Através do painel Dokploy, é possível monitorar e visualizar requisições ao servidor. Pelos resultados dos testes, o stack resiste a tudo que foi "lançado": requisições sem certificado, falsificação de cabeçalhos, TLS downgrade, tentativas de acesso a caminhos – tudo é interrompido no handshake. O Traefik não expõe endpoints internos, o acesso por IP direto retorna 403, e o acesso por domínio sem certificado interrompe o TLS.
Os dois vetores de ataque reais que permanecem são DoS na camada de handshake TLS e roubo de certificado. Isso é parcialmente mitigado pelo Fail2ban e rate limiting, mas não há proteção completa. Uma limitação do stack é a dependência nativa do Dokploy no Traefik – se você quiser mudar o proxy, terá que mudar a plataforma. O Webmin está presente, mas é melhor não expô-lo à internet. O stack é projetado para uma pessoa com 1-3 dispositivos; adaptá-lo para uma equipe também é possível.
Em última análise, o mTLS é uma ferramenta. Como qualquer ferramenta, funciona bem apenas quando você entende por que a está usando.
Fontes e Recomendações:
- Segundo cenário: Kubernetes corporativo. Um cluster Kubernetes, uma equipe, Istio Service Mesh, rotação automática de certificados a cada 24 horas, SPIFFE ID em vez de CN, problemas de falha em cascata durante a reinicialização do cluster. São escalas, riscos e ferramentas diferentes. Anna Luchnik detalha este cenário em um artigo da DevOps Conf – recomendo a leitura.
- Primeira parte do artigo sobre mTLS: [Link para a primeira parte]
- OpenSSL: Geração de CA, certificados
- Gerenciamento simplificado de certificados mTLS para o stack do artigo: [Link para a ferramenta]
© 2026 ООО "МТ ФИНАНС"
Tags: server, homelab, gerenciamento-de-projetos, mtls, zero-trust, redes, protecao-de-site, protecao-ddos, protecao-bots, ruvds_artigos
Hubs: Blog da empresa RUVDS.com Segurança da Informação Criptografia Otimização de Servidores Administração de Servidores
