NOC/SOC OPERATIVO · MONITOREO CONTINUO
IT Experts de México
Contáctanos
Inicio/ Blog/ diagnose debug flow: por qué un paquete no pasa por tu Forti...
Ciberseguridad

diagnose debug flow: por qué un paquete no pasa por tu FortiGate

RERubén Espinoza calendar_today02/09/2026 schedule9 min de lectura

Un cliente te llama: "no me abre el sistema de la sucursal, y ayer sí". Entras al FortiGate por la interfaz web, revisas las políticas, todo se ve bien. Y sin embargo el tráfico no pasa. ¿Ahora qué?

Aquí es donde la GUI se queda corta y el CLI te salva. El firewall sabe exactamente por qué descartó ese paquete — solo que no te lo cuenta por la interfaz gráfica. Se lo tienes que preguntar con diagnose debug flow, la herramienta con la que un FortiGate te narra, paquete por paquete, la decisión que tomó y en qué línea de código la tomó.

Es el comando que más usamos cuando algo está roto y no hay tiempo para adivinar. En este artículo te enseñamos a montarlo sin tumbar el equipo, a filtrar para no ahogarte en salida, y —lo importante— a leer lo que te devuelve. Incluido ese mensaje que a media internet en español lo deja frío: Denied by forward policy check (policy 0).

Por qué la GUI no te lo dice y el CLI sí

La interfaz web te muestra el estado: qué políticas existen, cuántas sesiones hay, qué logs se generaron. Lo que no te muestra es el proceso de decisión sobre un paquete concreto que está pasando ahora mismo. Y ese proceso tiene un orden: primero routing, luego DNAT, luego búsqueda de política, luego los perfiles de seguridad (UTM), luego SNAT. Si el paquete muere, murió en una de esas etapas, y saber en cuál es el 90% del diagnóstico.

diagnose debug flow te expone justo ese orden. Cada línea de salida trae un func= (la función interna de FortiOS) y un msg= en lenguaje casi humano. No necesitas ser desarrollador de Fortinet para leerlo; necesitas saber qué buscar. Vamos a eso.

El montaje: filtrar antes de encender

Regla de oro: nunca enciendas el debug sin filtrar primero. Un FortiGate en producción mueve miles de paquetes por segundo; si activas la traza sin filtro, la consola se vuelve ilegible y le metes carga innecesaria a la CPU. Primero acotas, luego enciendes.

Este es el montaje que usamos para seguir una sola conversación — supongamos que quieres ver qué le pasa al tráfico hacia el host 203.0.113.45 en el puerto 443:

Montaje del filtro y arranque de la traza (10 paquetes) — FortiOS 7.x
diagnose debug flow filter clear
diagnose debug flow filter addr 203.0.113.45
diagnose debug flow filter port 443
diagnose debug flow filter proto 6
diagnose debug flow show function-name enable
diagnose debug flow trace start 10
diagnose debug enable

Línea por línea, para que no memorices sino que entiendas:

  • filter clear — borra cualquier filtro previo. Empiezas limpio siempre.
  • filter addr — acota a una IP (origen o destino). Es lo que evita el diluvio.
  • filter port 443 y filter proto 6 — reduces a HTTPS sobre TCP (proto 6 = TCP; 17 = UDP; 1 = ICMP).
  • show function-name enable — agrega el func= a cada línea. Sin esto pierdes la pista de en qué etapa murió el paquete.
  • trace start 10 — captura 10 paquetes y se detiene sola. El número es tu red de seguridad: nunca dejas un debug corriendo indefinidamente en producción.
  • diagnose debug enable — el interruptor general. Hasta que no lo corres, no ves nada.

Y esto es lo que siempre corres al terminar, sin excepción:

Apagar el debug y limpiar (no lo dejes encendido)
diagnose debug flow trace stop
diagnose debug disable
diagnose debug reset

¿Por qué tanto énfasis? Porque un debug olvidado encendido en un equipo con conserve mode cercano es una de esas cosas que te arruinan un viernes. Lo enciendes para diagnosticar, lo apagas en cuanto tienes la respuesta.

Leer un flujo que SÍ pasa

Antes de cazar el problema, conviene saber cómo se ve lo normal. Esta es la traza de un paquete que el firewall acepta y rutea correctamente:

