ugrás a tartalomhoz
NyomtatásRSS - HozzászólásokEgyszerű stílusNormál betűméretNagyobb betűméretFriss tartalom

PHP futtatása fastcgi módon 

dtaylorjúl. 1. (szo), 00.58PHP
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 mod_php

A 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ányai

Mindannyian 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ével

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, 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


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ány

Ná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>


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 $*


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>


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-ben php.ini beállításokat használni, cserébe viszont van egy teljesen saját php.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.ini miatt.
  • 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


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:


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

*
*
A szerkesztőség fenntartja a moderálás jogát. BBCode formázás használható. Például: [b]vastag[/b], [i]dőlt[/i], [url=http://...]link[/url], [quote]idézet[/quote], [colorer=css]css kód[/colorer]. További lehetőségek

Ha a szöveged valójában új téma, akkor abban a formában beküldve többek között megjelenik a fórumok és a Weblabor összesített RSS csatornájában, saját webcímet kap, sőt RSS-ben is követhetőek lesznek a hozzászólásai.

Ha hozzászólásod magánjellegű, akkor a felhasználó saját kapcsolati űrlapjának használatával tudod elküldeni az üzenetet.