Diagnóstico de conexiones PHP-FPM abiertas en Core-Admin


#1

Introducción

Los procesos PHP-FPM son los responsables de ejecutar el código PHP de cada sitio web alojado en el servidor. Cada vez que un visitante accede a una página, un proceso PHP-FPM del pool correspondiente al dominio se encarga de interpretar el código, generar la respuesta HTML y devolverla al servidor web.

El problema surge cuando ese código PHP, durante su ejecución, realiza conexiones de red hacia servidores externos (APIs de terceros, servicios de analítica, pasarelas de pago, actualizaciones de plugins, etc.). Si el servidor de destino responde con lentitud o no responde en absoluto, el proceso PHP-FPM se queda bloqueado esperando la respuesta. Mientras tanto, ese proceso no puede atender ninguna otra petición web.

Si varios visitantes coinciden en ejecutar código que realiza estas llamadas externas lentas, múltiples procesos PHP-FPM se quedan enganchados simultáneamente, agotando el pool de workers disponibles. El resultado: el sitio web se vuelve lento o deja de responder por completo, incluso si el servidor tiene recursos de CPU y memoria de sobra.

Core-Admin incorpora una herramienta de diagnóstico que permite ver en tiempo real qué conexiones de red tienen abiertas los procesos PHP-FPM, identificar cuáles llevan demasiado tiempo activas y actuar sobre ellas.


¿Por qué no deberían existir conexiones de larga duración?

Un proceso PHP-FPM típico debería ejecutar su código y devolver la respuesta en menos de 1-2 segundos. Las conexiones de red que realiza (consultar una API, verificar una licencia, descargar un recurso) deberían completarse en fracciones de segundo.

Cuando una conexión lleva más de 5 segundos activa, es un indicador claro de problema:

  • El destino no responde: El servidor externo está caído, saturado o inaccesible. El proceso PHP-FPM se queda en estado SYN_SENT (esperando que el destino acepte la conexión) o ESTABLISHED (conectado pero sin recibir datos).

  • Timeouts mal configurados: Muchos plugins de WordPress y frameworks PHP tienen timeouts por defecto de 30, 60 o incluso 300 segundos. Esto significa que un solo proceso puede quedarse bloqueado hasta 5 minutos esperando una respuesta que nunca llega.

  • Efecto cascada: Cada proceso bloqueado es un worker menos disponible. Si un pool tiene 10 workers y 8 están enganchados esperando respuesta de un servidor externo, solo quedan 2 para atender todas las visitas. El sitio web se ralentiza drásticamente.

  • Agotamiento total del pool: Cuando todos los workers están ocupados en conexiones bloqueadas, las nuevas peticiones web se encolan. Los visitantes ven tiempos de carga de 30 segundos o errores 502/504. El sitio parece caído, pero el problema real no es falta de recursos: son procesos PHP atrapados en conexiones externas que no progresan.

El patrón más habitual

El escenario típico es un plugin o tema de WordPress que, en cada carga de página:

  1. Contacta con un servidor externo para verificar licencias, obtener estadísticas, comprobar actualizaciones o enviar datos de analítica.
  2. El servidor externo experimenta problemas (o ha sido discontinuado) y deja de responder.
  3. Cada visita al sitio web lanza una nueva conexión que se queda colgada durante 30-60 segundos.
  4. En cuestión de minutos, todos los workers PHP-FPM del dominio están bloqueados.

Lo más frustrante es que el propietario del sitio web no es consciente de que un plugin está haciendo estas llamadas, y desde el punto de vista del servidor, CPU y RAM están infrautilizados mientras el sitio no responde.


Visualizando las conexiones PHP-FPM

Desde la interfaz web de Core-Admin

La funcionalidad está disponible en la aplicación Webhosting Management, dentro de la sección Php-Fpm Connections. Para acceder, seleccione la opción correspondiente en el menú lateral de la aplicación:

Al acceder, se muestra un listado en tiempo real de todas las conexiones de red abiertas por los procesos PHP-FPM del servidor:

Cada entrada muestra:

