MITM TPROXY Transparent Decrypt (Português (Brasil))
§1 O que é e quando usar
Seção intitulada “§1 O que é e quando usar”Cada um dos outros quatro modos de captura tem uma limitação:
| Modo | Como o tráfego é direcionado | Limitação |
|---|---|---|
| AgentBridge | Falsificação de DNS via /etc/hosts para um conjunto fixo de hosts |
somente os hosts de agentes de IDE registrados |
| Hosts personalizados | Falsificação de DNS via /etc/hosts por host |
uma entrada por host; sudo para editar os hosts |
| HTTP_PROXY | Variáveis de ambiente HTTP_PROXY/HTTPS_PROXY |
somente aplicativos que respeitam a variável de ambiente |
| Proxy para todo o sistema | Configurações de proxy do sistema operacional | altera o estado global; exige reversão |
A descriptografia transparente TPROXY direciona o tráfego na camada do kernel. Ela
marca novas conexões TCP locais de saída para uma porta de destino (por padrão, 443) na
cadeia mangle OUTPUT; uma ip rule redireciona os pacotes marcados para entrega local
e, ao reentrarem, o destino TPROXY de mangle PREROUTING os encaminha para um
listener IP_TRANSPARENT — que então encerra o TLS e captura o texto simples.
Use-a quando quiser capturar e descriptografar o tráfego de um processo que:
- se comunica com um host que o AgentBridge não registra, e
- não respeita
HTTP_PROXY, e - você não quer afetar com uma alteração de proxy para todo o sistema.
Como a interceptação ocorre no kernel, o processo de origem não precisa de nenhuma alteração de configuração — mas deve confiar na CA dinâmica instalada pelo OmniRoute (consulte §4).
§2 Requisitos
Seção intitulada “§2 Requisitos”| Requisito | Detalhes |
|---|---|
| SO | Apenas Linux — IP_TRANSPARENT é uma opção de socket exclusiva do Linux. O carregador retorna “unavailable” em todas as outras plataformas. |
| Privilégio | A capacidade CAP_NET_ADMIN para criar o socket transparente e aplicar regras de iptables/ip — na prática, execute como root. |
| Addon nativo | Um pequeno addon N-API (src/mitm/tproxy/native/transparent.c) deve ser compilado ou fornecido como prebuild. Consulte §3. |
| Módulos do kernel | iptables com suporte a TPROXY, mangle e correspondência de mark (validado com o kernel 6.8.0). |
Degradação elegante: se algum requisito estiver ausente (sistema não Linux, sem toolchain,
addon não compilado), o carregador do addon (src/mitm/tproxy/transparentSocket.ts::loadTransparentAddon)
retornará null em vez de lançar uma exceção. O status do modo de captura então informa
available: false, a opção no painel fica desabilitada com a dica
“A descriptografia TPROXY requer Linux + root + o addon nativo”, e o restante do
OmniRoute continua funcionando.
§3 O addon nativo IP_TRANSPARENT
Seção intitulada “§3 O addon nativo IP_TRANSPARENT”O módulo net do Node não consegue executar setsockopt(IP_TRANSPARENT) antes de bind(), como
o TPROXY exige (caso contrário, o kernel descarta os pacotes redirecionados). O addon
(src/mitm/tproxy/native/transparent.c, compilado por meio de binding.gyp) é um pequeno módulo
N-API que expõe três funções, utilizadas por meio de transparentSocket.ts:
| Função do addon | Operação no socket | Utilizada para |
|---|---|---|
createTransparentListener(ip, port) |
socket() + SO_REUSEADDR + IP_TRANSPARENT + bind() + listen(), retorna o fd bruto |
o listener de captura transparente (o Node adota o fd por meio de server.listen({ fd })) |
setSocketMark(fd, mark) |
setsockopt SO_MARK em um fd existente |
prevenção de loop (marca os próprios sockets do proxy) |
connectMarked(ip, port, mark) |
socket() + SO_MARK antes de um connect() não bloqueante, retorna o fd |
o encaminhamento upstream recriptografado (o SYN carrega a marca) |
O destino original é lido de socket.localAddress/localPort — o TPROXY
o preserva, portanto não há consulta SO_ORIGINAL_DST/NAT.
Compilando o addon
Seção intitulada “Compilando o addon”npm run build:native:tproxy # cd src/mitm/tproxy/native && node-gyp rebuild # -> native/build/Release/transparent.node- Durante
npm run build,scripts/build/build-tproxy-native.mjsexecutanode-gyp rebuild. Isso é exclusivo do Linux e não fatal — a ausência de uma toolchain apenas deixa o modo de captura indisponível. assembleStandalone.mjscopiabuild/Release/transparent.nodepara o pacote standalone;transparentSocket.tso resolve tanto em relação ao módulo quanto em relação ao cwd (<cwd>/src/mitm/tproxy/native/...).build/eprebuilds/são ignorados pelo git — o binário é compilado, nunca commitado.
O carregador verifica, em ordem de prioridade:
native/build/Release/transparent.node e, em seguida, native/prebuilds/transparent.node
(ambos em relação ao módulo e em <cwd>/src/mitm/tproxy/).
§4 A CA dinâmica por SNI e o instalador do repositório de confiança
Seção intitulada “§4 A CA dinâmica por SNI e o instalador do repositório de confiança”Atualização #6684: o servidor estático do AgentBridge (
src/mitm/server.cjs) agora compartilha esse mesmo padrão de arquitetura de CA/certificado de folha, em vez de usar um único certificado de folha autoassinado estático. Ele usa uma instância de CA distinta (src/mitm/cert/rootCa.ts, persistida em<DATA_DIR>/mitm/ca.key/ca.crt) e é instalado no slot preexistenteomniroute-mitm.crtdo repositório de confiança (substituindo ali o antigo certificado de folha único — sem necessidade de limpeza de confiança dupla), mantido totalmente separado do slotomniroute-tproxy-ca.crtdo próprio TPROXY, descrito abaixo. Novas instalações do AgentBridge recebem automaticamente o modelo de CA; uma instalação que já confiava no antigo certificado de folha estático continua usando-o até que o operador aceite explicitamente a mudança por meio deMITM_ROOT_CA_ENABLED=true(consultesrc/mitm/cert/migration.ts) — uma CA MITM confiável capaz de assinar um certificado de folha para qualquer host é substancialmente mais poderosa que o antigo certificado de folha com SANs fixos, portanto a mudança nunca ocorre silenciosamente em uma instalação que já tenha estabelecido essa confiança.
Historicamente, o certificado MITM estático do AgentBridge funcionava apenas porque o AgentBridge
falsifica o DNS de um conjunto fixo de hosts (agora unificado com o modelo abaixo). O TPROXY
intercepta hosts arbitrários, portanto seu listener deve apresentar um certificado de folha válido para
qualquer SNI solicitado pelo cliente — o mesmo requisito que o AgentBridge agora tem
para o conjunto completo de MITM_TOOL_HOSTS (9 entradas de ferramentas), em vez de apenas os 4
hosts do antigravity.
CA dinâmica (src/mitm/tproxy/dynamicCert.ts)
Seção intitulada “CA dinâmica (src/mitm/tproxy/dynamicCert.ts)”DynamicCertStore executa uma CA local (criada com base na dependência selfsigned) que:
- Gera uma CA de longa duração por meio de
generateMitmCa()(CN"OmniRoute MITM CA", validade de 10 anos,basicConstraints CA=true+keyUsage keyCertSign,cRLSign, RSA de 2048 bits / SHA-256). - Emite um certificado de folha por nome de host SNI sob demanda por meio de
issueLeafCert()(validade de 1 ano,subjectAltName= o host SNI) e armazena em cache umtls.SecureContextpor nome de host. - Expõe
createSNICallback()para o servidor que encerra o TLS (consulte §5). - Pode ser construído com uma
existingCapara manter a CA estável entre reinicializações (assim, o repositório de confiança não precisa ser reinstalado).
A chave privada da CA nunca sai da máquina.
Instalador do repositório de confiança (src/mitm/tproxy/caTrust.ts)
Seção intitulada “Instalador do repositório de confiança (src/mitm/tproxy/caTrust.ts)”O cliente interceptado deve confiar na CA dinâmica; portanto, iniciar o modo de captura
instala o certificado da CA no repositório de confiança do sistema operacional, em um slot dedicado —
omniroute-tproxy-ca.crt (constante TPROXY_CA_CERT_NAME) — mantido separado do
slot do certificado MITM estático (omniroute-mitm.crt), para que os dois nunca sobrescrevam
um ao outro.
installTproxyCa(caPem, sudoPassword?) detecta o diretório de âncoras da distribuição
(na ordem: primeiro no estilo Debian) e executa o comando de atualização correspondente:
| Diretório de âncoras | Comando de atualização |
|---|---|
/usr/local/share/ca-certificates |
update-ca-certificates |
/etc/ca-certificates/trust-source/anchors |
update-ca-trust |
/etc/pki/ca-trust/source/anchors |
update-ca-trust |
/etc/pki/trust/anchors |
update-ca-certificates |
A instalação coloca temporariamente o PEM em um arquivo temporário e, em seguida, executa (com privilégios) mkdir -p no diretório
de âncoras, usa cp para copiar o arquivo temporário para ele e executa o comando de atualização. uninstallTproxyCa()
remove apenas o slot dedicado (deixando intacto o certificado MITM estático) e
atualiza o repositório — uma operação sem efeito em sistemas que não sejam Linux.
Todos os comandos privilegiados são executados por meio de execFileWithPassword (src/mitm/systemCommands.ts)
— spawn com arrays de argumentos, sem shell e sem interpolação de strings (Regra Rígida nº 13).
Quando o processo está sendo executado como root (por exemplo, no VPS), o destino é executado diretamente e nenhuma senha
é necessária; em um desktop sem root, o sudoPassword é passado via sudo -S pela entrada padrão.
O
sudoPassworddo desktop é fornecido no corpo da solicitação POST para autorizar a instalação no repositório de confiança; ele é totalmente ignorado quando o processo está sendo executado como root.
§5 Como a descriptografia e a captura funcionam
Seção intitulada “§5 Como a descriptografia e a captura funcionam”O pipeline (todo em src/mitm/tproxy/):
aplicativo local ──TCP/443──▶ mangle OUTPUT marca a conexão (fwmark) ip rule → tabela de rotas local → lo mangle PREROUTING TPROXY → listener IP_TRANSPARENT (porta 8443) │ captureMode.ts: lê o destino original de socket.localAddress ▼ tlsCapture.ts: 1. Encerra o TLS do CLIENTE com um certificado leaf por SNI (dynamicCert) 2. http.Server interno analisa o texto simples descriptografado 3. captura → globalTrafficBuffer.push() com source: "tproxy" (sanitizeHeaders + maskSecret aplicados) 4. encaminha RECRIPTOGRAFADO ao destino original por um socket com marca de bypass (connectMarked, antirloop) │ ▼ upstream original (api.example.com)- Encerramento TLS (
createTlsCaptureServer): encapsula o socket bruto interceptado em umtls.TLSSocketno lado do servidor usando o callback de SNI da CA dinâmica e, em seguida, entrega o fluxo descriptografado a umhttp.Serverinterno (o truque padrão de encerramento MITM). Os tempos de vida dos sockets são limitados porMITM_IDLE_TIMEOUT_MS, para que um túnel travado não esgote os descritores de arquivo. - Captura (
handleDecryptedRequest): adiciona umInterceptedRequestcomsource: "tproxy", status inicial"in-flight", cabeçalhos processados porsanitizeHeaders()e corpos processados pormaskSecret()antes de entrarem no buffer. Depois, a entrada é atualizada com a resposta, os tamanhos e a latência. - Encaminhamento recriptografado (
createForward/realForward): recriptografa para o destino original. Por padrão,rejectUnauthorizedétrue(seguro por padrão) — o certificado upstream é verificado em relação ao SNI/Host solicitado pelo cliente, portanto o proxy rejeita exatamente o que o cliente original rejeitaria.
Antirloop (SO_MARK)
Seção intitulada “Antirloop (SO_MARK)”Como as regras marcam novas conexões locais de saída, o encaminhamento recriptografado do próprio proxy normalmente seria interceptado novamente — um loop infinito. O caminho de encaminhamento evita isso com uma marca de bypass no socket (SO_MARK):
realForwardabre seu socket upstream por meio deconnectMarked(ip, port, DEFAULT_BYPASS_MARK)—DEFAULT_BYPASS_MARK = 0x539— que define a SO_MARK antes deconnect(), fazendo com que o SYN do encaminhamento carregue a marca de bypass.- A regra
mangle OUTPUTexclui conexões que já carregam a marca de bypass (-m mark ! --mark <bypassMark>), portanto o encaminhamento do proxy não é marcado novamente e não volta a entrar no TPROXY.
Observação de implementação: o socket com a marca de bypass deve ser instalado no
createConnectiondo agente (https.request({ createConnection })é silenciosamente ignorado quando há um agente presente); caso contrário, o encaminhamento abriria um socket sem marca e o loop retornaria. Essa foi a correção antirloop validada de ponta a ponta.
§6 Segurança
Seção intitulada “§6 Segurança”| Controle | Detalhe |
|---|---|
| API somente para loopback | /api/tools/agent-bridge/tproxy é abrangida pelo prefixo /api/tools/agent-bridge/ em LOCAL_ONLY_API_PREFIXES (src/server/authz/routeGuard.ts). A restrição a loopback é aplicada antes da autenticação (Regras Rígidas nº 15 + nº 17) — um JWT vazado por meio de um túnel não pode iniciar a captura TPROXY, que aplica regras de iptables e instala uma CA no repositório de confiança por meio de processos filhos. |
| Slot de CA dedicado | A CA dinâmica é instalada em omniroute-tproxy-ca.crt, sem jamais sobrescrever o certificado MITM estático. |
| A chave da CA nunca sai do host | DynamicCertStore mantém a chave da CA na memória; ela não é exportada. |
| Mascaramento de segredos | maskSecret() nos corpos de requisições/respostas e sanitizeHeaders() nos cabeçalhos são executados antes de globalTrafficBuffer.push(). |
| Sem interpolação de shell | Todos os comandos iptables/ip/do repositório de confiança são executados por meio de execFile/execFileWithPassword com arrays de argumentos (Regra Rígida nº 13). |
| Verificação do certificado upstream | O encaminhamento com nova criptografia verifica o certificado upstream por padrão (rejectUnauthorized: true). |
| Sanitização de erros | As respostas de erro da rota passam por sanitizeErrorMessage() (Regra Rígida nº 12). |
A CA de MITM é um recurso poderoso. Uma CA considerada confiável pelo sistema operacional e capaz de assinar qualquer host significa que tudo o que o OmniRoute interceptar pode ser descriptografado. Ela é protegida pelo modo explícito de captura TPROXY, disponível somente localmente, desativado por padrão, e a entrada do repositório de confiança é removida quando você interrompe o modo.
§7 Aplicação / reversão transacional do firewall
Seção intitulada “§7 Aplicação / reversão transacional do firewall”Uma falha nunca deve deixar uma regra mangle ou uma rota obsoleta para trás. O construtor de comandos
(src/mitm/tproxy/commands.ts) e o executor (src/mitm/tproxy/setup.ts) garantem que
a reversão seja o inverso exato da aplicação, em ordem inversa.
applyTproxy(cfg) executa os comandos de aplicação em ordem; em caso de qualquer falha, ele executa uma
revertTproxy(cfg) completa de melhor esforço e relança o erro — assim, o firewall fica
totalmente aplicado ou totalmente revertido, nunca parcialmente aplicado. revertTproxy(cfg) executa os
comandos inversos em ordem inversa e ignora falhas (idempotente — pode ser chamada
incondicionalmente, por exemplo, pela limpeza repairMitm() do AgentBridge).
validateTproxyConfig(cfg) é executada antes de qualquer comando: as portas devem estar entre 1–65535,
mark/routeTable/bypassMark devem ser inteiros positivos, e bypassMark deve ser
diferente de mark (prevenção de loop).
Comandos de aplicação (em ordem)
Seção intitulada “Comandos de aplicação (em ordem)”ip rule add fwmark <mark> lookup <routeTable>ip route add local 0.0.0.0/0 dev lo table <routeTable>iptables -t mangle -A OUTPUT -p tcp --dport <dport> -m mark ! --mark <bypassMark> -j MARK --set-mark <mark>iptables -t mangle -A PREROUTING -p tcp --dport <dport> -m mark --mark <mark> -j TPROXY --on-port <onPort> --tproxy-mark <mark>A reversão os exclui na ordem inversa: PREROUTING -D, OUTPUT -D, ip route del, ip rule del.
A receita é baseada em OUTPUT porque o caso de uso de MITM é o tráfego de saída local (aplicativos no mesmo host), que o TPROXY somente em
PREROUTINGnão detecta —PREROUTINGdetecta apenas tráfego encaminhado. A cadeiaOUTPUTmarca novas conexões locais, aip ruleas redireciona para entrega local (lo), ePREROUTINGentão as encaminha para o listener transparente.
§8 Configuração
Seção intitulada “§8 Configuração”A solicitação de inicialização (POST /api/tools/agent-bridge/tproxy) aceita os seguintes
campos, validados por StartTproxyBodySchema (tproxy/route.ts). Todos são opcionais
e usam seus valores padrão quando omitidos:
| Campo | Tipo | Padrão | Observações |
|---|---|---|---|
| dport | int (1–65535) | 443 |
Porta TCP de destino a ser interceptada de forma transparente |
| mark | int (≥1) | 0x2333 |
Marca do firewall definida em OUTPUT, correspondida pela ip rule + PREROUTING |
| onPort | int (1–65535) | 8443 |
Porta à qual o listener transparente (IP_TRANSPARENT) se vincula |
| routeTable | int (≥1) | 233 |
ID da tabela de roteamento baseado em políticas que contém a rota local 0.0.0.0/0 |
| bypassMark | int (≥1, ≠ mark) |
0x539 |
A marca de bypass do socket (SO_MARK) que o proxy define em suas próprias conexões upstream; excluída em OUTPUT (prevenção de loop) |
| sudoPassword | string | — | Somente para desktops sem root: autoriza a instalação no armazenamento de confiança; ignorada quando executado como root |
Não há variáveis de ambiente para TPROXY — toda a configuração é feita pelo corpo da solicitação POST ou pelos valores padrão acima.
§9 Habilitação pelo Inspetor de Tráfego
Seção intitulada “§9 Habilitação pelo Inspetor de Tráfego”- Abra o Inspetor de Tráfego (
/dashboard/tools/traffic-inspector). - Na barra de ferramentas dos modos de captura, localize o botão ⚠ “Descriptografar TPROXY”
(
src/app/(dashboard)/dashboard/tools/traffic-inspector/components/CaptureModesToolbar.tsx). - Clique no botão. Ele chama
POST /api/tools/agent-bridge/tproxypor meio destartTproxyCaptureMode()(src/lib/inspector/tproxyCaptureApi.ts), que: cria a CA dinâmica, abre o listener transparente, aplica as regras de firewall e instala a CA no repositório de confiança do sistema operacional. - Durante a execução, o botão de alternância fica âmbar e mostra a contagem de interceptações em tempo real
(
· <interceptCount>). As solicitações interceptadas aparecem na lista de solicitações comsource: "tproxy". - Clique novamente para interromper —
DELETE /api/tools/agent-bridge/tproxypor meio destopTproxyCaptureMode()fecha o listener, desinstala a CA e reverte as regras de firewall.
O status do modo de captura (em execução / disponível / contagem de interceptações / porta do listener) vem
de GET /api/tools/agent-bridge/tproxy (getCaptureStatus() em
src/mitm/tproxy/captureManager.ts). Apenas uma sessão TPROXY é executada por vez —
a tentativa de iniciar uma segunda sessão é rejeitada com “O modo de captura TPROXY já está em execução”.
§10 Solução de problemas
Seção intitulada “§10 Solução de problemas”O botão de alternância está desabilitado
Seção intitulada “O botão de alternância está desabilitado”O addon nativo não pode ser carregado. Confirme se você está usando Linux, compilou o addon
(npm run build:native:tproxy) e o processo consegue carregar transparent.node.
isTransparentSocketAvailable() controla o botão de alternância; GET /api/tools/agent-bridge/tproxy
retorna available: false quando o addon está ausente.
Nada é capturado
Seção intitulada “Nada é capturado”- Confirme se o processo interceptado realmente se conecta à
dportconfigurada (o padrão é443). - Confirme se o processo confia na CA dinâmica. A CA é instalada como
omniroute-tproxy-ca.crt; aplicativos com seu próprio repositório de confiança (Firefox/Chrome NSS) também podem exigir que o certificado seja adicionado a esse repositório. - Execute o autoteste Diagnosticar do AgentBridge (consulte
AGENTBRIDGE.md) para verificar a confiança no certificado / a integridade do servidor.
Regras de firewall obsoletas após uma falha
Seção intitulada “Regras de firewall obsoletas após uma falha”revertTproxy() é o inverso exato da aplicação e é idempotente. A interrupção do
modo reverte as regras; se o OmniRoute tiver sido encerrado durante uma sessão, use a ação
Reparar do AgentBridge (POST /api/tools/agent-bridge/repair) para desfazer estados órfãos do
sistema (falsificação de DNS, CA raiz, proxy do sistema). As regras mangle e a rota do TPROXY também
são limpas automaticamente na reinicialização.
Loop infinito / o proxy intercepta seu próprio encaminhamento
Seção intitulada “Loop infinito / o proxy intercepta seu próprio encaminhamento”Este é o caso de prevenção de loop. Confirme se bypassMark é diferente de mark (a validação
garante isso) e se o encaminhamento usa connectMarked (ele usa em realForward).
Consulte §5 Prevenção de loop.
§11 Mapa do código-fonte
Seção intitulada “§11 Mapa do código-fonte”| Arquivo | Responsabilidade |
|---|---|
src/mitm/tproxy/commands.ts |
Criador puro de comandos de aplicação + reversão de iptables/ip; validateTproxyConfig |
src/mitm/tproxy/setup.ts |
Executor transacional de applyTproxy / revertTproxy (reversão em caso de falha) |
src/mitm/tproxy/transparentSocket.ts |
Carregador do addon nativo (loadTransparentAddon), createTransparentListenerFd, connectMarked, setSocketMark, isTransparentSocketAvailable |
src/mitm/tproxy/native/transparent.c |
Addon N-API: createTransparentListener (IP_TRANSPARENT), setSocketMark, connectMarked |
src/mitm/tproxy/native/binding.gyp |
Manifesto de compilação do node-gyp |
src/mitm/tproxy/dynamicCert.ts |
DynamicCertStore — CA dinâmica por SNI + cache de certificados finais |
src/mitm/tproxy/caTrust.ts |
Instalação/desinstalação no repositório de confiança do SO (installTproxyCa / uninstallTproxyCa, slot dedicado) |
src/mitm/tproxy/tlsCapture.ts |
Mecanismo de descriptografia com terminação TLS + encaminhamento recriptografado com prevenção de loop |
src/mitm/tproxy/captureMode.ts |
Orquestração do listener transparente; lê o destino original de socket.localAddress |
src/mitm/tproxy/captureManager.ts |
Ciclo de vida singleton: startCaptureMode / stopCaptureMode / getCaptureStatus |
src/app/api/tools/agent-bridge/tproxy/route.ts |
Rota GET / POST / DELETE (LOCAL_ONLY) |
src/lib/inspector/tproxyCaptureApi.ts |
Funções auxiliares de fetch do cliente (fetchTproxyStatus / startTproxyCaptureMode / stopTproxyCaptureMode) |
HagiCode
HagiCode é um ambiente de programação com agentes, fluxos estruturados, execução multiagente e visualizações Hero Dungeon.
Transforme ideias em software útil com um fluxo de trabalho com agentes mais inteligente, rápido e agradável.

- SmartFluxos estruturados transformam intenções em um caminho executável da ideia à entrega.
- EfficientFluxos multiagente mantêm pesquisa, implementação e revisão em andamento simultaneamente.
- FunO Hero Dungeon torna longas sessões de programação mais visuais e colaborativas.