PHP futtatása fastcgi módban
Sokszor felmerül web szervereket adminisztrálók körében a kérdés, hogy hogyan lehetne a PHP futtatását biztonságosabbá tenni. Bizonyára sokunk futtat, telepített már rendszert mod_php-val (Apache), és sokan meg is tapasztaltuk ennek a hátrányait. Véleményem szerint ezeket a hátrányokat nagyon szépen meg lehet szüntetni, és lehet PHP-t futtatni biztonságosan, kompromisszumok nélkül.
A
A
A
A
Mindannyian dolgoztunk már
Ez egy felhasználónál nem gond (fejlesztő gépe), de mi a helyzet akkor, ha többen vannak? Ha én a
Természetesen, ekkor nagyon fontos az
De ez sem teljesen jó megoldás: én, mint átlagos felhasználó nem tudom a nagyon titkos könyvtáramat a
Másik nagy hátránya a
Egy lehetséges megoldás: PHP futtatása
Elég sok kutatásba, próbálkozásba került, mire sikerült megoldani a PHP futtatását úgy, hogy a fentebb említett,
Mi ez a fastcgi?
Röviden: olyan mint a CGI, csak jobb. :) Nézzük kicsit leegyszerűsítve: egy CGI (Common Gateway Interface) alkalmazás esetén a program futása a következőképpen néz ki: jön a kérés a webszerver felé, mire az továbbítja a kérést a CGI programnak. Jelen esetben ez a PHP értelmező lesz, ami futtatja a programot, és az eredményt visszaadja a webszervernek, majd ezután eltűnik a memóriából. Egy következő kéréskor ugyanez a folyamat ismétlődik, amiből egyből láthatjuk, hogy ez a módszer nem túl hatékony, a PHP értelmezőt állandóan be kell tölteni, majd ki kell pakolni a memóriából.
A fastcgi ezt a be/ki töltögetést küszöböli ki: a PHP értelmező bent marad a memóriában addig, amíg szükség van rá. Sőt, egyszerre több értelmezőt is a memóriában tart, így több kérést is ki tud szolgálni egyszerre a szerver.
A CGI program külön szálként fut a webszerveren, elkülönítve a webszervertől, és a többi hasonló száltól. Ha az egyik kedves felhasználó programja megöli a CGI értelmezőjét, akkor sincs semmi gond, az meghal, de a többi attól még vígan dolgozik, és szolgálja ki a lapokat.
PHP futtatás felhasználói jogokkal? Lehetséges?
Igen, lehetséges az Apache
A webszerver beállítása
A környezet kialakításához szükségünk lesz a
A fentebb említett modulokat betöltését a következő sorok az Apache konfigurációs állományába történő beírásával érhetjük el:
Debian rendszer alatt elég a
A
Nálam ez egy
A wrapper a
Ezután már csak a virtuális webszerver beállítása következik, mely két részből áll: a konkrét virtuális szerver konfigurációs állományából, és egy PHP-t indító shell scriptből, melyre a suEXEC miatt van szükség. Nézzük meg ez utóbbit először.
A PHP-t indító shell script
A
Virtuális szerver konfigurálása
A host neve legyen a példa kedvéért
A fenti kis programocska a
A virtuális web szerver beállításai
A szokásos dolgokon kívül a következőket kell beállítani:
A
A fastcgi módszer hátrányai
A fastcgi módszer előnyei
Azt hiszem a fentiekből már teljesen világos lehet, de azért kiemelném a legfontosabbakat:
Az eredmény
A webszerverünkön a
Szépen látszik, hogy a fastcgi fő folyamatot még a
Források:
Megjegyzés: hiába tettem el a linket, amikor a szerveremet állítottam be, de mára eltűnt az az oldal, ahol volt fenn sebességteszt eredmény.
Sokszor felmerül web szervereket adminisztrálók körében a kérdés, hogy hogyan lehetne a PHP futtatását biztonságosabbá tenni. Bizonyára sokunk futtat, telepített már rendszert mod_php-val (Apache), és sokan meg is tapasztaltuk ennek a hátrányait. Véleményem szerint ezeket a hátrányokat nagyon szépen meg lehet szüntetni, és lehet PHP-t futtatni biztonságosan, kompromisszumok nélkül.
A
mod_phpA
mod_php legnagyobb előnye, hogy
nagyon egyszerű telepíteni, pillanatok alatt készen van. Debian Linux
alatt a telepítése egy lépésben történik: apt-get install libapache2-mod-php5
(feltételezzük, hogy Apache 2-es webszervert és PHP 5-ös verziót
szeretnénk telepíteni). Ez a parancs letölti a megfelelő Apache modult,
és telepíti azt. A PHP konfigurációs állományát (php.ini)
alapértelmezés szerint a /etc/php5/apache könyvtárba teszi. A parancs kiadását követően újra kell indítanunk a webszervert, és már használhatjuk is a PHP-t.A
mod_php előnyei:- Egyszerű, gyors telepítés.
- Ismert a webfejlesztők körében.
- Gyors a php futása (mihez képest, ugye?).
- Virtual hostonként lehetőségünk van egyedi PHP beállítások használatára.
- A PHP futási paramétereit magunk is könnyedén módosíthatjuk könyvtáranként
.htaccessállományok segítségével.
A
mod_php hátrányaiMindannyian dolgoztunk már
mod_php-val,
így ismerjük azt a tényt, hogy a PHP kiszolgálása a webszervert futtató
felhasználó nevében történik (ez némely rendszeren a www-data, másokon a nobody).
Ez a megoldás azért problémás, mert ha írni akarunk a fájlrendszerbe,
akkor azt csak a jogosultsági rendszer meglazításával lehet: vagy az
összes felhasználónak írási joggal kell rendelkeznie az adott
állományra vagy könyvtárra, vagy az a www-data tulajdonában kell legyen.Ez egy felhasználónál nem gond (fejlesztő gépe), de mi a helyzet akkor, ha többen vannak? Ha én a
/home/donci/nagyontitkosallomanyok könyvtárban szeretném tárolni a nagyon titkosnak ítélt dolgaimat, akkor hogy oda tudjak írni, a www-data felhasználónak is kell tudnia oda írni. Ebből a tényből következik az, hogy ha a badboy
nevű felhasználó kideríti az elérési utat (ami nem feltétlenül esik
egybe a web gyökér könyvtárral), akkor simán el tudja olvasni az én
titkosnak vélt állományaimat. Természetesen, ekkor nagyon fontos az
open_basedir PHP direktíva beállítása, hogy badboy ne tudjon PHP programmal garázdálkodni a saját könyvtárán kívül (/home/badboy). Ugyanez vonatkozik a többi felhasználóra is!De ez sem teljesen jó megoldás: én, mint átlagos felhasználó nem tudom a nagyon titkos könyvtáramat a
www-data
tulajdonába átadni, mivel nem tudom a jelszavát. Annyit tehetek csak,
hogy az összes felhasználónak adok olvasási, írási jogot a könyvtárra (chmod o+rw),
de ezután már PHP futtatási jog sem kell ahhoz, hogy valaki
turkálhasson a könyvtárban. Valljuk be, ez nem túl szerencsés dolog.Másik nagy hátránya a
mod_php használatának az, hogy egy modul futtatja az összes felhasználó PHP programjait, ezért ha a kedves badboy ír egy olyan programot, ami valamely oknál fogva működésképtelenné teszi a mod_php-t, akkor az én PHP programom futása is megakad.Egy lehetséges megoldás: PHP futtatása
mod_fastcgi segítségévelElég sok kutatásba, próbálkozásba került, mire sikerült megoldani a PHP futtatását úgy, hogy a fentebb említett,
mod_php használatából fakadó hátrányokat kiküszöböljem.Mi ez a fastcgi?
Röviden: olyan mint a CGI, csak jobb. :) Nézzük kicsit leegyszerűsítve: egy CGI (Common Gateway Interface) alkalmazás esetén a program futása a következőképpen néz ki: jön a kérés a webszerver felé, mire az továbbítja a kérést a CGI programnak. Jelen esetben ez a PHP értelmező lesz, ami futtatja a programot, és az eredményt visszaadja a webszervernek, majd ezután eltűnik a memóriából. Egy következő kéréskor ugyanez a folyamat ismétlődik, amiből egyből láthatjuk, hogy ez a módszer nem túl hatékony, a PHP értelmezőt állandóan be kell tölteni, majd ki kell pakolni a memóriából.
A fastcgi ezt a be/ki töltögetést küszöböli ki: a PHP értelmező bent marad a memóriában addig, amíg szükség van rá. Sőt, egyszerre több értelmezőt is a memóriában tart, így több kérést is ki tud szolgálni egyszerre a szerver.
A CGI program külön szálként fut a webszerveren, elkülönítve a webszervertől, és a többi hasonló száltól. Ha az egyik kedves felhasználó programja megöli a CGI értelmezőjét, akkor sincs semmi gond, az meghal, de a többi attól még vígan dolgozik, és szolgálja ki a lapokat.
PHP futtatás felhasználói jogokkal? Lehetséges?
Igen, lehetséges az Apache
suEXEC szolgáltatását használva. A suEXEC
biztonsága azon alapul, hogy egy wrapperként (befoglaló programként)
más felhasználói jogokkal tud indítani alfolyamatokat. Ezzel a
módszerrel megoldhatjuk, hogy a CGI módban futó PHP programunk
felhasználói jogokkal fusson. Meg kell említenünk a teljesség kedvéért,
hogy léteznek még más PHP futtatási megoldások is: például a SuPHP, de a fellelhető információk alapján ennek a sebessége messze elmarad a FastCGI sebességétől (mérések szerint akár 70x lassabb is lehet!).A webszerver beállítása
A környezet kialakításához szükségünk lesz a
mod_fastcgi (plusz mod_cgi és mod_actons) és mod_suexec modulokra a webszerverhez, és CGI módú (--enable-fastcgi opcióval fordított) PHP-ra.A fentebb említett modulokat betöltését a következő sorok az Apache konfigurációs állományába történő beírásával érhetjük el:
LoadModule actions_module /usr/lib/apache2/modules/mod_actions.so
LoadModule cgi_module /usr/lib/apache2/modules/mod_cgi.so
LoadModule fastcgi_module /usr/lib/apache2/modules/mod_fastcgi.so
LoadModule cgi_module /usr/lib/apache2/modules/mod_cgi.so
LoadModule fastcgi_module /usr/lib/apache2/modules/mod_fastcgi.so
Debian rendszer alatt elég a
mods-available könyvtárból a megfelelő .load állmányokat linkelni a mods-enabled könyvtárba.A
fastcgi konfigurációs állományNálam ez egy
fastcgi nevű állományban van az Apache2 conf.d könyvtárában:FastCgiIpcDir /var/lib/apache2/fastcgi
FastCgiWrapper /usr/lib/apache2/suexec2
SuExecUserGroup www-data www-data
ScriptAlias /cgi/ /var/www/
<Location /cgi/>
Options +ExecCGI
SetHandler fastcgi-script
</Location>
FastCgiWrapper /usr/lib/apache2/suexec2
SuExecUserGroup www-data www-data
ScriptAlias /cgi/ /var/www/
<Location /cgi/>
Options +ExecCGI
SetHandler fastcgi-script
</Location>
A wrapper a
suexec2 program, amely indítani fogja a CGI programokat, és alapértelmezésben a www-data felhasználó/csoport jogokkal fog futni a PHP értelmező. Ezt követően a webszerver /cgi könyvtárára biztosítunk CGI futtatási lehetőséget.Ezután már csak a virtuális webszerver beállítása következik, mely két részből áll: a konkrét virtuális szerver konfigurációs állományából, és egy PHP-t indító shell scriptből, melyre a suEXEC miatt van szükség. Nézzük meg ez utóbbit először.
A PHP-t indító shell script
A
suEXEC biztonsági beállításai olyanok, hogy csak a /var/www
könyvtárból enged suid-elt program futtatást. Ezért egy apró programot
kell ebben a könyvtárban elhelyezni, amely majd a CGI módú PHP
értelmezőt indítja. Erre a programra a suEXEC biztosítja a webszerverétől eltérő felhasználói jogokat.Virtuális szerver konfigurálása
A host neve legyen a példa kedvéért
foo.bar, a felhasználó pedig foo. Ennek érdekében a /var/www alatt hozzunk létre egy foo.bar könyvtárat, melynek tulajdonosa foo:foo legyen. Ebbe a könyvtárba kell tenni a PHP-t indító scriptet php-fcgi néven, szintén foo:foo jogokkal. A könyvtárat azért csináljuk, hogy a virtuális szerverek konfigurációs állományait elkülönítsük egymástól.#!/bin/sh
PHPRC="."
export PHPRC
PHP_FCGI_CHILDREN=4
export PHP_FCGI_CHILDREN
exec /usr/lib/cgi-bin/php5 $*
PHPRC="."
export PHPRC
PHP_FCGI_CHILDREN=4
export PHP_FCGI_CHILDREN
exec /usr/lib/cgi-bin/php5 $*
A fenti kis programocska a
/usr/lib/cgi-bin/php5
programnak fogja átadni a vezérlést, amely feldolgozza majd a mi PHP
scriptünket. A PHPRC beállítás pedig lehetővé teszi, hogy ebben a
könyvtárban elhelyezzünk egy php.ini-t, így lehetőségünk van virtuális vebszerverenként egyedileg konfigurált PHP-t használni. Ezt a php.ini-t már lehet root jogokkal odatenni, ha nem akarjuk, hogy a felhasználó módosíthassa.A virtuális web szerver beállításai
A szokásos dolgokon kívül a következőket kell beállítani:
SuexecUserGroup foo foo
ScriptAlias /fcgi/ /var/www/foo.bar.fcgi/
<Location /fcgi/>
SetHandler fastcgi-script
</Location>
Directory /home/foo/webroot/ >
Options FollowSymLinks Indexes ExecCGI
Order deny,allow
allow from all
AddType application/x-httpd-fastphp .php
Action application/x-httpd-fastphp /fcgi/php-fcgi
</Directory>
ScriptAlias /fcgi/ /var/www/foo.bar.fcgi/
<Location /fcgi/>
SetHandler fastcgi-script
</Location>
Directory /home/foo/webroot/ >
Options FollowSymLinks Indexes ExecCGI
Order deny,allow
allow from all
AddType application/x-httpd-fastphp .php
Action application/x-httpd-fastphp /fcgi/php-fcgi
</Directory>
A
SuexecUserGroup után adjuk meg azt
a felhasználót, akinek a nevében fog futni a PHP. Ezután már csak
néhány fastcgi beállítás jön, ahol megadjuk, hogy egy .php kiterjesztésű állomány kiszolgálásakor a fent elkészített scriptünk fusson (de már felhasználói jogokkal).A fastcgi módszer hátrányai
- Lassabb mint a
mod_php. Részben igaz csak, igazából csak a CGI hívás miatt van egy pici konstans overhead (pár ms). Némely esetben a fastcgi PHP a gyorsabb.
- Nem lehet
.htaccess-benphp.inibeállításokat használni, cserébe viszont van egy teljesen sajátphp.ini-nk, ahol tényleg mindent be tudunk állítani virtuális szerverenként (azt is, hogy milyen modulokat használhat az adott host).
- Ha nem a felhasználó tulajonában van a PHP program, nem fut... :).
- Az Apache által biztosított könyvtár autentikáció csak külön beállításokkal működik.
A fastcgi módszer előnyei
Azt hiszem a fentiekből már teljesen világos lehet, de azért kiemelném a legfontosabbakat:
- Biztonságosabb, mint a
mod_php, mivel felhasználói jogokkal fut a PHP programunk.
- Hostonként teljes a kontroll a PHP felett a saját
php.inimiatt.
- Mivel a
/var/www-ben elhelyezett kis sciprtek bármilyen programot indíthatnak, ezért hostonként más verziójú PHP futtatható!
- Nem kell foglalkozni a könyvtárak jogainak átadásával: ahova a felhasználó írhat, oda írhat a PHP is, ezáltal sokkal átláthatóbb a jogrend.
Az eredmény
A webszerverünkön a
ps -axfu parancsot kiadva valami hasonló kimenetet kell kapnunk:root 9767 0.0
0.3 12748 6308 ? Ss
Jun06 0:08 /usr/sbin/apache2 -k start -DSSL
www-data 7792 0.0 0.2 12748 4632 ? S Jun29 0:01 \_ /usr/sbin/fcgi-pm -k start -DSSL
donci 7794 0.0 0.2 14016 5228 ? Ss Jun29 0:00 | \_ /usr/lib/cgi-bin/php5
donci 7795 0.1 1.3 39448 28724 ? S Jun29 2:11 | | \_ /usr/lib/cgi-bin/php5
donci 7796 0.1 1.3 39452 28736 ? S Jun29 2:11 | | \_ /usr/lib/cgi-bin/php5
donci 7797 0.1 1.3 38928 28200 ? S Jun29 2:11 | | \_ /usr/lib/cgi-bin/php5
donci 7799 0.1 1.4 41208 30520 ? S Jun29 2:06 | | \_ /usr/lib/cgi-bin/php5
user1 7845 0.0 0.2 14012 5224 ? Ss Jun29 0:00 | \_ /usr/lib/cgi-bin/php5
user1 7846 0.0 0.6 25068 14236 ? S Jun29 0:35 | | \_ /usr/lib/cgi-bin/php5
user1 7847 0.0 0.6 24980 14196 ? S Jun29 0:35 | | \_ /usr/lib/cgi-bin/php5
user1 7848 0.0 0.6 25040 14184 ? S Jun29 0:35 | | \_ /usr/lib/cgi-bin/php5
user1 7849 0.0 0.6 24956 14168 ? S Jun29 0:34 | | \_ /usr/lib/cgi-bin/php5
www-data 7792 0.0 0.2 12748 4632 ? S Jun29 0:01 \_ /usr/sbin/fcgi-pm -k start -DSSL
donci 7794 0.0 0.2 14016 5228 ? Ss Jun29 0:00 | \_ /usr/lib/cgi-bin/php5
donci 7795 0.1 1.3 39448 28724 ? S Jun29 2:11 | | \_ /usr/lib/cgi-bin/php5
donci 7796 0.1 1.3 39452 28736 ? S Jun29 2:11 | | \_ /usr/lib/cgi-bin/php5
donci 7797 0.1 1.3 38928 28200 ? S Jun29 2:11 | | \_ /usr/lib/cgi-bin/php5
donci 7799 0.1 1.4 41208 30520 ? S Jun29 2:06 | | \_ /usr/lib/cgi-bin/php5
user1 7845 0.0 0.2 14012 5224 ? Ss Jun29 0:00 | \_ /usr/lib/cgi-bin/php5
user1 7846 0.0 0.6 25068 14236 ? S Jun29 0:35 | | \_ /usr/lib/cgi-bin/php5
user1 7847 0.0 0.6 24980 14196 ? S Jun29 0:35 | | \_ /usr/lib/cgi-bin/php5
user1 7848 0.0 0.6 25040 14184 ? S Jun29 0:35 | | \_ /usr/lib/cgi-bin/php5
user1 7849 0.0 0.6 24956 14168 ? S Jun29 0:34 | | \_ /usr/lib/cgi-bin/php5
Szépen látszik, hogy a fastcgi fő folyamatot még a
www-data indította el, de a többi alfolyamat már felhasználóként fut.Források:
- FastCGI weblap
- Suexec'ed PHP-FastCGI on Apache2
- Using FastCGI with PHP
- Apache 2 mit PHP 4/5 als FastCGI
- Mod fcgi, egy másik fastcgi implementáció
Megjegyzés: hiába tettem el a linket, amikor a szerveremet állítottam be, de mára eltűnt az az oldal, ahol volt fenn sebességteszt eredmény.









Hozzászólás