Campo Descripción
Hosting Dominio al que pertenece el proceso (extraído del pool PHP-FPM)
PID Identificador del proceso PHP-FPM
Process Tipo de proceso (normalmente “php-fpm pool”)
User Usuario del sistema bajo el que se ejecuta
Protocol Protocolo de la conexión (TCP/UDP)
Src Dirección IP y puerto de origen (el servidor)
Dst Dirección IP y puerto de destino (el servidor externo)
Status Estado de la conexión TCP
Reverse DNS Nombre de host obtenido por DNS inverso del destino
Elapsed Tiempo que lleva activa la conexión

Interpretando el campo Elapsed

La columna Elapsed es la más importante para el diagnóstico. Muestra cuánto tiempo lleva activa cada conexión, con formato Xs, Xm Ys o Xh Ym Zs. En la siguiente captura se puede observar cómo varias conexiones llevan tiempos elevados, señal de que los procesos están bloqueados:

  • 0s - 2s: Normal. La conexión acaba de establecerse.
  • 3s - 5s: Sospechoso. Puede ser una API lenta pero aún dentro de lo tolerable.
  • > 5s: Problemático. La conexión no está progresando adecuadamente.
  • > 30s: Crítico. El proceso está atrapado y consumiendo un worker sin producir resultado.
  • > 5m: Severo. Indica un timeout mal configurado o un destino completamente inaccesible.

Interpretando el campo Status

  • SYN_SENT: El servidor está intentando establecer la conexión pero el destino no responde. Si permanece en este estado más de unos segundos, el destino es inalcanzable.
  • ESTABLISHED: La conexión se ha establecido pero no se están recibiendo datos. El destino aceptó la conexión pero no envía respuesta.
  • CLOSE_WAIT: El destino cerró su lado de la conexión pero el proceso PHP aún no ha terminado de procesarla.

Desde la línea de comandos

La misma información está disponible mediante el comando crad-php-fpm-show-connections, ejecutable como root:

# Ver todas las conexiones PHP-FPM activas
crad-php-fpm-show-connections

# Filtrar por un dominio concreto
crad-php-fpm-show-connections -n ejemplo.com

# Incluir todos los descriptores de fichero (no solo conexiones TCP)
crad-php-fpm-show-connections --show-all

# Salida en formato JSON (útil para scripts)
crad-php-fpm-show-connections --json

# Reiniciar el caché de seguimiento de tiempos
crad-php-fpm-show-connections --reset-tracking

La herramienta mantiene un fichero de seguimiento en /var/lib/core-admin/php-fpm-connections.track donde registra la primera vez que detecta cada conexión. Esto permite calcular el tiempo transcurrido (Elapsed) entre ejecuciones sucesivas. Las conexiones que desaparecen se purgan automáticamente del caché.


Bloqueando conexiones problemáticas con “Add reject rule”

Una vez identificada una conexión que está causando problemas (por ejemplo, todos los procesos de un dominio están enganchados hacia la misma IP de destino), Core-Admin permite bloquear inmediatamente esa IP de destino directamente desde la interfaz.

Accediendo a la acción

Primero, haga clic sobre una de las conexiones problemáticas en el listado para abrir su vista de detalle. En la parte inferior verá los botones de acción disponibles:

¿Qué hace exactamente?

Al seleccionar una conexión y pulsar “Add reject rule”, se muestra un diálogo de confirmación indicando la IP que se va a bloquear:

Al confirmar, el sistema ejecuta:

route add -host <IP_destino> reject

Este comando añade una regla de enrutamiento en el kernel que rechaza inmediatamente cualquier intento de conexión hacia esa IP. El efecto es:

  1. Las conexiones actuales no se cierran instantáneamente, pero dejarán de recibir datos y eventualmente alcanzarán su timeout.
  2. Los nuevos intentos de conexión fallan inmediatamente con un error de red, en lugar de quedarse esperando 30-60 segundos.
  3. El código PHP recibe un error rápido y puede continuar su ejecución (o terminar con error) en lugar de quedarse bloqueado.

Si la operación se ha completado correctamente, se muestra un mensaje de confirmación.

