ProxynetProxynet

O que é um proxy MITM? Guia de Charles, Fiddler e mitmproxy

Publicado:

15 min de leitura

Acar Diveroli
Autor: Acar Diveroli
Painéis de requisição e resposta 403 abertos como um envelope, um cadeado aberto no vão e um selo azul de CA local no arco

O seu scraper recebe um 403 em uma página de categoria que abre sem problema no navegador, e o erro não diz nada além do código de status. Lado a lado, a requisição do navegador e a do Python mostrariam a diferença em um minuto, mas o HTTPS mantém as duas lacradas. Um proxy MITM no seu próprio computador abre esse lacre só para você.

Este guia explica como um proxy MITM lê HTTPS, compara Charles, Fiddler e mitmproxy com as condições de licença de 2026 e trata do certificado raiz, dos seus próprios apps móveis, de uma configuração em Python testada e do encadeamento com um proxy upstream. Tudo parte do princípio de que o dispositivo e o app são seus, ou de que você tem permissão por escrito para testar o sistema.

O que é um proxy MITM?

“Man-in-the-middle” (homem no meio) é o nome de um ataque: alguém se coloca entre duas partes sem que elas saibam e lê o que elas enviam. Um proxy MITM usa a mesma posição para depuração. Você instala a ferramenta, o tráfego é seu e você mesmo confia no certificado dela, então ninguém é enganado. Empresas usam a técnica para inspeção TLS nos computadores dos funcionários; esse lado fica para proxy vs firewall.

Um forward proxy comum (como funciona um servidor proxy) vê só o host de destino de uma requisição HTTPS, pela linha CONNECT example.com:443, e depois transporta bytes criptografados. Um proxy MITM encerra a conexão criptografada na sua máquina, então vê a URL completa, cada cabeçalho e o corpo.

Como um proxy MITM abre o tráfego HTTPS?

A RFC 9110 descreve um túnel como um repasse cego, que passa as mensagens adiante sem alterá-las. Um proxy comum segue essa regra depois do CONNECT; um proxy MITM a quebra de propósito, para os clientes que confiam no certificado dele. Seguindo a descrição do fluxo feita pelo mitmproxy:

  1. O cliente envia CONNECT example.com:443 para a ferramenta local.
  2. A ferramenta responde 200 Connection Established, como se tivesse aberto o túnel.
  3. O cliente inicia o handshake TLS e informa o host no campo SNI.
  4. A ferramenta se conecta a esse host por TLS e lê os nomes (CN e SAN) do certificado do servidor.
  5. Ela cria um certificado com esses nomes e o assina com o seu certificado raiz local (a CA, autoridade certificadora).
  6. Se o cliente confia nessa CA, o handshake termina, e a ferramenta lê o tráfego em texto puro antes de criptografá-lo de novo em direção ao servidor.

Se o cliente não confia na CA, o passo 6 falha com um erro de certificado, como deve ser. Um gateway da Proxynet nunca executa o passo 5: ele repassa o túnel CONNECT às cegas, por isso um Proxies HTTPS não precisa de certificado raiz no seu dispositivo.

Comparação entre Charles, Fiddler e mitmproxy

Com base nas páginas dos próprios fornecedores em setembro de 2026; só modelos de licença, sem preços.

FerramentaLicençaPlataformasInterfacePorta padrãoProxy upstreamAutomação
CharlesLicença de usuário paga após 30 dias de testeWindows, macOS, LinuxApp de desktopGeralmente 8888HTTP, HTTPS e SOCKS; autenticação Basic ou NTLMBreakpoints, Rewrite, Map Local
Fiddler EverywhereAssinatura, 10 dias de testeWindows, macOS, LinuxApp de desktop8866String de proxy manual; autenticação Kerberos, Negotiate ou NTLMRules
Fiddler ClassicSó uso não comercial desde 3 de agosto de 2026Só WindowsApp de desktop8888Não tratado aquiFiddlerScript
mitmproxyOpen source, MITWindows, macOS, LinuxTerminal, navegador (mitmweb), linha de comando (mitmdump)8080--mode upstream: com upstream_auth (Basic)Addons em Python, CI

