# Saugi Nginx konfigūracija PHP

> Saugi Nginx PHP konfigūracija: į PHP-FPM perduoti tik tikrus scenarijus, leisti Front-Controller, užblokuoti dotfiles ir tinkamai nustatyti dydžio ribas.

Šaltinis: https://phpsos.de/lt/blog/nginx-fuer-php-absichern/  
Būsena: 2026-10-25  
Teikėjas: PHP SOS, PHP avarinė pagalba ir serverio sauga. Skubi pagalba per „WhatsApp“: https://wa.me/491736494914?text=Sveiki%2C%20PHP%20SOS%2C%20mums%20reikia%20pagalbos%20su%20m%C5%ABs%C5%B3%20PHP%20serveriu.%20%C4%AEmon%C4%97%3A%20%E2%80%A6%20Svetain%C4%97%3A%20%E2%80%A6

**Trumpai:** norėdami saugiai sukonfigūruoti Nginx PHP, į PHP-FPM perduokite tik scenarijus, kurie tikrai egzistuoja, Front-Controller programoms net tik `index.php`. Prie to priklauso užblokuoti dotfiles, tokie kaip `.git` ir `.env`, numatytasis serveris nežinomiems pagrindinio kompiuterio vardams (hostname), tinkamos dydžio ribos ir `security.limit_extensions = .php` baseine. Tai neapsaugo nuo spragų pačiame PHP, bet riboja, kas po klaidos gali būti vykdoma.

## Pavojingiausios eilutės yra PHP location