¿Por qué esto resuelve la lentitud?

El problema fundamental de las conexiones bloqueadas es que el código PHP se queda esperando una respuesta que nunca llega o que tarda demasiado. Con la regla de rechazo activa:

  • En lugar de esperar 30-60 segundos por cada intento de conexión fallido, el código recibe un error en menos de 1 segundo.
  • Los procesos PHP-FPM se liberan rápidamente y vuelven a estar disponibles para atender visitas.
  • El sitio web recupera su rendimiento normal casi de inmediato.
  • La funcionalidad del plugin que hacía la llamada fallará (mostrará un error o simplemente no completará esa operación), pero el resto del sitio seguirá funcionando.

Consideraciones importantes

  • La regla se aplica a nivel de servidor completo, no solo a un dominio. Todos los dominios alojados perderán conectividad hacia esa IP.
  • La regla no sobrevive a un reinicio del servidor. Si se necesita que sea persistente, debe configurarse de forma permanente.
  • Antes de añadir la regla, conviene verificar mediante el campo Reverse DNS que la IP no corresponde a un servicio legítimo y necesario (por ejemplo, una pasarela de pago o un servicio de correo).
  • Todas las acciones quedan registradas en el historial de cambios del dominio, incluyendo: quién añadió la regla, desde qué IP, la dirección de destino bloqueada y su DNS inverso.

Para eliminar una regla de rechazo

Si se ha bloqueado una IP por error o ya se ha resuelto el problema de fondo, la regla se puede eliminar manualmente:

route del -host <IP_destino> reject

Identificando el código origen con “Buscar origen” (Find caller)

Bloquear la IP resuelve el síntoma de forma inmediata, pero la solución definitiva es identificar y desactivar el código que está realizando esas llamadas externas problemáticas. Para ello, Core-Admin ofrece la función “Buscar origen” (Find caller).

¿Qué hace?

Desde la vista de detalle de la conexión, pulse el botón “Find caller” (o “Buscar origen” si la interfaz está en español):

El sistema escanea todos los ficheros del document root del dominio buscando referencias a la IP de destino o sus dominios asociados.