[LAB] Traza de un flujo permitido — salida de diagnose debug flow
id=65308 trace_id=1 func=print_pkt_detail line=5892 msg="vd-root:0 received a packet(proto=6, 192.168.10.20:52344->203.0.113.45:443) from port2. flag [S], seq 1846135720, ack 0, win 64240"
id=65308 trace_id=1 func=init_ip_session_common line=6073 msg="allocate a new session-000a1b2c"
id=65308 trace_id=1 func=iprope_dnat_check line=5387 msg="in-[port2], out-[], no DNAT"
id=65308 trace_id=1 func=__vf_ip_route_input_common line=2611 msg="find a route: flag=00000000 gw-203.0.113.45 via port1"
id=65308 trace_id=1 func=fw_forward_handler line=990 msg="Allowed by Policy-7:"
id=65308 trace_id=1 func=__ip_session_run_tuple line=3466 msg="SNAT 192.168.10.20->203.0.113.45[port1]"

Lee de arriba hacia abajo como una historia:

  1. Entró un paquete TCP de 192.168.10.20 hacia 203.0.113.45:443, por port2. El flag [S] (SYN) te dice que es el arranque de una conexión nueva.
  2. Se creó una sesión nueva. Bien.
  3. No hubo DNAT — no es tráfico redirigido a una VIP.
  4. Encontró ruta de salida por port1. Sin esta línea, el problema sería de routing, no de política.
  5. La joya: Allowed by Policy-7. El paquete casó con la política 7 y fue permitido. Ese número es el que buscas en tu tabla de políticas.
  6. Se aplicó SNAT — el origen se tradujo a la IP de port1 al salir.

Ese es el camino feliz. Ahora el interesante.

Leer un flujo que NO pasa: el temido "policy 0"

Mismo montaje, pero el cliente reporta que otro tráfico —digamos SSH al mismo host— no funciona. Esta es la traza:

[LAB] Traza de un flujo bloqueado — el paquete muere en la búsqueda de política
id=65308 trace_id=3 func=print_pkt_detail line=5892 msg="vd-root:0 received a packet(proto=6, 192.168.10.20:52890->203.0.113.45:22) from port2. flag [S], seq 2938471028, ack 0, win 64240"
id=65308 trace_id=3 func=init_ip_session_common line=6073 msg="allocate a new session-000a1c9f"
id=65308 trace_id=3 func=iprope_dnat_check line=5387 msg="in-[port2], out-[], no DNAT"
id=65308 trace_id=3 func=__vf_ip_route_input_common line=2611 msg="find a route: flag=00000000 gw-203.0.113.45 via port1"
id=65308 trace_id=3 func=fw_forward_handler line=990 msg="Denied by forward policy check (policy 0)"

Fíjate en la última línea: Denied by forward policy check (policy 0). Y ahora la pregunta del millón: ¿qué es la política 0?

La política 0 no existe en tu lista. Es la denegación implícita — la regla invisible al final de toda la tabla que dice "si ninguna política anterior aceptó este paquete, lo tiro". Cuando ves policy 0, el firewall te está diciendo con todas sus letras: "revisé todas tus políticas, ninguna casó con este tráfico, así que lo bloqueé por defecto".

Esto cambia por completo tu diagnóstico. El problema no es que una política esté bloqueando; es que no hay política que permita ese tráfico específico, o hay una pero no casa por un detalle: la interfaz de origen equivocada, el objeto de dirección mal armado, el servicio que no incluye el puerto 22, o el orden de las políticas (una regla más arriba la está "tapando"). Fíjate además que la traza encontró ruta — o sea, no es routing; es política, sin ambigüedad.

El diccionario de las cuatro denegaciones más comunes

El 90% de los "no pasa" que vas a diagnosticar caen en uno de estos cuatro mensajes. Guárdalo:

Mensajes de denegación de debug flow y qué significan de verdad
"Denied by forward policy check (policy 0)"
    -> Ninguna política casó. Falta una regla, o la que existe no
       coincide por interfaz/objeto/servicio/orden. NO es routing.

"reverse path check fail, drop"
    -> RPF: el paquete de vuelta saldría por una interfaz distinta a
       la de entrada. Ruteo asimétrico. Revisa rutas, no políticas.