O Charles e o Fiddler Everywhere são indicados para equipes de QA de apps móveis que editam requisições em uma janela; o mitmproxy, para desenvolvedores que querem a verificação em uma suíte de testes ou no CI, onde cada passo é uma função Python. O Burp Suite é voltado para testes de segurança, que ficam fora deste guia.

O que é o Charles Proxy e quando escolhê-lo?

O Charles é um app de desktop que você pode testar por 30 dias antes de comprar uma licença de usuário. Ele descriptografa só os hosts da sua lista de SSL Proxying (* significa todos os hosts) e encaminha o restante do tráfego HTTPS sem abrir. Um testador aponta o proxy do Wi-Fi do iPhone para o notebook e a porta 8888, permite o aparelho quando o Charles pergunta e depois usa Breakpoints para editar requisições, Map Local para responder a partir de um arquivo e o throttling (limitação de banda) para simular uma rede lenta.

O que é o Fiddler? Classic e Everywhere

O Fiddler Classic roda só no Windows, não é mais desenvolvido e tem o FiddlerScript. Desde 3 de agosto de 2026, a licença dele permite só uso não comercial; os usuários comerciais tiveram até 17 de setembro de 2026 para migrar, e não existe licença paga do Classic.

O Fiddler Everywhere é o produto comercial: Windows, macOS e Linux, assinatura depois de 10 dias de teste, suporte a HTTP/2 e TLS 1.3, e porta 8866. Você ativa a captura de HTTPS, confia no certificado raiz dele e filtra as sessões por host.

O que é o mitmproxy? Três interfaces e addons em Python

O mitmproxy tem licença MIT; a versão 12.2.3 (12 de maio de 2026) exige Python 3.12 ou mais recente. Ele traz o mitmproxy (visão no terminal), o mitmweb (visão no navegador) e o mitmdump (sem interface, para scripts e CI), todos na porta 8080 por padrão.

Na primeira execução, ele cria a sua CA em ~/.mitmproxy, única para aquela instalação: a chave privada (mitmproxy-ca.pem) fica ao lado dos arquivos de certificado para cada plataforma (mitmproxy-ca-cert.pem, .p12, .cer). Com o proxy configurado em um dispositivo, mitm.it oferece o arquivo certo e os passos de instalação. Um addon é um arquivo Python cujas funções têm o nome de eventos como response.

Por que é preciso um certificado raiz, e ele é seguro?

Quem tem a chave privada de uma CA pode criar um certificado que parece válido para qualquer site em todos os dispositivos que confiam nela. O risco está nessa chave, não na ferramenta:

  • Só uma CA gerada pela sua própria ferramenta. O nosso guia sobre a segurança de proxies gratuitos diz para não instalar um certificado que um serviço de proxy pede, e isso continua valendo: uma CA remota permite que um estranho leia o seu tráfego. Uma ferramenta no seu próprio computador é diferente, porque a chave dela nunca sai da sua máquina.
  • Só em dispositivos de teste, só durante o teste. Não compartilhe nem faça commit de ~/.mitmproxy, e remova a CA ao terminar.
  • Mantenha as verificações da ferramenta ligadas. A opção ssl_insecure do mitmproxy pula a verificação de certificado em direção ao servidor, e o texto de ajuda dela avisa que isso deixa o próprio mitmproxy exposto a interceptação.

Para remover a CA:

  • Windows: certmgr.msc > Autoridades de Certificação Raiz Confiáveis > Certificados.
  • macOS: apague o certificado da ferramenta no app Acesso às Chaves.
  • iPhone: Ajustes > Geral > Gerenciamento de Dispositivo e VPN > o perfil > Remover Perfil.
  • Android (Pixel): Configurações > Segurança e privacidade > Mais configurações de segurança > Criptografia e credenciais > Credenciais do usuário; em outros fabricantes, o caminho muda antes dos dois últimos passos.

Ver o tráfego do seu próprio app no Android e no iPhone

Aponte o proxy do Wi-Fi do celular para o endereço IP do seu computador e a porta da ferramenta, usando as configurações de proxy no Android ou as configurações de proxy no iPhone.