Po PHP2Shell daugelis komandų tikrina savo PHP-FPM versijas ir baseinus, kaip aprašo puslapis [Nginx su PHP-FPM apsauga](https://phpsos.de/lt/server/nginx-php-fpm/), ir po atnaujinimo [iš naujo paleidžia visus darbinius procesus (worker)](https://phpsos.de/lt/php2shell/php-fpm-neustart/). Antras žvilgsnis skiriamas pačiai Nginx konfigūracijai. Būtent ten nusprendžiama, kurie failai apskritai vykdomi kaip PHP.

Daugelyje konfigūracijų yra blokas, kuris kiekvieną užklausą `.php` perduoda PHP-FPM, nesvarbu, kur failas yra. Jei įterptas PHP failas patenka į įkėlimų aplanką, serveris jį vykdo. Iš failo klaidos taip atsiranda užpakalinės durys.

Šis straipsnis koncentruojasi į Nginx pusę: kurios direktyvos svarbios, kaip veikia location blokų eilės tvarka ir kaip patikrinti rezultatą.

## Kaip Nginx nusprendžia, kuris blokas taikomas

Kas nori saugiai sukonfigūruoti Nginx PHP, turi žinoti location blokų pasirinkimą. Pasak Nginx dokumentacijos, jis vyksta taip:

1. Tikslus atitikmuo su `location =` iš karto baigia paiešką.
2. Tarp prefiksinių location įsimenama ilgiausia tinkama. Jei ji turi `^~`, reguliarieji reiškiniai nebetikrinami.
3. Kitu atveju reguliarieji reiškiniai (`~`, `~*`) tikrinami konfigūracijos failo eilės tvarka; laimi pirmas atitikmuo.
4. Jei joks reguliarusis reiškinys netinka, taikoma įsimintoji prefiksinė location.

Iš to išplaukia dvi praktinės taisyklės. PHP blokavimas įkėlimų aplankuose turi būti sukurtas arba kaip `^~` prefiksas, arba kaip reguliarusis reiškinys prieš bendrą PHP bloką. O įprasta prefiksinė location, pavyzdžiui, `location /uploads/`, neapsaugo, nes `.php` reguliarusis reiškinys ją nustelbia.

## Saugi bazinė konfigūracija

Toliau pateiktas pavyzdys rodo serverio bloką programai su Front-Controller, kaip įprasta Laravel, Symfony, Shopware 6 ar daugelyje savo kūrimo programų. Kelius, lizdą ir sertifikatus pritaikykite.

```nginx
server {
    listen 443 ssl;
    server_name www.example.de;
    root /var/www/seite1/public;
    index index.php;

    ssl_certificate     /etc/ssl/seite1/fullchain.pem;
    ssl_certificate_key /etc/ssl/seite1/privkey.pem;

    server_tokens off;
    client_max_body_size 32m;

    # Leisti Let's Encrypt ir kitus žinomus kelius
    location ^~ /.well-known/ {
        try_files $uri =404;
    }

    # Užblokuoti paslėptus failus ir aplankus (.git, .env, .htaccess)
    location ~ /\. {
        deny all;
    }

    location / {
        try_files $uri $uri/ /index.php$is_args$args;
    }

    # Tik Front-Controller perduodamas PHP-FPM
    location = /index.php {
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
        fastcgi_param DOCUMENT_ROOT $realpath_root;
        fastcgi_hide_header X-Powered-By;
        fastcgi_pass unix:/run/php/seite1.sock;
    }

    # Joks kitas PHP failas nevykdomas
    location ~ \.php$ {
        return 404;
    }
}
```

`$realpath_root` išsprendžia simbolines nuorodas. Tai svarbu diegiant su besikeičiančia simboline nuoroda į dabartinį leidimą (release), kad PHP-FPM ir OPcache matytų teisingą kelią. Taip pat atkreipkite dėmesį: pasak Nginx dokumentacijos, `fastcgi_param` direktyvos iš aukštesnių lygių paveldimos tik tada, kai dabartiniame lygyje savų nėra. Todėl `include fastcgi_params;` priklauso tam pačiam blokui.

Klasikiniai CMS, tokie kaip WordPress, TYPO3 ar Contao, turi kelis įėjimo taškus. Ten Front-Controller bloką pakeiskite bendra PHP location, kuri perduoda tik egzistuojančius failus (`try_files $uri =404;`), ir užblokuokite vykdymą visuose įrašomuose aplankuose. Kaip tai pasiekti, aprašyta skyriuje [PHP vykdymo įkėlimų aplankuose draudimas](https://phpsos.de/lt/blog/php-in-uploads-verbieten/).

## Antra apsauga PHP-FPM

Nginx nusprendžia, kas perduodama, PHP-FPM nusprendžia, ką vykdo. Pasak PHP vadovo, PHP-FPM numatytai vykdo failus su `.php` ir `.phar` ir pats rekomenduoja tai apriboti iki `.php`. Tai pagauna žiniatinklio serverio konfigūracijos klaidas.

```ini
; baseine, pvz., /etc/php/8.3/fpm/pool.d/seite1.conf
security.limit_extensions = .php
listen = /run/php/seite1.sock
listen.owner = www-data
listen.group = www-data
listen.mode = 0660
```

Lizdas turėtų būti pasiekiamas tik Nginx. FPM prievadai tinkle, pavyzdžiui, `9000`, neturi būti atveriami į išorę. Kaip serveris apskritai rodo tik reikalingus prievadus, aprašo [Ugniasienė žiniatinklio serveriui: atverti tik reikalingus prievadus](https://phpsos.de/lt/blog/firewall-fuer-webserver/).

## Nežinomi hostname ir kiti reguliavimo varžtai

Be savo numatytojo serverio Nginx užklausas nežinomiems hostname atsako pirmuoju tinkamu serverio bloku. Automatizuoti skenavimai, kurie kreipiasi tik į IP adresą, tada patenka tiesiai į jūsų programą. Atskiras numatytasis serveris tokias užklausas nutraukia be atsakymo.

```nginx
server {
    listen 80 default_server;
    listen 443 ssl default_server;
    server_name _;
    ssl_reject_handshake on;
    return 444;
}
```

Kiti pasiteisinę punktai:

| Reguliavimo varžtas | Rekomendacija | Paskirtis |
|---|---|---|
| `server_tokens` | `off` | jokio versijos numerio antraštėje ir klaidų puslapiuose |
| `client_max_body_size` | pagal `post_max_size` | dideles užklausas atmesti anksti |
| `autoindex` | išjungtas (numatytasis) | jokių katalogų sąrašų |
| `fastcgi_hide_header` | `X-Powered-By` | PHP versijos neišduoti į išorę |
| Būsenos puslapiai | `pm.status_path` tik viduje | jokių eksploatacijos duomenų viešai |
| Atsarginių kopijų failai | `.sql`, `.zip`, `.bak` žiniatinklio šakniniame kataloge užblokuoti arba pašalinti | jokio duomenų bazių atsisiuntimo |

Daugiau apie versijų duomenis rasite straipsnyje [expose_php ir Server antraštė](https://phpsos.de/lt/blog/expose-php-versionsangaben/).

Kitas reguliavimo varžtas liečia leidžiamus HTTP metodus. Daugumai svetainių reikia tik GET, HEAD ir POST. Su `limit_except` kitus metodus galima atmesti location bloke; pasak Nginx dokumentacijos, GET leidimas automatiškai leidžia ir HEAD. Iš anksto patikrinkite, ar jūsų programos sąsajos nenaudoja, pavyzdžiui, PUT ar DELETE, nes REST API tai daro dažnai.

## Išbandykite prieš iš naujo įkeldami

Kiekvieną pakeitimą pirmiausia patikrinkite su `nginx -t` ir tik tada iš naujo įkelkite Nginx. Po to elgseną iš išorės išbandykite įprastomis užklausomis į savo domeną:

```bash
sudo nginx -t && sudo systemctl reload nginx
# Tikimasi: 403 arba 404
curl -s -o /dev/null -w "%{http_code}\n" https://www.example.de/.git/HEAD
curl -s -o /dev/null -w "%{http_code}\n" https://www.example.de/.env
# Tikimasi: 404, nes vykdomas tik Front-Controller
curl -s -o /dev/null -w "%{http_code}\n" https://www.example.de/info.php
# Kurie blokai perduoda PHP-FPM?
sudo nginx -T 2>/dev/null | grep -nE "location|fastcgi_pass"
```

Prieš kiekvieną didesnį pakeitimą išsaugokite pilną `nginx -T` išvestį su data. Joje yra visa veiksminga konfigūracija, įskaitant visus įtrauktus failus. Jei po pakeitimo kas nors nepavyksta, palyginimas iš karto parodo, kas skiriasi. Kitos kritinės spragos atveju taip turėsite ir patikimą inventorizacijos pagrindą nereikalaujant pirma rinkti failų.

> **Patarimas:**
> Konfigūraciją pirmiausia keiskite testinėje aplinkoje arba serverio bloko kopijoje. Pamirštas įėjimo taškas, pavyzdžiui, mokėjimo atgalinis kvietimas (callback), kitaip pastebimas tik tada, kai nebelieka užsakymų.

## Kaip PHP SOS padeda konkrečiai?

- **Perskaityti konfigūraciją:** visą Nginx konfigūraciją analizuojame su `nginx -T` ir kiekvieną PHP perdavimą priskiriame jo svetainei ir baseinui.
- **Nustatyti įėjimo taškus:** kartu su jūsų kūrėjais nustatome, kurie scenarijai turi būti vykdomi, ir užblokuojame likusius.
- **Įgyvendinti ir išbandyti:** pritaikome serverio blokus ir baseinus, tikriname su `nginx -t` ir išbandome formas, mokėjimo kelius ir įkėlimus.
- **Apsaugoti ilgam:** konfigūracija tampa mūsų [serverio sutvirtinimo](https://phpsos.de/lt/leistungen/server-haertung/) ir jūsų serverio dokumentacijos dalimi.


## Dažni klausimai

**Ar po PHP atnaujinimo reikia iš naujo paleisti Nginx?**  
PHP pataisai ne, nes Nginx neturi PHP. Iš naujo paleisti reikia visas PHP-FPM paslaugas. Jei kartu keičiate ir Nginx konfigūraciją, prieš tai patikrinkite ją su nginx -t ir tada iš naujo įkelkite Nginx.

**Kodėl PHP perduoti tik index.php?**  
Daugelis šiuolaikinių programų turi vieną įėjimo tašką, Front-Controller. Jei PHP-FPM perduodamas tik šis failas, įterpto PHP failo kitoje vietoje per naršyklę vykdyti nebus įmanoma. Sistemose su daug įėjimo taškų šis šablonas neįmanomas.

**Ką duoda security.limit_extensions PHP-FPM?**  
Nustatymas nurodo, kuriuos failų plėtinius PHP-FPM vykdo kaip scenarijų. Pasak PHP vadovo, numatytieji yra .php .phar; rekomenduojama apriboti iki .php. Tai pagauna žiniatinklio serverio konfigūracijos klaidas, bet jos nepakeičia.

**Ar Nginx taisyklės yra apsauga nuo PHP2Shell?**  
Ne. PHP2Shell slypi PHP interpretatoriuje ir uždaroma tik atnaujinus į ištaisytą versiją ir iš naujo paleidus visus darbinius procesus (worker). Saugi Nginx konfigūracija sumažina atakos paviršių ir apriboja žalą po įsilaužimo.

## Šaltiniai

- [Nginx: ngx_http_core_module](https://nginx.org/en/docs/http/ngx_http_core_module.html)
- [Nginx: ngx_http_fastcgi_module](https://nginx.org/en/docs/http/ngx_http_fastcgi_module.html)
- [PHP vadovas: FPM konfigūracija](https://www.php.net/manual/en/install.fpm.configuration.php)
- [OWASP Cheat Sheets](https://cheatsheetseries.owasp.org/)
