Na kratko: mod_php je PHP kot modul v spletnem strežniku Apache. Vsak proces Apache tedaj vsebuje poln interpreter PHP in kodo PHP izvaja sam; SAPI se imenuje apache2handler. To je preprosto nastaviti, a PHP veže na Apache, praviloma zahteva prefork MPM in komaj dopušča ločevanje med spletnimi stranmi. Priročnik PHP za nove namestitve to odsvetuje, pri PHP2Shell pa ekipa PHP tveganje pri mod_php ocenjuje kot najvišje.
Kaj je mod_php?
Pri mod_php Apache naloži PHP kot lasten modul v svoje procese. Ločene storitve PHP ni: ko mora Apache izdati datoteko .php, kodo PHP izvede isti proces, ki je zahtevo sprejel. Dolga leta je bila to standardna pot za poganjanje PHP in je na starejših strežnikih ter v nekaterih image Docker razširjena še danes.
Po priročniku PHP kot strežniški modul konfiguracijo prebere samo enkrat, ob zagonu spletnega strežnika. Spremembe v php.ini in posodobitve modula zato začnejo veljati šele po ponovnem zagonu Apacheja.
Za razumevanje je pomembno: procesi Apache živijo dolgo. En proces zaporedoma sprejme veliko povezav, preden ga zamenjajo; koliko, ureja direktiva Apache MaxConnectionsPerChild. Vdelani interpreter PHP v tem času ostaja isti. Kdor na disku zamenja knjižnico libphp, na tekočih procesih ne spremeni ničesar.
Za vodstvo in vodje projektov je to mogoče povzeti takole: pri mod_php sta spletni strežnik in PHP ena enota. Kdor poseže v eno, vpliva na drugo. Posodobitev PHP pomeni ponovni zagon spletnega strežnika, napaka v PHP teče s pravicami spletnega strežnika, ločevanje med več spletnimi stranmi na istem strežniku pa je komaj mogoče.
Kako se mod_php vključi?
Priročnik PHP prikazuje vključitev v dveh korakih: naložiti modul in določiti, katere datoteke naj PHP obdeluje.
LoadModule php_module modules/libphp.so
<FilesMatch \.php$>
SetHandler application/x-httpd-php
</FilesMatch>
Priročnik priporoča FilesMatch s SetHandler namesto samo AddType, da se naložene datoteke, kot je bild.php.jpg, ne izvajajo kot PHP. V Debianu in Ubuntuju to delo prevzamejo paketi, kot je libapache2-mod-php8.3, ter ukaza a2enmod in a2dismod.
Ali je mod_php aktiven, je mogoče preveriti samo z branjem:
apachectl -M 2>/dev/null | grep -i php # Debian/Ubuntu
httpd -M 2>/dev/null | grep -i php # družina RHEL
apachectl -V | grep -i mpm # aktivni MPM (prefork, worker, event)
Prefork, Thread Safety in viri
Apache zahteve razporeja prek modula za večprocesiranje (MPM). Po priročniku PHP mod_php potrebuje MPM prefork, razen če je bil PHP zgrajen z Zend Thread Safety (--enable-zts). Večina paketov distribucij je zgrajena brez Thread Safety.
Prefork pomeni: en proces na hkratno povezavo, vsak proces pa nosi poln interpreter PHP. Tudi zahteve za slike ali datoteke CSS tako zasedejo proces s PHP v prtljagi. To stane pomnilnik in omejuje obremenitev, ki jo strežnik zdrži.
| Značilnost | mod_php | PHP-FPM |
|---|---|---|
| Kje teče PHP? | v vsakem procesu Apache | v samostojni storitvi |
| MPM Apache | praviloma prefork |
možen event |
| Uporabnik za vsako spletno stran | ne, vse kot uporabnik Apache | da, za vsak pool |
| Ponovni zagon PHP | samo z Apachejem | neodvisno od Apacheja |
| Nastavitve po imenikih | php_value v .htaccess |
pool ali .user.ini |
Priročnik zato za vse sodobne namestitve priporoča PHP-FPM z mod_proxy_fcgi: boljše upravljanje virov, ločevanje procesov, ponovni zagon PHP brez ponovnega zagona Apacheja in združljivost z MPM event, ki je od Apache 2.4 standard. Osnove so na strani PHP-FPM razložen.
Nastavitve z .htaccess, php_value in php_admin_value
Z mod_php je nastavitve PHP mogoče določiti neposredno v konfiguraciji Apache. Priročnik pri tem razlikuje načine spreminjanja: vnosi z INI_PERDIR smejo stati v php.ini, .htaccess ali httpd.conf, vnosi z INI_SYSTEM samo v php.ini ali httpd.conf.
# V konfiguraciji VirtualHost: za aplikacijo zaklenjeno
php_admin_flag display_errors off
php_admin_value upload_max_filesize 24M
# V .htaccess mogoče, a ga aplikacija lahko prepiše
php_value max_execution_time 60
php_admin_value in php_admin_flag sta dovoljena samo v konfiguraciji strežnika, ne v .htaccess. Prav ta razlika je pomembna pri prehodnih ukrepih proti PHP2Shell, ker vrednosti, kot je session.upload_progress.enabled, aplikacija ne sme moči ponastaviti.
mod_php in PHP2Shell: zakaj je tveganje najvišje
Ekipa PHP tveganje zaradi PHP2Shell pri mod_php ocenjuje kot najvišje: tam je bil exploit prikazan, še preden sploh teče koda aplikacije. Varnostni vtičniki ali preverjanja v CMS-ju tako pridejo prepozno. Dodatno PHP pri mod_php teče s pravicami in v pomnilniku spletnega strežnika. Podrobna uvrstitev je na strani Zakaj je tveganje pri mod_php najvišje.
Za upravljavce zato velja:
- Modul PHP posodobiti na 8.5.12, 8.4.27, 8.3.36 ali 8.2.35 oziroma na potrjen backport.
- Apache popolnoma znova zagnati, ne samo znova naložiti, in preveriti čas zagona procesov.
- Prehodne vrednosti nastaviti prek
php_admin_valuev konfiguraciji strežnika, če posodobitev še ni mogoča. - Nato načrtovati prehod na PHP-FPM, kot je opisano na strani Zavarovanje Apacheja z mod_php.
Kako PHP SOS pomaga konkretno?
- Prepoznavanje: preverimo, na katerih strežnikih teče mod_php, s katerim MPM in iz katerega vira paketov.
- Popravljanje: posodobimo modul PHP, Apache popolnoma znova zaženemo in dokažemo stanje.
- Zavarovanje prehoda: kjer je posodobitev blokirana, ukrepe php.net nastavimo zaklenjeno v konfiguraciji strežnika.
- Preklop: v okviru utrjevanja strežnika preizkušeno preidemo na PHP-FPM z lastnimi pooli.
Pogosta vprašanja
Zakaj se reče mod_php, če se modul imenuje php_module?
mod_php je pogovorno ime za PHP kot modul Apache. V konfiguraciji se naloži z LoadModule; priročnik PHP kot primer navaja LoadModule php_module modules/libphp.so. Starejše različice so uporabljale imena, kot sta php7_module ali php5_module.
Zakaj mod_php potrebuje prefork MPM?
Po priročniku PHP mod_php potrebuje prefork MPM, razen če je bil PHP zgrajen z Zend Thread Safety. Večina paketov distribucij je zgrajena brez Thread Safety. Prefork za vsako hkratno povezavo zažene lasten proces, kar zahteva več pomnilnika.
Ali vrstice php_value v .htaccess delujejo tudi s PHP-FPM?
Ne. php_value in php_flag v .htaccess sta direktivi Apache modula PHP in delujeta samo z mod_php. Pod PHP-FPM sodijo take nastavitve v pool ali, za dovoljene vrednosti, v .user.ini.
Ali moram mod_php takoj opustiti?
Najprej pride posodobitev PHP s popolnim ponovnim zagonom Apacheja. Prehod na PHP-FPM je po tem smiseln, a ga je treba načrtovati in preizkusiti. PHP2Shell ne zapre, ker je prizadet tudi PHP-FPM.