Android. Segundo a documentação da configuração de segurança de rede, apps voltados ao Android 7.0 (API de nível 24) ou mais recente confiam por padrão só nas CAs do sistema, então o seu app pode falhar com um erro de TLS enquanto o navegador funciona. No seu próprio app, adicione um bloco debug-overrides:

xml
<!-- res/xml/network_security_config.xml -->
<network-security-config>
    <debug-overrides>
        <trust-anchors>
            <certificates src="user" />
        </trust-anchors>
    </debug-overrides>
</network-security-config>

Referencie o arquivo com android:networkSecurityConfig="@xml/network_security_config" no manifesto. O Android ignora o bloco quando android:debuggable é false, então um build de release mantém as regras normais de confiança.

iPhone. Depois de instalar o perfil, ative a confiança total em Ajustes > Geral > Sobre > Certificados Confiáveis.

Pinning. Um app que faz pinning de certificados recusa o certificado da ferramenta. No seu próprio app, ajuste o pinning no build de teste; no app de outra pessoa, o pinning é uma decisão do desenvolvedor, e este guia para aí.

Interceptar, editar e reenviar requisições

As três ferramentas permitem pausar uma requisição e mudar um cabeçalho antes que ela saia, responder a uma requisição com um arquivo local para testar uma tela de erro e enviar de novo uma requisição salva, de modo que um bug que aparece uma vez por dia pode ser repetido quando você quiser. No mitmproxy, -w flows.mitm salva os fluxos e -C flows.mitm os reenvia. Reenvie só para a sua própria API ou para um endpoint que você tenha permissão para testar, dentro dos limites de taxa dele.

Para a requisição em segundo plano de uma página web, o DevTools basta (como encontrar a requisição XHR); a ferramenta local é para scripts e apps.

Depurar um scraper em Python com um proxy MITM

De volta ao 403: passamos o script pelo mitmdump, registramos cada resposta e imprimimos os detalhes da requisição em cada erro. Testado com Python 3.13, mitmproxy 12.2.3 e Requests 2.34.2 (pip install mitmproxy requests).

O addon, debug_addon.py, imprime uma linha por resposta e, em 4xx e 5xx, os cabeçalhos que costumam diferir dos de um navegador, se um cookie foi enviado e o início do corpo:

python
"""Addon do mitmdump: uma linha por resposta, detalhes da requisição em cada 4xx e 5xx."""
from mitmproxy import http

WATCH = ("User-Agent", "Accept", "Accept-Language", "Accept-Encoding")


def response(flow: http.HTTPFlow) -> None:
    req, resp = flow.request, flow.response
    print(f"{resp.status_code} {req.method} {req.pretty_url}")
    if resp.status_code < 400:
        return
    for name in WATCH:
        print(f"    {name}: {req.headers.get(name, '(not sent)')}")
    print(f"    Cookie: {'sent' if 'Cookie' in req.headers else 'not sent'}")
    body = resp.get_content(strict=False) or b""  # descomprimido se vier em gzip ou br
    print(f"    body: {body[:300].decode('utf-8', 'replace')!r}")

O script, scraper_debug.py, usa o proxy só quando DEBUG_PROXY está definida e confia na CA local por meio de verify. A documentação do Requests avisa que verify=False deixa a aplicação vulnerável a ataques MitM, por isso ele nunca aparece aqui:

python
"""Busca páginas com Requests; defina DEBUG_PROXY para passá-las por um mitmdump local."""
import os
import sys
from pathlib import Path

import requests

DEBUG_PROXY = os.environ.get("DEBUG_PROXY")  # ex.: http://127.0.0.1:8080
MITM_CA = Path.home() / ".mitmproxy" / "mitmproxy-ca-cert.pem"

session = requests.Session()
session.headers.update({
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
                  "(KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36",
    "Accept-Language": "en-GB,en;q=0.9",
})


