Po przerwie dziś wracamy do naszego cyklu związanego z przygotowaniem i zabezpieczaniem serwera VPS (choć dotyczy to również serwerów dedykowanych, jak i komputerów domowych pełniących rolę serwera).

Tym razem nie będziemy zajmować się zabezpieczeniami samego serwera/systemu, a skupimy się na webserwerwerze Nginx i Apache2 – a konkretnie PHP-FPM, czyli module odpowiedzialnym za przetwarzanie plików PHP.

Użytkownik www-data na (web)serwerze

Zaryzykuję, że większość użytkowników (administratorów) serwerów trzyma na nich więcej niż jedną stronę, i pewnie większość z tych stron w mniejszym lub większym stopniu korzysta z PHP.

Przy standardowej konfiguracji za obsługę wszystkich stron odpowiada jeden użytkownik (np. www-data), a tym samym ma on dostęp do wszystkich plików wszystkich strona na danym serwerze. W takiej sytuacji wystarczy, że skutecznie zostanie zaatakowana jedna ze stron, by napastnik mógł uzyskać pełny dostęp do plików pozostałych stron (wszystko działa na jednym użytkowniku).

Ale nie trzeba włamania/ataku by doprowadzić do (potencjalnie) ryzykownej sytuacji – wystarczy, że na swoim serwerze przy standardowej konfiguracji webserwera/PHP udostępniacie miejsce na strony innych osób (hostujecie strony innych), i mają oni możliwość modyfikowania zawartości/plików. To wystarczy, by mogli uzyskać dostęp do plików związanych z innymi stronami – w tym plików konfiguracyjnych, w których znajdują się m.in. loginy i hasła.

PHP Pools, czyli minimalizowanie ryzyka

By zmienić ten stan rzeczy możemy skorzystać z opcji PHP Pools, którą znajdziemy w module FastCGI Process Manager (PHP-FPM), odpowiedzialnym za przetwarzanie plików PHP (Apache2, Nginx).

Dzięki temu będziemy mogli odizolować od siebie poszczególne (wybrane) domeny, poprzez przekazanie obsługi plików PHP do oddzielnych użytkowników, tak by ew. straty ograniczyć do minimum.

Większe zapotrzebowanie na zasoby? Może…

Oczywiście przy większej ilości domen możemy liczyć się z pewnym wzrostem zapotrzebowania na moc obliczeniową i/lub pamięć RAM, ale przyznam, że nawet nie bardo jestem w stanie podać o jakim zakresie mowa.

Chyba kiedyś widziałem jakieś testy, które… No właśnie – nawet nie pamiętam co z nich wynikało, ale skoro cały czas korzystam z tego rozwiązania, to najwidoczniej dodatkowe obciążenie dla serwera musiałem uznać za mało mało istotne. Zwłaszcza, że przy okazji jest to kolejny element zabezpieczający nasz serwer – konkretnie strony internetowe.

Lepsza kontrola wykorzystania zasobów serwera

Skoro przy wykorzystaniu zasobów jesteśmy, to rozdzielenie stron do poszczególnych gniazd (sockets) ma jeszcze jeden przydatny aspekt – w przypadku sporego obciążenia serwera jesteśmy w stanie po nazwie użytkownika/gniazda zidentyfikować stronę, która generuje największe obciążenie serwera.

Konfiguracja nowego gniazda/zasobu PHP (PHP Pools)

Teoria i marketing za nami, i teoretycznie można (w końcu) brać się do pracy – ale najpierw małe wprowadzenie:

W tym poradniku postaram się pokazać Wam jak najprostszy sposób na wykorzystanie PHP Pools, a więc prawdopodobnie nie będę się zagłębiał w dodatkowe ustawienia, to jednak warto byście wiedzieli, że w ten sposób możecie dla poszczególnych stron wybrać nie tylko użytkownika w ramach którego będą działały (wykonywały się) skrypty PHP, ale możecie ustawić również pozostałe opcje związane z działaniem PHP na serwerze (choćby php_admin_value czy php_admin_flag).

Na potrzeby tego poradnika będę korzystał z użytkownika „webinsider” i grupy o takiej samej nazwie – więc wszędzie tam gdzie w kodzie czy poleceniach znajdziecie „webinsider” powinniście/możecie to zmienić na swoją własną, wybraną nazwę.

Tworzymy nowego użytkownika w systemie

Zaczynamy od utworzenia w systemie nowej grupy (webinsider) i przypisanego do niej użytkownika (webinsider):

sudo groupadd webinsider && sudo useradd -g webinsider webinsider

Nie konfigurował hasła, gdyż nie będzie ten użytkownik logował się do systemu – jeśli w Waszym przypadku będzie inaczej (np. konfiguracja SCP zamiast FTP) to możecie mu ustawić hasło za pomocą polecenia:

sudo passwd webinsider

Od razu też zmienimy właściciela plików wybranej strony na nowo utworzonego użytkownika, dzięki czemu będziemy mogli m.in. zapisywać pliki bezpośrednio z poziomu strony, jak np. aktualizacja wtyczek w WordPressie:

sudo chown webinsider:webinsider -R /ścieżka/do/plików/strony

Konfiguracja gniazda/zasobu (PHP Pools)

