Röviden: A PHP-FPM (FastCGI Process Manager) önálló szolgáltatásként üzemelteti a PHP-t a webszerver mellett. Egy master folyamat kezeli a poolokat, és minden pool workereket indít, amelyek FastCGI-n keresztül dolgozzák fel a kéréseket. A poolok weboldalanként saját felhasználóval, saját korlátokkal és zárolt PHP-beállításokkal üzemeltethetők. Mivel a workerek sok kérést dolgoznak fel egymás után, PHP-frissítés után mindet újra kell indítani.
Mi a PHP-FPM?
A PHP-kézikönyv az FPM-et a PHP elsődleges FastCGI-megvalósításaként írja le, olyan funkciókkal, amelyek főleg erősen terhelt weboldalaknál hasznosak. Az FPM a PHP 5.3.3-mal került be önálló SAPI-ként, vagyis önálló üzemmódként. SAPI-neve fpm-fcgi.
A különbség a mod_php-hoz képest: a PHP nem a webszerverben fut, hanem önálló szolgáltatásként. Az Nginx, az Apache vagy más webszerver a PHP-kéréseket a FastCGI protokollon keresztül adja tovább, és megkapja a kész választ. A webszerver és a PHP így egymástól függetlenül indítható újra, konfigurálható és védhető. Hogy a FastCGI alapvetően hogyan működik, azt a CGI és FastCGI oldal írja le.
Master, poolok és workerek: a folyamatmodell
A PHP-FPM három szintből áll:
- Master folyamat: beolvassa a konfigurációt, megnyitja a socketeket, és elindítja vagy leállítja a workereket. Maga nem hajt végre alkalmazáskódot.
- Poolok: Minden poolnak van neve, saját socketje vagy portja, saját Unix-felhasználója és saját PHP-beállításai. A kézikönyv kifejezetten említi poolonként a különböző uid-et, gid-et, chrootot, környezetet és php.ini-t.
- Workerek: egy pool folyamatai, amelyek kéréseket fogadnak és hajtanak végre. Egy worker sok kérést dolgoz fel egymás után, mielőtt lecserélik.
Hány worker fut, azt a folyamatkezelő határozza meg a pm direktívával:
| Mód | Viselkedés | Fontos direktívák |
|---|---|---|
static |
rögzített számú worker | pm.max_children |
dynamic |
worker az alsó és felső határ között | pm.start_servers, pm.min_spare_servers, pm.max_spare_servers |
ondemand |
worker csak szükség esetén, üresjárat után leépül | pm.process_idle_timeout (alapérték 10s) |
A pm.max_children minden módban korlátozza az egyidejű kérések számát. A pm.max_requests egy workert egy rögzített számú kérés után lecserél; a 0 alapérték korlátlant jelent.
Hogy melyik mód illik, az a terheléstől függ. A static mindig ugyanannyi workert tart készenlétben, és egyenletesen erősen használt, elegendő memóriával rendelkező alkalmazásokhoz való. A dynamic a legtöbb weboldalnak megfelelő kompromisszum. Az ondemand memóriát takarít meg sok kis weboldalt kiszolgáló szervereken, mert látogatók nélküli poolok nem foglalnak workereket; cserébe szünet utáni első kérés kicsit tovább tart. Túl magasra állított pm.max_children terhelési csúcsoknál memóriahiányba kergetheti a szervert, a túl alacsony pedig várakozási időkhöz és a webszerver hibaüzeneteihez vezet.
Egy pool biztonságos alapbeállításokkal
Példa egy weboldalankénti saját poolra, a PHP-kézikönyv direktíváival. Az útvonalak és értékek példák:
; /etc/php/8.3/fpm/pool.d/kunde-a.conf
[kunde-a]
user = kunde-a
group = kunde-a
listen = /run/php/kunde-a.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
pm = ondemand
pm.max_children = 10
pm.process_idle_timeout = 10s
request_terminate_timeout = 60s
security.limit_extensions = .php
clear_env = yes
php_admin_value[open_basedir] = /var/www/kunde-a:/tmp
php_admin_flag[session.upload_progress.enabled] = off
php_admin_value[error_log] = /var/log/php/kunde-a.error.log
A kézikönyv szerint a php_value és php_flag útján megadott értékek futásidőben az ini_set() segítségével módosíthatók, a php_admin_value és php_admin_flag útján megadottak viszont nem. A security.limit_extensions alapértelmezetten .php .phar, és meghatározza, mely fájlkiterjesztéseket hajtja végre az FPM főszkriptként. A clear_env = yes az alapérték, és kiüríti a workerek környezetét.
A felügyelethez van egy állapotoldal a pm.status_path útján, és egy ping oldal a ping.path útján. Mindkettőnek csak belső hálózatról szabad elérhetőnek lennie. A lassú kéréseket az FPM backtrace-szel naplózza, ha a request_slowlog_timeout és a slowlog be van állítva.
A PHP-kézikönyv figyelmeztet: aki meg tud nyitni egy FastCGI-kapcsolatot a PHP-FPM-hez, az irányítja a kérés konfigurációját, és ezzel tetszőleges kódot hajthat végre. A PHP-FPM-nek soha nem szabad megbízhatatlan hálózatból elérhetőnek lennie. Használjon Unix-socketet vagy listen.allowed_clients beállítást.
Milyen szerepe van a PHP-FPM-nek a PHP2Shell esetében?
A PHP-FPM az érintett üzemmódok közé tartozik. A folyamatmodell a CVE-2026-109619 esetén válik különösen világossá: a kéréshez tartozó belső állapot a memória felszabadítása után is fennmaradhat, és egy későbbi kérés ugyanabban a workerben felhasználhatja, mielőtt visszaállítanák. Ez csak azért lehetséges, mert a workerek sok kérést dolgoznak fel egymás után.
Ebből három kötelezettség következik:
- Frissítés telepítése: PHP 8.5.12, 8.4.27, 8.3.36 vagy 8.2.35, illetve a disztribúció megerősített backportja.
- Az összes worker újraindítása: A lemezen lévő új fájlok mit sem változtatnak, amíg régi workerek futnak. Ez minden telepített FPM-verzióra és minden poolra érvényes. A parancsok a PHP-FPM és az összes worker újraindítása oldalon találhatók.
- Az átmeneti értékek zárolt beállítása: A php.net intézkedései, például a
session.upload_progress.enabled=0, aphp_admin_valuevagyphp_admin_flagútján a poolba tartoznak, nem a.user.ini-be.
A poolokra bontás nem helyettesíti a frissítést, de korlátozza a kárt: ha minden weboldal saját felhasználó alatt fut, a támadó egy betörés után nem éri el automatikusan a többiek fájljait. Hogy ez konkrétan hogyan néz ki, azt a PHP-FPM-poolok elkülönítése weboldalanként cikk írja le; az Nginxbe való beillesztés az Nginx védelme PHP-FPM-mel oldalon található.
Hogyan segít konkrétan a PHP SOS?
- Poolok felmérése: Felsoroljuk a szerver összes FPM-verzióját, poolját, felhasználóját és socketjét.
- Javítás és újraindítás: Frissítjük a PHP-t, és az indítási időkkel igazoljuk, hogy nem fut már régi worker.
- Poolok szétválasztása: A szerver-megerősítés keretében weboldalanként saját felhasználójú, zárolt beállításokkal rendelkező poolt állítunk be.
- Elérhetőség ellenőrzése: Ellenőrizzük, hogy a FastCGI-socketek és az állapotoldalak kívülről nem érhetők el.
Gyakori kérdések
Minek a rövidítése az FPM?
Az FPM a FastCGI Process Manager rövidítése. A PHP-kézikönyv a PHP elsődleges FastCGI-megvalósításaként írja le, olyan funkciókkal, amelyek főleg erősen terhelt weboldalaknál hasznosak. A PHP 5.3.3-mal került be.
Mi a különbség a pool és a worker között?
A pool közös konfigurációjú worker-folyamatok csoportja: felhasználó, socket, korlátok és PHP-beállítások. A worker egyetlen folyamat, amely egymás után dolgozza fel a kéréseket. Egy szervernek sok poolja lehet, például weboldalanként egy.
A PHP-FPM-nek TCP-n vagy Unix-socketen keresztül kell elérhetőnek lennie?
Ha a webszerver ugyanazon a gépen fut, a PHP-kézikönyv Unix-socketet ajánl. TCP esetén a listen.allowed_clients beállítást meg kell adni, különben bármelyik cím csatlakozhat. A kézikönyv szerint egy nyitottan elérhető FastCGI-port tetszőleges kód végrehajtását teszi lehetővé.
Véd a pm.max_requests az olyan rések ellen, mint a PHP2Shell?
Nem. A pm.max_requests egy workert egy rögzített számú kérés után lecserél, és főleg a bővítményekben lévő memóriaszivárgások ellen segít. Az értelmezőben lévő rés ellen csak a frissítés segít, az összes worker ezt követő újraindításával.