def request_options():
    options = {"timeout": (5, 30)}  # (conexão, leitura) em segundos
    if DEBUG_PROXY:
        if not MITM_CA.is_file():
            sys.exit(f"{MITM_CA} not found: start mitmdump once, it creates the CA there.")
        # Passado por requisição: um valor em Session.proxies pode ser sobrescrito por HTTPS_PROXY.
        options["proxies"] = {"http": DEBUG_PROXY, "https": DEBUG_PROXY}
        options["verify"] = str(MITM_CA)  # confia na CA local, nunca verify=False
    return options


def fetch(url):
    try:
        return session.get(url, **request_options())
    except requests.exceptions.SSLError as exc:
        sys.exit(f"TLS check failed for {url}: is {MITM_CA} the CA of the "
                 f"mitmdump that is running?\n{exc}")
    except requests.exceptions.ProxyError as exc:
        sys.exit(f"Debug proxy {DEBUG_PROXY} did not answer: is mitmdump running?\n{exc}")


if __name__ == "__main__":
    for url in sys.argv[1:] or ["https://httpbin.org/headers"]:
        resp = fetch(url)
        print(resp.status_code, url)
        for name, value in resp.request.headers.items():
            print(f"    {name}: {value}")

Inicie o mitmdump só no endereço de loopback:

bash
mitmdump --listen-host 127.0.0.1 -p 8080 -s debug_addon.py -w flows.mitm

Depois rode o script em um segundo terminal (no PowerShell, defina antes $env:DEBUG_PROXY = "http://127.0.0.1:8080"):

bash
DEBUG_PROXY=http://127.0.0.1:8080 python scraper_debug.py https://httpbin.org/headers https://httpbin.org/status/403

A janela do mitmdump imprimiu isto (linhas de conexão removidas):

text
200 GET https://httpbin.org/headers
403 GET https://httpbin.org/status/403
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/140.0.0.0 Safari/537.36
    Accept: */*
    Accept-Language: en-GB,en;q=0.9
    Accept-Encoding: gzip, deflate, br
    Cookie: not sent
    body: ''

Agora abra a página em um navegador configurado com o mesmo proxy. Accept: */* contra o text/html,... do navegador, ou um cookie ausente de uma página anterior, são achados típicos; o segundo significa que o script pulou uma etapa (sessões e cookies em Python). Se o site recusa de propósito clientes que não são navegadores, essa é a resposta dele: use a API do site ou peça permissão.

Um arquivo de CA errado interrompeu o script com CERTIFICATE_VERIFY_FAILED e a nossa dica. mitmdump --set server=false -C flows.mitm -s debug_addon.py reenviou as duas requisições e terminou sem abrir uma porta de escuta.

O servidor vê o handshake TLS da ferramenta, não o do seu script, então um site que verifica fingerprints TLS pode responder de outro jeito enquanto a ferramenta está ligada; compare com uma execução sem DEBUG_PROXY. As novas tentativas para 429 estão em códigos de status HTTP no web scraping, as variáveis de ambiente em proxy no wget, a rotação em como rotacionar proxies em Python e a escolha de biblioteca em HTTPX, Requests ou AIOHTTP.

Testar de outro país: encadear a ferramenta local a um proxy

Para ver os preços que o seu app mostra a um usuário na Alemanha, envie o tráfego do dispositivo para a ferramenta MITM local (onde acontece a descriptografia), dali para um proxy upstream e depois para o destino. Em destinos HTTPS, o proxy upstream só transporta o túnel criptografado de novo; a Proxynet não o descriptografa.

mitmproxy. O modo upstream encaminha cada requisição, e upstream_auth adiciona autenticação Basic:

bash
mitmdump --listen-host 127.0.0.1 --mode upstream:http://pr.proxynet.io:8000 --set upstream_auth=user:pass -s debug_addon.py

Testamos isso contra um proxy local que exige senha. Com uma senha errada, o script recebeu um 502 do mitmdump, e o log dele mostrou a causa: o upstream recusou o CONNECT com 407.

Charles. O recurso External Proxies aceita endereços separados para HTTP, HTTPS e SOCKS, com autenticação Basic ou NTLM e uma lista de exceções com curingas.