Naszym kolejnym krokiem będzie przygotowanie pliku z konfiguracją gniazda PHP (PHP socekt) dla naszego użytkownika.

W tym celu możemy utworzyć nowy plik:

sudo nano /etc/php5/fpm/pool.d/webinsider.conf

O takiej zawartości (wariant minimalny):

[webinsider]
user = webinsider
group = webinsider
listen = /var/run/php5-fpm-webinsider.sock
listen.owner = www-data
listen.group = www-data
pm = dynamic
pm.max_children = 5
pm.start_servers = 2
pm.min_spare_servers = 1
pm.max_spare_servers = 3
chdir = /

Możecie też wykorzystać jako wzór istniejący plik www.conf:

sudo cp /etc/php5/fpm/pool.d/www.conf /etc/php5/fpm/pool.d/webinsider.conf

W tym przypadku wystarczy zmienić 4 linijki (wartość oryginalna -> nowa wartość):

[www] -> [webinsider]
user = www-data -> user = webinsider
group = www-data -> group = webinsider
listen = /var/run/php5-fpm.sock -> listen = /var/run/php5-fpm-webinsider.sock

Pozostałe opcje możecie zostawić bez zmian…

Konfiguracja webserwera Nginx

Teraz możemy przystąpić do modyfikacji ustawień wybranej domeny skonfigurowanej na naszym serwerze – z racji tego, że pod ręką mam akurat serwer z Nginx, to od tego webserwera zaczniemy:

sudo nano /etc/nginx/sites-available/webinsider

I szukamy sekcji odpowiedzialnej za obsługę plików PHP, która może wyglądać np. tak:

location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
include fastcgi.conf;
}

I zmieniamy linijkę:

fastcgi_pass unix:/var/run/php5-fpm.sock;

na:

fastcgi_pass unix:/var/run/php5-fpm-webinsider.sock;

W tym miejscu warto jeszcze rozważyć dodanie (powyżej) linijki:

fastcgi_param PHP_ADMIN_VALUE "open_basedir=$document_root";

Lub wersja z dostępem również do katalogu „/tmp”, by działało wgrywanie plików w PHP:

fastcgi_param PHP_ADMIN_VALUE "open_basedir=$document_root:/tmp";

Dzięki czemu zabezpieczymy resztę plików na serwerze (w tym pliki innych stron) przed niepowołanym dostępem, np. z jakiegoś menedżera plików  PHP.

Konfiguracja webserwera Apache2

O ile w przypadku punktu dotyczącego Nginx nawet przed chwilą – specjalnie na potrzeby tego wpisu – utworzyłem nowego użytkownika i „przeniosłem na niego” obsługę PHP, to w przypadku serwera Apache2 (oczywiście z PHP-FPM) muszę posiłkować się swoimi notatkami – nie mam akurat pod ręką żadnego.

W tym przypadku również edytujemy plik odpowiedzialny za konfigurację wybranej domeny:

sudo nano /etc/apache2/sites-available/webinsider.conf

I szukamy sekcji odpowiedzialnej za obsługę PHP za pomocą modułu mod_fastcgi, w której powinna znajdować się linijka podobna do tej:

FastCgiExternalServer /usr/lib/cgi-bin/php5-fcgi -socket /var/run/php5-fpm.sock -pass-header Authorization

I zmieniamy ja na:

FastCgiExternalServer /usr/lib/cgi-bin/php5-fcgi-webisnider -socket /var/run/php5-fpm-webinsider.sock -pass-header Authorization

Tylko tak jak napisałem – o ile w przypadku Nginx jestem pewien, to w przypadku Apache2 posiłkuję się tylko i wyłącznie notatkami (wprawdzie poradniki często pisze korzystając z notatek, to najczęściej przy tej okazji odświeżam je sprawdzając opisywane rozwiązanie np. „na żywym serwerze”).

Wprowadzamy zmiany w życie

Na tym etapie możemy chyba wprowadzić zmiany w życie, czyli restartujemy poszczególne usługi, zaczynając od PHP:

sudo service php5-fpm restart

Następnie Nginx:

sudo service nginx configtest
sudo service nginx reload

Lub Apache2:

sudo apache2ctl configtest
sudo apache2 restart

Test, czyli sprawdzamy czy wszystko działa

W tym momencie obsługa plików PHP dla wybranej domeny powinna być realizowana przez naszego nowego użytkownika (webinsider), co możemy sprawdzić za pomocą polecenia:

patryk@vps21:~$ ps aux | grep webinsider
webinsi [...] php-fpm: pool webinsider
patryk [...] grep webinsider

Możemy też skorzystać z pliku phpinfo.php:

<?php phpinfo(); ?>

Gdzie po jego wywołaniu znajdziemy m.in. użytkownika który odpowiada za obsługę plików PHP:

_SERVER["USER"] webinsider
(!) Zgłoś błąd na stronie | Lub postaw nam kawę :-)
LUTy dla D-Cinelike (DJI Mini 3 Pro, DJI Avata, OSMO Pocket) od MiniFly
Wdrożenie Omnibusa w sklepie na WooCommerce
Jak (legalnie) latać dronem w Kategorii Otwartej
Patryk