Накратко: CGI (Common Gateway Interface) е стар интерфейс, при който уеб сървърът стартира нова програма за всяка заявка, при PHP програмата php-cgi. FastCGI е неговото развитие: PHP процесите работят постоянно и приемат много заявки през сокет. PHP-FPM е най-важната реализация на FastCGI за PHP. За сигурността са важни преди всичко настройките cgi.* и правилото, че FastCGI достъпът никога не бива да е публично достъпен.
Какво е CGI?
CGI е един от най-старите методи, чрез които уеб сървърите създават динамично съдържание. Ръководството на PHP препраща при настройката cgi.rfc2616_headers към RFC 3875, спецификацията на Common Gateway Interface. И началото на PHP са CGI програми: Расмус Лердорф написва през 1994 г. първите „Personal Home Page Tools“ като CGI двоични файлове на C.
Принципът: за всяка заявка уеб сървърът стартира нов процес, предава данните от заявката чрез променливи на средата и стандартния вход и чете отговора от стандартния изход. След това процесът приключва. Според ръководството на PHP при CGI и CLI PHP чете своя php.ini наново при всяко извикване, а при сървърните модули само при стартиране.
Това прави CGI устойчив, защото всяка заявка започва със свеж процес. Прави го обаче и бавен: стартирането на процеса, зареждането на конфигурацията и инициализирането на разширенията отнемат време при всяка заявка.
Какво е FastCGI?
FastCGI решава проблема с производителността, като поддържа процесите живи. Уеб сървърът се свързва през Unix сокет или TCP порт с работещ процес и му изпраща заявката по протокола FastCGI. Процесът я обработва и чака следващата.
| Характеристика | CGI | FastCGI с php-cgi | FastCGI с PHP-FPM |
|---|---|---|---|
| Процес за всяка заявка | да | не | не |
| Име на SAPI | cgi-fcgi |
cgi-fcgi |
fpm-fcgi |
| Пулове със собствен потребител | не | не | да |
| Управление на процесите | уеб сървър | модул на уеб сървъра, напр. mod_fcgid | собствен главен процес |
.user.ini се чете |
да | да | да |
PHP-FPM според ръководството е основната реализация на FastCGI в PHP. Тя допълва протокола с управление на процесите, пулове, страници със състоянието и slowlog. Подробности има в PHP-FPM, обяснен.
Настройките cgi в php.ini
За работа с CGI PHP познава собствени настройки. Следните стойности и описания са от ръководството на PHP:
cgi.force_redirect(по подразбиране 1,INI_SYSTEM): според ръководството е необходима, за да се използва PHP като CGI безопасно под повечето уеб сървъри. Изключване само „на собствен риск“; под IIS трябва да е изключена.cgi.fix_pathinfo(по подразбиране 1,INI_SYSTEM): осигурява правилни стойности наPATH_INFOиPATH_TRANSLATED. Скриптовете трябва да ползватSCRIPT_FILENAMEвместоPATH_TRANSLATED.cgi.discard_path(по подразбиране 0,INI_SYSTEM): позволява CGI двоичният файл да се постави безопасно извън уеб директорията, без защитата с.htaccessда може да бъде заобиколена.fastcgi.impersonate(по подразбиране 0,INI_SYSTEM): важи само за IIS под Windows.user_ini.filenameиuser_ini.cache_ttl(по подразбиране.user.iniи 300 секунди): управляват дали и колко често PHP чете файлове.user.ini.
При Nginx към това спада чисто предаване на пътя на скрипта. Четим основен шаблон, без гаранция за всяка среда:
location ~ \.php$ {
try_files $uri =404; # предавай на PHP само съществуващи файлове
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
Редът try_files $uri =404; не позволява заявки към несъществуващи .php пътища да бъдат предавани на PHP.
Защо отвореният FastCGI достъп е опасен
Ръководството на PHP изрично предупреждава: който може да отвори FastCGI връзка към PHP, контролира конфигурацията на заявката, например auto_prepend_file, и така може да изпълни произволен код. Причината е, че уеб сървърите могат да изпращат настройки на PHP през FastCGI параметри като PHP_VALUE и PHP_ADMIN_VALUE.
От това следват ясни правила:
- Свързвайте PHP-FPM или php-cgi в режим FastCGI само през Unix сокет, когато уеб сървърът работи на същия хост.
- При TCP задайте
listen.allowed_clientsи блокирайте порта във файъруола; указания по темата има в статията Файърол за уеб сървъри. - Дръжте правата на сокета тесни с
listen.owner,listen.groupиlisten.mode.
Проверете с ss -lntp | grep -i php дали някой PHP процес слуша на TCP адрес. Обвързване към 0.0.0.0 или към публичен адрес е случай, изискващ спешна намеса.
CGI, FastCGI и PHP2Shell
От PHP2Shell са засегнати както php-cgi, така и PHP-FPM. И за двата важи: актуализация до 8.5.12, 8.4.27, 8.3.36 или 8.2.35, респективно до потвърден backport, след това прекратяване и рестартиране на всички работещи PHP процеси. При настройки с FastCGI и php-cgi процесите често продължават да работят незабелязано, защото никоя самостоятелна услуга не ги управлява. Как да откриете и премахнете това наследство, е описано в php-cgi: наследство с риск. В Plesk вариантите се наричат другояче; помощ дава Plesk: разбиране на PHP обработчиците.
Как помага PHP SOS конкретно?
- Установяване на обработчиците: Определяме дали Вашите уебсайтове работят през CGI, FastCGI с php-cgi или PHP-FPM.
- Затваряне на достъпите: Проверяваме сокетите, портовете и правилата на файърол, така че да няма FastCGI достъп, достъпен отвън.
- Корекция и почистване: Актуализираме PHP и прекратяваме всички стари процеси, включително осиротели инстанции на php-cgi.
- Премахване: В рамките на заздравяването на сървъра заменяме наследството с CGI с PHP-FPM със собствени пулове.
Често задавани въпроси
FastCGI същото като PHP-FPM ли е?
Не. FastCGI е протокол, чрез който уеб сървърът общува с процес на приложение. PHP-FPM е програма, която реализира този протокол за PHP и управлява процесите. И php-cgi може да говори FastCGI, но не предлага пулове.
Защо чистият CGI се смята за остарял?
При CGI уеб сървърът стартира нов процес за всяка заявка и PHP при това всеки път чете конфигурацията си. Това струва време и ресурси. FastCGI и PHP-FPM държат процесите постоянно готови и затова са значително по-ефективни.
Какво е .user.ini?
Файлът .user.ini е малък конфигурационен файл в уеб директория. Според ръководството на PHP той се чете само от SAPI на CGI и FastCGI, т.е. и от PHP-FPM. Може да съдържа само настройки с режими INI_PERDIR, INI_USER или INI_ALL.
Как да разбера дали на моя сървър работи php-cgi?
С команди само за четене като ps или pgrep потърсете процеси с име php-cgi и погледнете в конфигурацията на уеб сървъра за записи като mod_fcgid, Action или ScriptAlias с php-cgi. В хостинг панелите режимът на работа често се нарича CGI или FastCGI приложение.