# Izolacija PHP-FPM poolova po web-stranici

> Izolirajte PHP-FPM poolove po web-stranici: provjerite postojeće poolove, zaštitite socketove, ograničite ekstenzije, sakrijte status stranice i postavite granice.

Izvor: https://phpsos.de/hr/blog/php-fpm-pools-isolieren/  
Stanje: 25.10.2026  
Pružatelj: PHP SOS, PHP hitna pomoć i sigurnost poslužitelja. Hitna pomoć putem WhatsAppa: https://wa.me/491736494914?text=Pozdrav%20PHP%20SOS%2C%20trebamo%20pomo%C4%87%20s%20na%C5%A1im%20PHP%20poslu%C5%BEiteljem.%20Tvrtka%3A%20%E2%80%A6%20Web-stranica%3A%20%E2%80%A6

**Ukratko:** Svaka web-stranica na poslužitelju trebala bi imati zaseban PHP-FPM pool sa zasebnim sistemskim korisnikom i zasebnim socketom. Razdvajanje postaje djelotvorno tek s pojedinostima: prava na socket samo za web-poslužitelj, `security.limit_extensions` na `.php`, nikakve javno dostupne status stranice, vlastite granice za procese i trajanje te odvojeni zapisnici. Od samog PHP2Shella štiti samo ažuriranje; poolovi ograničavaju koliko daleko napad doseže.

## Jedan poslužitelj, mnogo web-stranica, zajednički rizik

Na mnogim se poslužiteljima tijekom godina nakupilo ono što nitko nije tako planirao. Web-stranica tvrtke, shop, kampanjska stranica iz 2019. i testni sustav rade jedni uz druge, često pod istim korisnikom i u istom poolu. Ako se zaboravljena kampanjska stranica kompromitira, otvoreni su i podaci kupaca shopa.

