En resumen: CGI (Common Gateway Interface) es una interfaz antigua en la que el servidor web inicia un programa nuevo para cada petición; en PHP, el programa php-cgi. FastCGI es su evolución: los procesos de PHP se ejecutan de forma permanente y reciben muchas peticiones a través de un socket. PHP-FPM es la implementación de FastCGI más importante para PHP. Para la seguridad son relevantes sobre todo los ajustes cgi.* y la regla de que un acceso FastCGI nunca debe ser accesible públicamente.
¿Qué es CGI?
CGI es uno de los métodos más antiguos con los que los servidores web generan contenido dinámico. El manual de PHP remite, en el ajuste cgi.rfc2616_headers, a la RFC 3875, la especificación del Common Gateway Interface. También los comienzos de PHP fueron programas CGI: Rasmus Lerdorf escribió en 1994 las primeras «Personal Home Page Tools» como binarios CGI en C.
El principio: para cada petición, el servidor web inicia un proceso nuevo, le entrega los datos de la petición mediante variables de entorno y la entrada estándar, y lee la respuesta de la salida estándar. Después el proceso termina. Según el manual de PHP, en CGI y CLI PHP vuelve a leer su php.ini en cada invocación y, en los módulos de servidor, solo al iniciar.
Eso hace que CGI sea robusto, porque cada petición empieza con un proceso nuevo. Pero también lo hace lento: iniciar el proceso, cargar la configuración e inicializar las extensiones cuesta tiempo en cada petición.
¿Qué es FastCGI?
FastCGI resuelve el problema de rendimiento haciendo que los procesos sigan vivos. El servidor web se conecta mediante un socket Unix o un puerto TCP a un proceso en ejecución y le envía la petición con el protocolo FastCGI. El proceso la atiende y espera la siguiente.
| Característica | CGI | FastCGI con php-cgi | FastCGI con PHP-FPM |
|---|---|---|---|
| Proceso por petición | sí | no | no |
| Nombre de la SAPI | cgi-fcgi |
cgi-fcgi |
fpm-fcgi |
| Pools con usuario propio | no | no | sí |
| Control de procesos | servidor web | módulo del servidor web, p. ej. mod_fcgid | proceso maestro propio |
Se lee .user.ini |
sí | sí | sí |
Según el manual, PHP-FPM es la implementación FastCGI principal de PHP. Complementa el protocolo con gestión de procesos, pools, páginas de estado y un slowlog. Los detalles están en PHP-FPM explicado.
Los ajustes cgi en el php.ini
Para el funcionamiento en CGI, PHP conoce ajustes propios. Los siguientes valores y descripciones proceden del manual de PHP:
cgi.force_redirect(por defecto 1,INI_SYSTEM): según el manual, necesario para ejecutar PHP como CGI de forma segura bajo la mayoría de los servidores web. Desactivarlo solo «bajo su propia responsabilidad»; bajo IIS debe estar desactivado.cgi.fix_pathinfo(por defecto 1,INI_SYSTEM): garantiza valores correctos dePATH_INFOyPATH_TRANSLATED. Los scripts deben usarSCRIPT_FILENAMEen lugar dePATH_TRANSLATED.cgi.discard_path(por defecto 0,INI_SYSTEM): permite colocar el binario CGI de forma segura fuera del directorio web, sin que pueda eludirse la protección de.htaccess.fastcgi.impersonate(por defecto 0,INI_SYSTEM): solo relevante para IIS en Windows.user_ini.filenameyuser_ini.cache_ttl(por defecto.user.iniy 300 segundos): controlan si PHP lee los archivos.user.iniy con qué frecuencia.
En Nginx forma parte de esto un traspaso limpio de la ruta del script. Un patrón básico legible, sin garantía para todos los entornos:
location ~ \.php$ {
try_files $uri =404; # pasar a PHP solo archivos existentes
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
La línea try_files $uri =404; evita que se pasen a PHP las peticiones a rutas .php inexistentes.
Por qué un acceso FastCGI abierto es peligroso
El manual de PHP advierte expresamente: quien pueda abrir una conexión FastCGI con PHP controla la configuración de la petición, por ejemplo auto_prepend_file, y con ello puede ejecutar código arbitrario. El motivo es que los servidores web pueden enviar ajustes de PHP mediante parámetros FastCGI como PHP_VALUE y PHP_ADMIN_VALUE.
De ello se derivan reglas claras:
- Conectar PHP-FPM o php-cgi en modo FastCGI solo mediante un socket Unix cuando el servidor web se ejecute en el mismo host.
- Con TCP, fijar
listen.allowed_clientsy bloquear el puerto en el cortafuegos; indicaciones en el artículo Cortafuegos para servidores web. - Mantener estrictos los permisos del socket con
listen.owner,listen.groupylisten.mode.
Compruebe con ss -lntp | grep -i php si algún proceso de PHP escucha en una dirección TCP. Un enlace a 0.0.0.0 o a una dirección pública es un caso que requiere actuar con urgencia.
CGI, FastCGI y PHP2Shell
PHP2Shell afecta tanto a php-cgi como a PHP-FPM. Para ambos rige: actualizar a 8.5.12, 8.4.27, 8.3.36 o 8.2.35, o a un backport confirmado, y después finalizar y reiniciar todos los procesos de PHP en ejecución. En las configuraciones FastCGI con php-cgi, los procesos suelen seguir ejecutándose sin que se note, porque ningún servicio propio los gestiona. Cómo encontrar y retirar este lastre heredado se explica en php-cgi: un lastre con riesgo. En Plesk las variantes se llaman de otro modo; ayuda Plesk: entender los handlers de PHP.
¿Cómo ayuda PHP SOS en concreto?
- Inventariar los handlers: averiguamos si sus sitios web se ejecutan mediante CGI, FastCGI con php-cgi o PHP-FPM.
- Cerrar accesos: revisamos sockets, puertos y reglas del cortafuegos para que ningún acceso FastCGI sea accesible desde fuera.
- Parchear y limpiar: actualizamos PHP y finalizamos todos los procesos antiguos, también las instancias huérfanas de php-cgi.
- Sustituir: en el marco del refuerzo del servidor sustituimos los restos de CGI por PHP-FPM con pools propios.
Preguntas frecuentes
¿Es FastCGI lo mismo que PHP-FPM?
No. FastCGI es un protocolo mediante el cual un servidor web habla con un proceso de aplicación. PHP-FPM es un programa que implementa ese protocolo para PHP y gestiona los procesos. También php-cgi puede hablar FastCGI, pero no ofrece pools.
¿Por qué se considera obsoleto el CGI puro?
En CGI, el servidor web inicia un proceso nuevo para cada petición y PHP lee cada vez su configuración. Esto cuesta tiempo y recursos. FastCGI y PHP-FPM mantienen procesos permanentemente disponibles y por eso son mucho más eficientes.
¿Qué es un .user.ini?
Un .user.ini es un pequeño archivo de configuración en un directorio web. Según el manual de PHP, solo lo leen las SAPI de CGI y FastCGI, es decir, también PHP-FPM. Solo puede contener ajustes con los modos INI_PERDIR, INI_USER o INI_ALL.
¿Cómo sé si en mi servidor se ejecuta php-cgi?
Busque con comandos de solo lectura como ps o pgrep procesos llamados php-cgi y revise en la configuración del servidor web entradas como mod_fcgid, Action o ScriptAlias con php-cgi. En los paneles de hosting, el modo de ejecución suele llamarse CGI o aplicación FastCGI.