Fiddler Everywhere. Em Settings > Gateway você informa uma string de proxy manual, e a documentação lista Kerberos, Negotiate e NTLM para a autenticação no upstream, não usuário e senha. Com a Proxynet, autorize em vez disso o endereço IP do seu computador (user:pass e whitelist de IP).

Use um Proxies móveis para um IP de operadora ou um Proxies residenciais para uma conexão residencial; o cenário completo está na nossa página de teste de apps.

Para que se usa um proxy MITM?

Erros comuns

  • Deixar a CA instalada. Quem obtiver a chave depois pode se passar por qualquer site para aquele dispositivo.
  • Publicar código com verify=False. Aponte verify para o arquivo da CA.
  • Esperar que um app Android confie em uma CA de usuário. Apps voltados à API de nível 24+ a ignoram fora de um build de debug que a permita.
  • Esquecer o SSL Proxying para o host no Charles. Você vê entradas CONNECT criptografadas e nenhum conteúdo.
  • Escutar em todas as interfaces. Sem --listen-host, o mitmdump escutou em 0.0.0.0 e :: no nosso teste; use 127.0.0.1, a menos que um celular precise se conectar.
  • Compartilhar arquivos de fluxo sem cuidado. Eles guardam cookies e cabeçalhos.
  • Usar o Fiddler Classic no trabalho depois de agosto de 2026. A licença dele é só para uso não comercial.

Guia de decisão

NecessidadeRecomendação
Comparar a requisição de um scraper com a do navegadormitmproxy com um addon pequeno; verify do Requests apontado para o arquivo da CA
Editar requisições em uma janela para QA de apps móveisCharles ou Fiddler Everywhere
Fiddler para trabalho comercial no WindowsFiddler Everywhere ou outra ferramenta, não o Fiddler Classic
Tráfego HTTPS do seu próprio app Androiddebug-overrides só no build de debug
Testar o seu app como um usuário de outro paísEncadear a ferramenta local a um proxy móvel ou residencial (teste de apps)
Encontrar a requisição em segundo plano de uma página webA aba Network do DevTools; não é preciso ferramenta MITM

Perguntas frequentes

No seu próprio dispositivo e app, ou em um sistema que você tem permissão por escrito para testar, é uma ferramenta de depuração. Ler o tráfego de outras pessoas às escondidas é outra coisa. Sobre scraping, veja web scraping é legal?.

O mitmproxy é seguro?

A ferramenta é open source e roda localmente. O risco é a chave privada da CA em ~/.mitmproxy: mantenha essa chave privada, instale a CA só em dispositivos de teste e remova a CA depois.

O Fiddler Classic ainda é gratuito, e qual a diferença para o Fiddler Everywhere?

Desde 3 de agosto de 2026, o Fiddler Classic é gratuito só para uso não comercial; ele roda no Windows e não é mais desenvolvido. O Fiddler Everywhere é o produto pago e multiplataforma, com suporte a HTTP/2 e TLS 1.3.

Existe alternativa gratuita ao Charles Proxy?

O mitmproxy é open source e roda nas mesmas plataformas; o mitmweb dá a ele uma visão no navegador. O próprio Charles tem 30 dias de teste.

Instalei o certificado no Android. Por que o tráfego do meu app ainda não aparece?

Apps voltados à API de nível 24 ou mais recente confiam por padrão só nas CAs do sistema. Permita CAs de usuário no build de debug do seu próprio app com debug-overrides, e ajuste o pinning no build de teste se o app fizer pinning de certificados.

Qual a diferença entre um proxy MITM, um proxy comum e uma VPN?

Um proxy comum e uma VPN transportam o tráfego criptografado sem lê-lo e mudam o seu IP de saída (proxy vs VPN). Um proxy MITM abre esse tráfego no seu computador e mantém o seu IP, a menos que seja encadeado a um proxy upstream.

Em resumo

Um proxy MITM é uma ferramenta para ler o seu próprio tráfego, com uma CA que fica local, temporária e só em dispositivos de teste. O Charles e o Fiddler Everywhere combinam com trabalho em uma janela; o mitmproxy combina com scripts e CI. Quando um teste precisa vir de outro país, encadeie a ferramenta local a um proxy upstream, começando pela nossa página de teste de apps.