El proceso es el siguiente:

  1. Resolución DNS inversa: Obtiene el nombre de host asociado a la IP de destino (por ejemplo, 192.0.96.246lb.wordpress.com) y extrae también el dominio padre (wordpress.com).

  2. Recopilación de ficheros: Recorre recursivamente el document root del dominio, recopilando todos los ficheros con extensiones relevantes:

    • Código: .php, .inc, .module
    • Configuración: .ini, .conf, .json, .xml, .yml, .yaml
    • Otros: .txt, .htaccess
  3. Extracción de referencias: En cada fichero, busca:

    • URLs completas (http://, https://, ftp://, ssl://, tcp://, tls://)
    • Nombres de host entrecomillados (valores de configuración, constantes)
    • Direcciones IP directas
  4. Resolución y comparación DNS: Cada hostname encontrado se resuelve vía DNS y se compara con la IP de destino original. Si coincide, se marca como match.

  5. Presentación de resultados: Para cada coincidencia, muestra:

    • Ruta del fichero
    • Número de línea
    • Fecha de creación del fichero
    • Fecha de última modificación
    • Contenido de la línea

Los resultados se muestran directamente en un área de texto dentro del panel, permitiendo copiar la información fácilmente:

Ejemplo de uso práctico

Imaginemos que vemos múltiples conexiones PHP-FPM del dominio mitienda.com hacia 192.0.96.246 (que resuelve a lb.wordpress.com) con tiempos de más de 30 segundos. Al pulsar “Buscar origen”, obtenemos algo como:

Search terms (from reverse DNS): 192.0.96.246, lb.wordpress.com, wordpress.com
Scanning 12847 files in /var/www/mitienda.com/html ...

Found 3 match(es) connecting to 192.0.96.246:

File                                                          Line  Created              Updated              Line Content
/var/www/mitienda.com/html/wp-content/plugins/jetpack/...     142   2025-11-03 14:22:01  2025-11-03 14:22:01  $api_url = 'https://public-api.wordpress.com/rest/v1.1/...
/var/www/mitienda.com/html/wp-content/plugins/jetpack/...     87    2025-11-03 14:22:01  2025-11-03 14:22:01  define('JETPACK__API_BASE', 'https://jetpack.wordpress.com/...
/var/www/mitienda.com/html/wp-content/themes/flavor/...       23    2025-09-15 10:05:33  2025-09-15 10:05:33  'update_server' => 'https://flavor.developer.wordpress.com/...

Con esta información podemos ver que:

  • El plugin Jetpack realiza llamadas a la API de WordPress.com.
  • El tema Flavor contacta con un servidor de actualizaciones de WordPress.com.

La acción correctiva sería desactivar temporalmente Jetpack y/o el sistema de actualizaciones del tema hasta que los servidores de WordPress.com recuperen su disponibilidad, o configurar los timeouts de estos componentes a valores más razonables.

Desde la línea de comandos

La misma funcionalidad está disponible directamente:

# Buscar qué código en /var/www/ejemplo.com/html conecta con 192.0.96.246
crad-php-fpm-show-connections --find-caller=192.0.96.246 /var/www/ejemplo.com/html

# Con salida detallada (muestra el progreso de resolución DNS)
crad-php-fpm-show-connections --find-caller=192.0.96.246 -v /var/www/ejemplo.com/html

# Salida en JSON
crad-php-fpm-show-connections --find-caller=192.0.96.246 --json /var/www/ejemplo.com/html

Flujo de trabajo recomendado

Cuando un sitio web alojado experimenta lentitud, el proceso de diagnóstico recomendado es:

1. Visualizar las conexiones

Acceder a Php-Fpm Connections en Webhosting Management y observar:

  • ¿Hay conexiones con Elapsed superior a 5 segundos?
  • ¿Múltiples conexiones apuntan a la misma IP de destino?
  • ¿Los procesos afectados pertenecen al mismo dominio?

2. Evaluar el impacto

Haga clic en una conexión sospechosa para ver sus detalles completos:

  • Comprobar el Reverse DNS del destino para entender a qué servicio se está conectando.
  • Comprobar el Status: SYN_SENT indica que el destino es completamente inalcanzable; ESTABLISHED indica que acepta conexiones pero no responde.

3. Bloquear si es necesario (Add reject rule)

Si las conexiones están causando degradación del servicio:

  • Seleccionar una de las conexiones problemáticas.
  • Pulsar “Add reject rule” y confirmar en el diálogo.

Paso 3: Confirmación de la regla de rechazo y mensaje de éxito

  • Los procesos PHP-FPM comenzarán a liberarse en segundos.

4. Identificar el origen (Buscar origen)

Una vez estabilizado el servicio:

  • Seleccionar la conexión y pulsar “Buscar origen”.
  • Revisar los resultados que aparecen en el área de texto.

Paso 4: Resultado de "Buscar origen" mostrando los ficheros PHP que contienen referencias al destino bloqueado

  • Comunicar al propietario del sitio qué componente está causando el problema.

5. Aplicar la solución definitiva

Según el caso:

  • Desactivar el plugin o tema problemático.
  • Configurar timeouts más cortos en el código del plugin (si es posible).
  • Actualizar el componente a una versión que corrija el problema.
  • Eliminar la regla de rechazo una vez corregido el código:
    route del -host <IP> reject
    

Resumen

Herramienta Propósito Efecto
Php-Fpm Connections Visualizar conexiones abiertas Diagnóstico: ver qué procesos están bloqueados y hacia dónde
Add reject rule Bloquear IP de destino Acción inmediata: los procesos dejan de esperar y se liberan
Buscar origen (Find caller) Localizar el código que hace la llamada Solución definitiva: identificar el plugin/tema/código responsable

La combinación de estas tres herramientas permite pasar de “el sitio está lento y no sabemos por qué” a “el plugin X está haciendo llamadas a un servidor que no responde, lo hemos bloqueado y el sitio ha recuperado su rendimiento” en cuestión de minutos.