PHP-FPM, FastCGI upravitelj procesa za PHP, to rješava poolovima: skupinama worker procesa s vlastitim postavkama. Kako funkcionira osnovno načelo, objašnjava članak [PHP-FPM objašnjen: upravitelj procesa, poolovi i workeri](https://phpsos.de/hr/php/php-fpm-erklaert/). Izgradnju odvojenih poolova sa zasebnim korisnikom, zasebnom privremenom mapom i `open_basedir` opisuje vodič [open_basedir i izolacija po web-stranici](https://phpsos.de/hr/ratgeber/open-basedir/). Ovaj članak ide korak dalje: kako provjeriti postojeće poolove i koje postavke razdvajanje čine otpornim?

Važno za svrstavanje: kod PHP2Shella ranjivosti CVE-2026-109618 i CVE-2026-109619 nalaze se u PHP interpreteru koji dijele svi poolovi jedne verzije PHP-a. Zaseban pool ne sprječava iskorištavanje. Ali odlučuje hoće li napadač nakon toga doseći jednu web-stranicu ili sve.

## PHP-FPM poolovi sa zasebnim korisnikom: provjera postojećeg stanja

Prije nego išta promijenite, steknite pregled. Sljedeće naredbe samo čitaju. Putovi i brojevi verzija razlikuju se po distribuciji:

```bash
# Svi poolovi s korisnikom i socketom
grep -HE '^\s*(\[|user|group|listen)\s*' /etc/php/*/fpm/pool.d/*.conf

# Pokrenuti poolovi i njihovi korisnici
ps -eo user,pid,cmd | grep '[p]hp-fpm: pool'

# Socketi i njihova prava
ls -l /run/php/

# Provjeriti konfiguraciju na pogreške (ništa ne mijenja)
sudo php-fpm8.3 -t
```

Pazite na tri obrasca: više web-stranica u istom poolu, poolove koji rade kao `www-data` ili čak kao `root` te socketove u koje smiju pisati svi korisnici. Svaki od njih potkopava razdvajanje.

Ako na poslužitelju radi više verzija PHP-a, svaka ima vlastitu FPM uslugu s vlastitim direktorijima poolova. Provjerite sve, a ne samo verziju koju ste posljednju postavili. Upravo su stare verzije sa zaboravljenim poolovima rizik jer se često niti održavaju niti ponovno pokreću nakon ažuriranja. Napomene o tome nalaze se u članku [Više verzija PHP-a na jednom poslužitelju](https://phpsos.de/hr/blog/mehrere-php-versionen-server/). Rezultat zabilježite u maloj tablici: web-stranica, pool, korisnik, socket, verzija PHP-a. Taj je pregled ujedno osnova za svaku kasniju izmjenu.

## Najvažnije postavke po poolu

Sljedeći pregled oslanja se na FPM konfiguraciju u PHP priručniku. Vrijednosti za procese i vremena ovise o Vašem opterećenju i aplikaciji:

| Postavka | Svrha | Preporuka |
|---|---|---|
| `user`, `group` | korisnik workera | zaseban korisnik za svaku web-stranicu, nikad `root` |
| `listen.owner`, `listen.group`, `listen.mode` | prava na socketu | samo grupa web-poslužitelja, način `0660` |
| `listen.acl_users` | pristup putem ACL-a umjesto vlasnika | upisati samo korisnika web-poslužitelja |
| `security.limit_extensions` | ekstenzije koje se izvršavaju | ograničiti na `.php` (zadano `.php .phar`) |
| `clear_env` | isprazniti varijable okruženja | ostaviti na zadanom `yes` |
| `pm.max_children` | najveći broj workera | ograničiti tako da jedna web-stranica ne zauzme cijeli poslužitelj |
| `request_terminate_timeout` | prekid zapelih zahtjeva | postaviti prema najdužem legitimnom zahtjevu |
| `pm.status_path`, `ping.path` | status i ping stranica | postaviti samo ako je potrebno i interno zaštititi |
| `slowlog`, `request_slowlog_timeout` | zapisnik sporih zahtjeva | po poolu u zasebnu datoteku |

Izvadak za ojačani pool izgleda ovako:

```ini
; /etc/php/8.3/fpm/pool.d/shop.conf (izvadak)
[shop]
user = shop
group = shop
listen = /run/php/shop.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660

pm = dynamic
pm.max_children = 20
pm.start_servers = 4
pm.min_spare_servers = 2
pm.max_spare_servers = 6
request_terminate_timeout = 60s

security.limit_extensions = .php
clear_env = yes

slowlog = /var/log/php/shop.slow.log
request_slowlog_timeout = 10s
php_admin_value[error_log] = /var/log/php/shop.error.log
```

Postavke poput `memory_limit` ili `session.upload_progress.enabled` zadajte po poolu pomoću `php_admin_value` i `php_admin_flag`. Prema priručniku te se vrijednosti ne mogu nadjačati putem `ini_set()`. Više o tome u članku [php_admin_value: zaključati postavke od nadjačavanja](https://phpsos.de/hr/blog/php-admin-value-sperren/).

## Status stranice i izmjena workera: ispravno svrstavanje

`pm.status_path` i `ping.path` aktivni su samo ako su postavljeni. Status stranica prikazuje pokrenute zahtjeve, procese i opterećenje. Za nadzor je korisna, ali javno dostupna nepotreban je izvor informacija za napadače. Te putanje u web-poslužitelju prosljeđujte samo za interne adrese. Kako Nginx i PHP-FPM sigurno surađuju, opisuje članak [Zaštititi Nginx s PHP-FPM-om](https://phpsos.de/hr/server/nginx-php-fpm/).

`pm.max_requests` određuje nakon koliko zahtjeva se worker ponovno pokreće; zadano je `0`, dakle nikad. Vrijednost veća od nule pomaže protiv sporo rastuće potrošnje memorije. Kao zaštita od PHP2Shella nije zamišljena: php.net ga ne navodi među prijelaznim mjerama i naglašava da potpuno štiti samo ažuriranje. Nakon ažuriranja vrijedi i ovo: svi workeri svih poolova moraju se ponovno pokrenuti jer inače stari procesi nastavljaju raditi s ranjivim kodom.

> **Savjet:**
> Održavajte predložak za nove poolove i svaku novu web-stranicu postavljajte pomoću njega. Tako razdvajanje nastaje automatski, umjesto da se godinama kasnije naknadno dograđuje.

## Tipične pogreške pri prelasku

Najčešća je pogreška novi pool koji doduše radi pod vlastitim korisnikom, ali čije datoteke i dalje pripadaju korisniku `www-data`. Tada pool ne smije pisati gdje mora i netko prava postavi preširoko. Unaprijed razjasnite koje mape moraju biti zapisive. Druga su pogreška planirani zadaci koji i dalje rade pod starim korisnikom i stvaraju datoteke s pogrešnim vlasnikom. Treća je zajednička mapa sesija za sve poolove, koja razdvajanje ponovno ukida.

Nakon svake izmjene testirajte prijavu, prijenose, predmemorije i planirane zadatke web-stranice te pratite zapisnik pogrešaka poola.

## Kako PHP SOS konkretno pomaže?

- Bilježimo sve poolove, korisnike, socketove i postavke i pokazujemo gdje web-stranice danas dijele procese ili prava.
- Za svaku web-stranicu postavljamo ojačani pool, s pravima na socket, granicom ekstenzija, granicama resursa i vlastitim zapisnicima.
- Zaštićujemo status stranice, kontrolirano ponovno pokrećemo sve workere i testiramo svaku web-stranicu.
- U sklopu [ojačavanja poslužitelja](https://phpsos.de/hr/leistungen/server-haertung/) razdvajanje dokumentiramo kao predložak za buduće projekte.


## Česta pitanja

**Zašto bi svaka web-stranica trebala imati zaseban PHP-FPM pool?**  
Zaseban pool sa zasebnim sistemskim korisnikom razdvaja web-stranice na razini procesa i prava nad datotekama. Ako se jedna web-stranica kompromitira, kod ne može bez daljnjega čitati datoteke drugih. Uz to se granice i postavke mogu odvojeno zadati za svaku web-stranicu.

**Štiti li zaseban pool od PHP2Shella?**  
Ne. Ranjivosti su u samom PHP interpreteru koji svi poolovi dijele. Zaštitu pruža samo ažuriranje na ispravljenu verziju uz ponovno pokretanje svih workera. Odvojeni poolovi ipak ograničavaju koliko daleko doseže uspješan napad.

**Što postiže security.limit_extensions?**  
Prema PHP priručniku postavka ograničava koje ekstenzije datoteka PHP-FPM izvršava kao glavnu skriptu. Zadano je .php i .phar. Tko je ograniči na .php, sprječava da se primjerice učitane slikovne datoteke izvršavaju kao PHP ako je web-poslužitelj pogrešno konfiguriran.

**Je li status stranica PHP-FPM-a opasna?**  
Otkriva pojedinosti o pokrenutim procesima i zahtjevima. Ako je javno dostupna bez zaštite, napadačima olakšava orijentaciju. Prema priručniku aktivna je samo ako je postavljen pm.status_path. Tada bi web-poslužitelj trebao ograničiti putanju na interne adrese.

## Izvori

- [PHP priručnik: FPM konfiguracija](https://www.php.net/manual/en/install.fpm.configuration.php)
- [Nginx dokumentacija](https://nginx.org/en/docs/)
- [BSI (njemački Savezni ured za informacijsku sigurnost) IT-Grundschutz](https://www.bsi.bund.de/DE/Themen/Unternehmen-und-Organisationen/Standards-und-Zertifizierung/IT-Grundschutz/it-grundschutz_node.html)