"iprope_in_check() check failed on policy 0, drop"
    -> Tráfico dirigido AL firewall (local-in): admin, VPN, ping.
       Lo gobiernan las local-in policies, no las de forwarding.

"denied by security policy" / bloqueo tras "Allowed by Policy-N"
    -> La política SÍ casó y permitió, pero un perfil de seguridad
       (IPS, antivirus, filtro web) descartó el paquete. Ahí no toques
       la política: revisa el perfil UTM.

La distinción del último caso es la que más confunde a quien empieza: que una política acepte no garantiza que el paquete pase. Si esa política tiene perfiles de seguridad aplicados, el tráfico todavía tiene que sobrevivir la inspección. Por eso a veces ves un Allowed by Policy-N seguido, unas líneas después, de un descarte. La política hizo su trabajo; el perfil hizo el suyo. Lo desarrollamos en qué logra (y qué no) el IPS de un firewall.

Un caso real de campo

Nos tocó exactamente este escenario en una empresa con una VIP mal armada: el tráfico entrante moría y la GUI no daba pista. El debug flow mostró no DNAT donde debía haber traducción — la VIP existía en la configuración pero la política no la referenciaba como destino. Diez segundos de traza contra media hora de revisar pantallas. Si trabajas seguido con port forwarding y VIPs, ese patrón lo cubrimos a fondo en NAT a fondo: port forwarding, DMZ y las VIP de FortiGate.

La moraleja no es memorizar mensajes. Es cambiar el reflejo: cuando algo no pasa por el FortiGate, deja de adivinar en la GUI y pregúntale directo al equipo con debug flow. El firewall siempre sabe por qué tiró tu paquete; solo hay que saber preguntarle. Si quieres entender qué decide un perímetro moderno más allá de este comando, empieza por el firewall moderno: qué hace de verdad un perímetro. Y para el resto del arsenal de consola, esta serie sigue: ver los paquetes reales con la captura de paquetes y saber quién está vivo en la red con get system arp.

#fortinet #fortigate #cli #troubleshooting #debug-flow #firewall

Preguntas frecuentes

help ¿Es seguro correr diagnose debug flow en un FortiGate en producción?

Sí, siempre que filtres antes de encender y limites el número de paquetes con trace start N. El riesgo no es el comando, sino dejarlo corriendo sin filtro: eso satura la consola y suma carga de CPU. Filtra por dirección y puerto, captura unos pocos paquetes y apágalo en cuanto tengas la respuesta.

help ¿Qué significa exactamente policy 0 en la salida?

Es la denegación implícita: la regla por defecto al final de la tabla que descarta todo el tráfico que ninguna política explícita permitió. Ver policy 0 significa que no existe una regla que case con ese tráfico, o que la que existe no coincide por interfaz, objeto, servicio u orden. No es un bloqueo activo, es la ausencia de un permiso.

help ¿Por qué veo Allowed by Policy-N y aun así el tráfico no llega?

Porque la política aceptó el paquete, pero un perfil de seguridad (IPS, antivirus, filtro web) aplicado a esa política lo descartó después. La aceptación de la política y la inspección UTM son dos etapas distintas. Si el flujo muere tras un Allowed by, el problema está en el perfil de seguridad, no en la regla.

help ¿Sirve debug flow para tráfico dirigido al propio firewall, como la VPN o el admin?

Sí, pero verás mensajes distintos. El tráfico hacia el FortiGate mismo lo gobiernan las local-in policies, no las de forwarding. Ahí el mensaje típico es iprope_in_check() ... policy 0, y se diagnostica revisando las local-in policies, no las reglas de tránsito.

RE
Sobre el autor

Rubén Espinoza es fundador y Director Técnico de IT Experts de México. Trabaja en la industria de TI desde 1998: diseña y opera soluciones de infraestructura, ciberseguridad, continuidad, automatización y tecnología OT para entornos empresariales e industriales. Escribe desde proyectos reales y sistemas en producción.

Ver perfil y todos sus artículos →
Compartir
// Más artículos
// Contacto

Inicia hoy tu transformación digital

Trabajemos juntos. Cuéntanos qué necesita tu operación y te respondemos a la brevedad.

call+52 (614) 400-0013 phone_in_talk+52 (614) 426-2339 mailcontacto@itxperts.com.mx

Al enviar aceptas nuestro Aviso de Privacidad.