MITM TPROXY Transparent Decrypt (Español)
§1 Qué es y cuándo usarlo
Sección titulada «§1 Qué es y cuándo usarlo»Los otros cuatro modos de captura tienen una limitación cada uno:
| Modo | Cómo se dirige el tráfico | Limitación |
|---|---|---|
| AgentBridge | Falsificación DNS mediante /etc/hosts para un conjunto fijo de hosts |
solo los hosts registrados del agente del IDE |
| Hosts personalizados | Falsificación DNS mediante /etc/hosts por host |
una entrada por host; se necesita sudo para editar hosts |
| HTTP_PROXY | Variables de entorno HTTP_PROXY/HTTPS_PROXY |
solo las aplicaciones que respetan la variable de entorno |
| Proxy de todo el sistema | Configuración del proxy del sistema operativo | modifica el estado global; es necesario revertirlo |
En cambio, el descifrado transparente TPROXY dirige el tráfico en la capa del kernel. Marca
las nuevas conexiones TCP salientes locales a un puerto objetivo (de forma predeterminada, 443) en la
cadena mangle OUTPUT; una regla ip rule redirige los paquetes marcados a la entrega local
y, al volver a entrar, el objetivo TPROXY de mangle PREROUTING los entrega a un
listener IP_TRANSPARENT, que termina TLS y captura el texto sin cifrar.
Úselo cuando quiera capturar y descifrar el tráfico de un proceso que:
- se comunica con un host que AgentBridge no registra,
- no respeta
HTTP_PROXY, y - no desea alterar con un cambio del proxy de todo el sistema.
Como la interceptación se produce en el kernel, el proceso de origen no necesita ningún cambio de configuración, pero debe confiar en la CA dinámica que instala OmniRoute (consulte §4).
§2 Requisitos
Sección titulada «§2 Requisitos»| Requisito | Detalle |
|---|---|
| SO | Solo Linux — IP_TRANSPARENT es una opción de socket exclusiva de Linux. El cargador devuelve “no disponible” en cualquier otra plataforma. |
| Privilegios | La capacidad CAP_NET_ADMIN para crear el socket transparente y aplicar reglas de iptables/ip; en la práctica, debe ejecutarse como root. |
| Addon nativo | Debe compilarse un pequeño addon de N-API (src/mitm/tproxy/native/transparent.c) o distribuirse como binario precompilado. Consulte §3. |
| Módulos del kernel | iptables con compatibilidad para TPROXY, mangle y la coincidencia mark (validado con el kernel 6.8.0). |
Degradación controlada: si falta algún requisito (sistema distinto de Linux, ausencia de cadena de herramientas,
addon sin compilar), el cargador del addon (src/mitm/tproxy/transparentSocket.ts::loadTransparentAddon)
devuelve null en lugar de generar una excepción. El estado del modo de captura indica entonces
available: false, el selector del panel de control queda deshabilitado con la información sobre herramientas
“El descifrado TPROXY requiere Linux + root + el addon nativo”, y el resto de
OmniRoute continúa funcionando.
§3 El addon nativo IP_TRANSPARENT
Sección titulada «§3 El addon nativo IP_TRANSPARENT»El módulo net de Node no puede ejecutar setsockopt(IP_TRANSPARENT) antes de bind(), lo cual
es necesario para TPROXY (de lo contrario, el kernel descarta los paquetes redirigidos). El addon
(src/mitm/tproxy/native/transparent.c, compilado mediante binding.gyp) es un pequeño
módulo N-API que expone tres funciones, utilizadas a través de transparentSocket.ts:
| Función del addon | Operación del socket | Uso |
|---|---|---|
createTransparentListener(ip, port) |
socket() + SO_REUSEADDR + IP_TRANSPARENT + bind() + listen(); devuelve el fd sin procesar |
el listener de captura transparente (Node adopta el fd mediante server.listen({ fd })) |
setSocketMark(fd, mark) |
setsockopt SO_MARK en un fd existente |
prevención de bucles (marca los sockets propios del proxy) |
connectMarked(ip, port, mark) |
socket() + SO_MARK antes de un connect() no bloqueante; devuelve el fd |
el reenvío ascendente cifrado de nuevo (el SYN lleva la marca) |
El destino original se obtiene de socket.localAddress/localPort; TPROXY
lo conserva, por lo que no es necesaria ninguna consulta de SO_ORIGINAL_DST/NAT.
Compilación del addon
Sección titulada «Compilación del addon»npm run build:native:tproxy # entra en src/mitm/tproxy/native y ejecuta node-gyp rebuild # -> native/build/Release/transparent.node- Durante
npm run build,scripts/build/build-tproxy-native.mjsejecutanode-gyp rebuild. Es exclusivo de Linux y no fatal: si falta la cadena de herramientas, simplemente el modo de captura queda no disponible. assembleStandalone.mjscopiabuild/Release/transparent.nodeen el paquete independiente;transparentSocket.tslo resuelve tanto de forma relativa al módulo como relativa al cwd (<cwd>/src/mitm/tproxy/native/...).build/yprebuilds/están ignorados por git: el binario se compila, nunca se incluye en commits.
El cargador comprueba, en orden de prioridad:
native/build/Release/transparent.node y después native/prebuilds/transparent.node
(tanto de forma relativa al módulo como bajo <cwd>/src/mitm/tproxy/).
§4 La CA dinámica por SNI y el instalador del almacén de confianza
Sección titulada «§4 La CA dinámica por SNI y el instalador del almacén de confianza»Actualización de #6684: el servidor estático de AgentBridge (
src/mitm/server.cjs) ahora comparte este mismo patrón de arquitectura de CA/certificado final en lugar de usar un único certificado final autofirmado estático. Utiliza una instancia de CA distinta (src/mitm/cert/rootCa.ts, persistida en<DATA_DIR>/mitm/ca.key/ca.crt) y se instala en la ubicación preexistenteomniroute-mitm.crtdel almacén de confianza (sustituyendo allí el antiguo certificado final único, sin necesidad de limpiar dos certificados de confianza), que se mantiene completamente separada de la ubicaciónomniroute-tproxy-ca.crtpropia de TPROXY descrita más adelante. Las instalaciones nuevas de AgentBridge obtienen automáticamente el modelo de CA; una instalación que ya confiaba en el antiguo certificado final estático continúa utilizándolo hasta que el operador habilita explícitamenteMITM_ROOT_CA_ENABLED=true(consultesrc/mitm/cert/migration.ts): una CA MITM de confianza que puede firmar un certificado final para cualquier host es considerablemente más potente que el antiguo certificado final con SAN fijos, por lo que el cambio nunca se realiza de forma silenciosa en una instalación que ya confía en él.
Históricamente, el certificado MITM estático de AgentBridge solo funcionaba porque
AgentBridge falsifica mediante DNS un conjunto fijo de hosts (ahora unificado
con el modelo descrito a continuación). TPROXY intercepta hosts arbitrarios,
por lo que su listener debe presentar un certificado final válido para cualquier
SNI que solicite el cliente, el mismo requisito que ahora tiene AgentBridge para
el conjunto completo MITM_TOOL_HOSTS (9 entradas de herramientas), en lugar de
solo para los 4 hosts de antigravity.
CA dinámica (src/mitm/tproxy/dynamicCert.ts)
Sección titulada «CA dinámica (src/mitm/tproxy/dynamicCert.ts)»DynamicCertStore ejecuta una CA local (creada sobre la dependencia selfsigned) que:
- Genera una CA de larga duración mediante
generateMitmCa()(CN"OmniRoute MITM CA", validez de 10 años,basicConstraints CA=true+keyUsage keyCertSign,cRLSign, RSA de 2048 bits/SHA-256). - Emite un certificado final por nombre de host SNI bajo demanda mediante
issueLeafCert()(validez de 1 año,subjectAltName= el host SNI) y almacena en caché untls.SecureContextpor nombre de host. - Expone
createSNICallback()para el servidor que termina TLS (consulte §5). - Puede construirse con una
existingCapara mantener estable la CA entre reinicios (de modo que no sea necesario reinstalarla en el almacén de confianza).
La clave privada de la CA nunca sale de la máquina.
Instalador del almacén de confianza (src/mitm/tproxy/caTrust.ts)
Sección titulada «Instalador del almacén de confianza (src/mitm/tproxy/caTrust.ts)»El cliente interceptado debe confiar en la CA dinámica, por lo que, al iniciar el
modo de captura, el certificado de la CA se instala en el almacén de confianza del
SO bajo una ubicación dedicada —omniroute-tproxy-ca.crt (constante
TPROXY_CA_CERT_NAME)—, separada de la ubicación del certificado MITM estático
(omniroute-mitm.crt) para que nunca se sobrescriban entre sí.
installTproxyCa(caPem, sudoPassword?) detecta el directorio de anclajes de la
distribución (en orden: primero el estilo Debian) y ejecuta el comando de
actualización correspondiente:
| Directorio de anclajes | Comando de actualización |
|---|---|
/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 |
La instalación coloca primero el PEM en un archivo temporal y, a continuación,
ejecuta (con privilegios) mkdir -p para crear el directorio de anclajes, usa
cp para copiar allí el archivo preparado y ejecuta el comando de actualización.
uninstallTproxyCa() elimina únicamente la ubicación dedicada (sin modificar el
certificado MITM estático) y actualiza el almacén; en sistemas que no sean Linux,
no realiza ninguna operación.
Todos los comandos con privilegios se ejecutan mediante execFileWithPassword
(src/mitm/systemCommands.ts): spawn con matrices de argumentos, sin shell
ni interpolación de cadenas (Regla estricta n.º 13). Cuando el proceso se ejecuta
como root (por ejemplo, en el VPS), el comando de destino se ejecuta directamente
y no se necesita contraseña; en un equipo de escritorio sin acceso root,
sudoPassword se pasa mediante sudo -S por stdin.
El valor
sudoPassworddel equipo de escritorio se proporciona en el cuerpo de la solicitud POST para autorizar la instalación en el almacén de confianza; se ignora por completo cuando el proceso se ejecuta como root.
§5 Cómo funcionan el descifrado y la captura
Sección titulada «§5 Cómo funcionan el descifrado y la captura»La canalización (todo bajo src/mitm/tproxy/):
aplicación local ──TCP/443──▶ mangle OUTPUT marca la conexión (fwmark) ip rule → tabla de rutas local → lo mangle PREROUTING TPROXY → listener IP_TRANSPARENT (puerto 8443) │ captureMode.ts: lee el destino original de socket.localAddress ▼ tlsCapture.ts: 1. finaliza TLS para el CLIENTE con un certificado hoja por SNI (dynamicCert) 2. un http.Server interno analiza el texto plano descifrado 3. captura → globalTrafficBuffer.push() con source: "tproxy" (se aplican sanitizeHeaders + maskSecret) 4. reenvía, cifrándolo de nuevo, al destino original mediante un socket marcado para omisión (connectMarked, antirrecursión) │ ▼ servidor ascendente original (api.example.com)- Terminación TLS (
createTlsCaptureServer): envuelve el socket interceptado sin procesar en untls.TLSSocketdel lado del servidor mediante el callback SNI de la CA dinámica y, a continuación, entrega el flujo descifrado a unhttp.Serverinterno (la técnica estándar de terminación MITM). La duración de los sockets está limitada porMITM_IDLE_TIMEOUT_MS, de modo que un túnel bloqueado no pueda agotar los descriptores de archivo. - Captura (
handleDecryptedRequest): inserta unInterceptedRequestconsource: "tproxy", un estado inicial de"in-flight", las cabeceras procesadas mediantesanitizeHeaders()y los cuerpos mediantemaskSecret()antes de que entren en el búfer. A continuación, la entrada se actualiza con la respuesta, los tamaños y la latencia. - Reenvío cifrado de nuevo (
createForward/realForward): vuelve a cifrar el tráfico hacia el destino original. El valor predeterminado derejectUnauthorizedestrue(seguro de forma predeterminada): el certificado del servidor ascendente se verifica con respecto al SNI/Host solicitado por el cliente, por lo que el proxy rechaza exactamente lo que rechazaría el cliente original.
Antirrecursión (SO_MARK)
Sección titulada «Antirrecursión (SO_MARK)»Como las reglas marcan las nuevas conexiones salientes locales, el reenvío cifrado de nuevo del propio proxy normalmente volvería a interceptarse, lo que produciría un bucle infinito. La ruta de reenvío se protege frente a esto mediante una marca de socket de omisión (SO_MARK):
realForwardabre su socket ascendente medianteconnectMarked(ip, port, DEFAULT_BYPASS_MARK)—DEFAULT_BYPASS_MARK = 0x539—, que establece SO_MARK antes deconnect(), de modo que el SYN del reenvío incluye la marca de omisión.- La regla
mangle OUTPUTexcluye las conexiones que ya tengan la marca de omisión (-m mark ! --mark <bypassMark>), por lo que el reenvío del proxy no vuelve a marcarse ni vuelve a entrar en TPROXY.
Nota de implementación: el socket marcado para omisión debe instalarse en
createConnectiondel agente (https.request({ createConnection })se ignora silenciosamente cuando hay un agente presente); de lo contrario, el reenvío abriría un socket sin marcar y el bucle reaparecería. Esta fue la corrección antirrecursión validada mediante pruebas e2e.
§6 Seguridad
Sección titulada «§6 Seguridad»| Control | Detalle |
|---|---|
| API exclusiva de loopback | /api/tools/agent-bridge/tproxy está cubierta por el prefijo /api/tools/agent-bridge/ en LOCAL_ONLY_API_PREFIXES (src/server/authz/routeGuard.ts). La restricción de loopback se aplica antes de la autenticación (Reglas estrictas n.º 15 y n.º 17): un JWT filtrado a través de un túnel no puede iniciar la captura TPROXY, que aplica reglas de iptables e instala una CA en el almacén de confianza mediante procesos secundarios. |
| Ubicación dedicada para la CA | La CA dinámica se instala en omniroute-tproxy-ca.crt, sin sobrescribir nunca el certificado MITM estático. |
| La clave de la CA nunca sale del host | DynamicCertStore mantiene la clave de la CA en memoria; no se exporta. |
| Enmascaramiento de secretos | maskSecret() en los cuerpos de las solicitudes/respuestas y sanitizeHeaders() en los encabezados se ejecutan antes de globalTrafficBuffer.push(). |
| Sin interpolación de shell | Todos los comandos de iptables/ip/almacén de confianza se ejecutan mediante execFile/execFileWithPassword con matrices de argumentos (Regla estricta n.º 13). |
| Verificación del certificado de origen | El reenvío recifrado verifica de forma predeterminada el certificado del servidor de origen (rejectUnauthorized: true). |
| Saneamiento de errores | Las respuestas de error de la ruta pasan por sanitizeErrorMessage() (Regla estricta n.º 12). |
La CA MITM es una capacidad muy potente. Una CA en la que confía el sistema operativo y que puede firmar para cualquier host implica que se puede descifrar todo lo que OmniRoute intercepte. Está protegida mediante el modo explícito de captura TPROXY, exclusivo para conexiones locales y desactivado de forma predeterminada; además, la entrada del almacén de confianza se elimina al detener el modo.
§7 Aplicación / reversión transaccional del firewall
Sección titulada «§7 Aplicación / reversión transaccional del firewall»Un fallo nunca debe dejar una regla mangle ni una ruta obsoleta. El generador de comandos
(src/mitm/tproxy/commands.ts) y el ejecutor (src/mitm/tproxy/setup.ts) garantizan
que la reversión sea exactamente la operación inversa de la aplicación, en orden inverso.
applyTproxy(cfg) ejecuta los comandos de aplicación en orden; ante cualquier fallo, ejecuta una
operación completa de revertTproxy(cfg) mediante el mejor esfuerzo y vuelve a lanzar el error, de modo que el firewall queda
completamente aplicado o completamente revertido, nunca aplicado a medias. revertTproxy(cfg) ejecuta los
comandos inversos en orden inverso e ignora los fallos (es idempotente y se puede invocar
incondicionalmente, por ejemplo, desde la limpieza repairMitm() de AgentBridge).
validateTproxyConfig(cfg) se ejecuta antes de cualquier comando: los puertos deben estar entre 1–65535,
mark/routeTable/bypassMark deben ser enteros positivos y bypassMark debe
ser diferente de mark (antibucle).
Comandos de aplicación (en orden)
Sección titulada «Comandos de aplicación (en orden)»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>La reversión los elimina en orden inverso: PREROUTING -D, OUTPUT -D, ip route del, ip rule del.
La receta se basa en OUTPUT porque el caso de uso de MITM es el tráfico saliente local (aplicaciones en el mismo host), que TPROXY en
PREROUTINGpor sí solo no ve, ya quePREROUTINGsolo ve el tráfico reenviado. La cadenaOUTPUTmarca las conexiones locales nuevas, la reglaip rulelas redirige a la entrega local (lo) y, a continuación,PREROUTINGlas asigna al listener transparente.
§8 Configuración
Sección titulada «§8 Configuración»La solicitud de inicio (POST /api/tools/agent-bridge/tproxy) acepta los siguientes
campos, validados mediante StartTproxyBodySchema (tproxy/route.ts). Todos son opcionales
y, si no se especifican, adoptan sus valores predeterminados:
| Campo | Tipo | Valor predeterminado | Notas |
|---|---|---|---|
| dport | int (1–65535) | 443 |
Puerto TCP de destino que se interceptará de forma transparente |
| mark | int (≥1) | 0x2333 |
Marca del firewall establecida en OUTPUT, con la que coinciden ip rule + PREROUTING |
| onPort | int (1–65535) | 8443 |
Puerto al que se vincula el listener transparente (IP_TRANSPARENT) |
| routeTable | int (≥1) | 233 |
Id. de la tabla de enrutamiento por políticas que contiene la ruta local 0.0.0.0/0 |
| bypassMark | int (≥1, ≠ mark) |
0x539 |
Marca de socket de omisión (SO_MARK) que el proxy establece en sus propias conexiones ascendentes; se excluye en OUTPUT (antibucle) |
| sudoPassword | string | — | Solo para escritorios sin acceso root: autoriza la instalación en el almacén de confianza; se ignora con acceso root |
No hay variables de entorno para TPROXY: toda la configuración se proporciona mediante el cuerpo de la solicitud POST o los valores predeterminados anteriores.
§9 Habilitación desde el Inspector de tráfico
Sección titulada «§9 Habilitación desde el Inspector de tráfico»- Abra el Inspector de tráfico (
/dashboard/tools/traffic-inspector). - En la barra de herramientas de modos de captura, busque el botón ⚠ “Descifrado TPROXY”
(
src/app/(dashboard)/dashboard/tools/traffic-inspector/components/CaptureModesToolbar.tsx). - Haga clic en el botón. Este llama a
POST /api/tools/agent-bridge/tproxymediantestartTproxyCaptureMode()(src/lib/inspector/tproxyCaptureApi.ts), que: crea la CA dinámica, abre el listener transparente, aplica las reglas del firewall e instala la CA en el almacén de confianza del sistema operativo. - Cuando está en ejecución, el interruptor cambia a ámbar y muestra el número de interceptaciones
en tiempo real (
· <interceptCount>). Las solicitudes interceptadas aparecen en la lista de solicitudes consource: "tproxy". - Haga clic de nuevo para detenerlo:
DELETE /api/tools/agent-bridge/tproxymediantestopTproxyCaptureMode()cierra el listener, desinstala la CA y revierte las reglas del firewall.
El estado del modo de captura (en ejecución / disponible / número de interceptaciones / puerto del listener) se obtiene
de GET /api/tools/agent-bridge/tproxy (getCaptureStatus() en
src/mitm/tproxy/captureManager.ts). Solo se ejecuta una sesión TPROXY a la vez;
al intentar iniciar una segunda, se rechaza con “El modo de captura TPROXY ya está en ejecución”.
§10 Solución de problemas
Sección titulada «§10 Solución de problemas»El interruptor está deshabilitado
Sección titulada «El interruptor está deshabilitado»El complemento nativo no se puede cargar. Confirme que está en Linux, que ha compilado el complemento
(npm run build:native:tproxy) y que el proceso puede cargar transparent.node.
isTransparentSocketAvailable() controla el interruptor; GET /api/tools/agent-bridge/tproxy
devuelve available: false cuando falta el complemento.
No se captura nada
Sección titulada «No se captura nada»- Confirme que el proceso interceptado se conecta realmente al
dportconfigurado (de forma predeterminada,443). - Confirme que el proceso confía en la CA dinámica. La CA se instala como
omniroute-tproxy-ca.crt; es posible que las aplicaciones con su propio almacén de confianza (Firefox/Chrome NSS) también necesiten que se añada allí el certificado. - Ejecute la autoprueba Diagnose de AgentBridge (consulte
AGENTBRIDGE.md) para realizar comprobaciones de confianza del certificado y del estado del servidor.
Reglas obsoletas del firewall después de un fallo
Sección titulada «Reglas obsoletas del firewall después de un fallo»revertTproxy() es la operación inversa exacta de la aplicación de reglas y es idempotente. Al detener el
modo, se revierten las reglas; si OmniRoute se cerró de forma abrupta durante una sesión, utilice la acción
Repair de AgentBridge (POST /api/tools/agent-bridge/repair) para deshacer el estado huérfano del sistema
(suplantación de DNS, CA raíz y proxy del sistema). Las reglas mangle de TPROXY y la ruta también
se eliminan automáticamente al reiniciar.
Bucle infinito / el proxy intercepta su propio reenvío
Sección titulada «Bucle infinito / el proxy intercepta su propio reenvío»Este es el caso antibucle. Confirme que bypassMark sea distinto de mark (la validación
lo exige) y que el reenvío utilice connectMarked (así ocurre en realForward).
Consulte §5 Antibucle.
§11 Mapa de archivos fuente
Sección titulada «§11 Mapa de archivos fuente»| Archivo | Responsabilidad |
|---|---|
src/mitm/tproxy/commands.ts |
Generador puro de comandos de aplicación y reversión de iptables/ip; validateTproxyConfig |
src/mitm/tproxy/setup.ts |
Ejecutor transaccional de applyTproxy / revertTproxy (reversión en caso de fallo) |
src/mitm/tproxy/transparentSocket.ts |
Cargador del complemento nativo (loadTransparentAddon), createTransparentListenerFd, connectMarked, setSocketMark, isTransparentSocketAvailable |
src/mitm/tproxy/native/transparent.c |
Complemento N-API: createTransparentListener (IP_TRANSPARENT), setSocketMark, connectMarked |
src/mitm/tproxy/native/binding.gyp |
Manifiesto de compilación de node-gyp |
src/mitm/tproxy/dynamicCert.ts |
DynamicCertStore: CA dinámica por SNI y caché de certificados hoja |
src/mitm/tproxy/caTrust.ts |
Instalación/desinstalación en el almacén de confianza del SO (installTproxyCa / uninstallTproxyCa, ranura dedicada) |
src/mitm/tproxy/tlsCapture.ts |
Motor de descifrado con terminación TLS y reenvío antibucle recifrado |
src/mitm/tproxy/captureMode.ts |
Orquestación del listener transparente; lee el destino original desde socket.localAddress |
src/mitm/tproxy/captureManager.ts |
Ciclo de vida singleton: startCaptureMode / stopCaptureMode / getCaptureStatus |
src/app/api/tools/agent-bridge/tproxy/route.ts |
Ruta GET / POST / DELETE (LOCAL_ONLY) |
src/lib/inspector/tproxyCaptureApi.ts |
Funciones auxiliares de fetch del cliente (fetchTproxyStatus / startTproxyCaptureMode / stopTproxyCaptureMode) |
HagiCode
HagiCode es un espacio de trabajo de programación con agentes, flujos estructurados, ejecución multiagente y vistas de Hero Dungeon.
Convierte ideas en software útil con un flujo de trabajo con agentes más inteligente, rápido y ameno.

- SmartLos flujos estructurados convierten la intención en un itinerario ejecutable desde la idea hasta la entrega.
- EfficientLos flujos multiagente permiten avanzar en paralelo con la investigación, implementación y revisión.
- FunHero Dungeon hace que las largas sesiones de programación sean visuales y colaborativas.