Lyhyesti: Asettaaksenne Nginxin PHP:lle turvallisesti välitätte PHP-FPM:lle vain skriptit, jotka todella ovat olemassa, front controller -sovelluksissa jopa vain tiedoston index.php. Lisäksi tarvitaan estetyt piilotiedostot kuten .git ja .env, oletuspalvelin tuntemattomille isäntänimille, sopivat kokorajat ja security.limit_extensions = .php poolissa. Se ei suojaa PHP:n omilta aukoilta, mutta rajaa, mitä virheen jälkeen voidaan suorittaa.
Vaarallisimmat rivit ovat PHP-locationissa
PHP2Shellin jälkeen monet tiimit tarkistavat PHP-FPM-versionsa ja poolinsa, kuten sivu Nginxin ja PHP-FPM:n suojaus kuvaa, ja käynnistävät päivityksen jälkeen kaikki workerit uudelleen. Toinen katse kohdistuu Nginxin asetuksiin itseensä. Siellä ratkaistaan, mitkä tiedostot ylipäätään suoritetaan PHP:nä.
Monessa asetuksessa on lohko, joka välittää jokaisen .php-pyynnön PHP-FPM:lle riippumatta siitä, missä tiedosto sijaitsee. Jos sisäänajettu PHP-tiedosto päätyy upload-kansioon, palvelin suorittaa sen. Tiedostovirheestä tulee näin takaportti.
Tämä kirjoitus keskittyy Nginxin puoleen: mitkä direktiivit ratkaisevat, miten location-lohkojen järjestys vaikuttaa ja miten testaatte tuloksen.
Miten Nginx päättää, mikä lohko pätee
Joka haluaa asettaa Nginxin PHP:lle turvallisesti, tarvitsee tuntea location-lohkojen valinta. Nginxin dokumentaation mukaan se etenee näin:
- Tarkka osuma
location =-lohkoon lopettaa haun heti. - Etuliite-locationeista muistetaan pisin sopiva. Jos siinä on
^~, säännöllisiä lausekkeita ei enää tarkisteta. - Muuten säännölliset lausekkeet (
~,~*) tarkistetaan asetustiedoston järjestyksessä; ensimmäinen osuma voittaa. - Jos mikään säännöllinen lauseke ei osu, voimaan tulee muistettu etuliite-location.
Tästä seuraa kaksi käytännön sääntöä. PHP:n esto upload-kansioissa on joko luotava ^~-etuliitteenä tai sen on oltava säännöllisenä lausekkeena ennen yleistä PHP-lohkoa. Ja tavallinen etuliite-location kuten location /uploads/ ei suojaa, koska .php-päätteen säännöllinen lauseke ohittaa sen.
Turvallinen perusasetus
Seuraava esimerkki näyttää palvelinlohkon sovellukselle, jossa on front controller, kuten Laravelissa, Symfonyssa, Shopware 6:ssa tai monissa omissa kehityksissä on tavallista. Polut, socketin ja varmenteet mukautatte omiin tarpeisiinne.
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;
# Salli Let's Encrypt ja muut tunnetut polut
location ^~ /.well-known/ {
try_files $uri =404;
}
# Estä piilotetut tiedostot ja kansiot (.git, .env, .htaccess)
location ~ /\. {
deny all;
}
location / {
try_files $uri $uri/ /index.php$is_args$args;
}
# Vain front controller välitetään PHP-FPM:lle
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;
}
# Mitään muuta PHP-tiedostoa ei suoriteta
location ~ \.php$ {
return 404;
}
}
$realpath_root ratkaisee symboliset linkit. Se on tärkeää käyttöönotoissa, joissa symlink vaihtuu nykyiseen julkaisuun, jotta PHP-FPM ja OPcache näkevät oikean polun. Huomatkaa lisäksi: Nginxin dokumentaation mukaan fastcgi_param-direktiivit periytyvät ylemmiltä tasoilta vain, jos nykyisellä tasolla ei ole omia. Siksi include fastcgi_params; kuuluu samaan lohkoon.
Klassisilla CMS:illä kuten WordPress, TYPO3 tai Contao on useita sisääntulopisteitä. Niissä korvaatte front controller -lohkon yleisellä PHP-locationilla, joka välittää vain olemassa olevat tiedostot (try_files $uri =404;), ja estätte suorituksen kaikissa kirjoitettavissa kansioissa. Miten se onnistuu, kerrotaan kohdassa PHP:n suorituksen kielto upload-kansioissa.
Toinen varmistus PHP-FPM:ssä
Nginx päättää, mitä välitetään, PHP-FPM päättää, mitä se suorittaa. PHP-käsikirjan mukaan PHP-FPM suorittaa oletuksena tiedostot päätteillä .php ja .phar ja suosittelee itse rajaamaan sen arvoon .php. Se sieppaa verkkopalvelimen asetusvirheet.
; poolissa, esim. /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
Socketin pitäisi olla saavutettavissa vain Nginxille. FPM-portteja verkossa, kuten 9000, ei pidä avata ulospäin. Miten palvelin yleisesti näyttää vain tarvittavat portit, kuvaa Palomuuri verkkopalvelimelle: avatkaa vain tarvittavat portit.
Tuntemattomat isäntänimet ja muut säätöruuvit
Ilman omaa oletuspalvelinta Nginx vastaa tuntemattomien isäntänimien pyyntöihin ensimmäisellä sopivalla palvelinlohkolla. Automatisoidut skannaukset, jotka puhuttelevat vain IP-osoitetta, päätyvät silloin suoraan sovellukseenne. Oma oletuspalvelin päättää tällaiset pyynnöt ilman vastausta.
server {
listen 80 default_server;
listen 443 ssl default_server;
server_name _;
ssl_reject_handshake on;
return 444;
}
Muita hyviksi havaittuja kohtia:
| Säätöruuvi | Suositus | Tarkoitus |
|---|---|---|
server_tokens |
off |
ei versionumeroa otsakkeessa ja virhesivuilla |
client_max_body_size |
sopiva arvoon post_max_size |
hylkää suuret pyynnöt aikaisin |
autoindex |
pois (oletus) | ei hakemistolistauksia |
fastcgi_hide_header |
X-Powered-By |
ei PHP-versiota ulospäin |
| Tilasivut | pm.status_path vain sisäisesti |
ei käyttötietoja julkisesti |
| Varmuuskopiotiedostot | estäkää tai poistakaa .sql, .zip, .bak verkkojuuresta |
ei tietokantojen latausta |
Lisää versiotiedoista kirjoituksessa expose_php ja Server-otsakkeet.
Yksi säätöruuvi koskee sallittuja HTTP-metodeja. Useimmat verkkosivustot tarvitsevat vain GET-, HEAD- ja POST-metodit. Direktiivillä limit_except muut metodit voidaan hylätä locationissa; Nginxin dokumentaation mukaan GET-metodin salliminen sallii automaattisesti myös HEAD-metodin. Tarkistakaa etukäteen, käyttävätkö sovelluksenne rajapinnat esimerkiksi PUT- tai DELETE-metodia, sillä REST-rajapinnat tekevät niin usein.
Testatkaa ennen uudelleenlatausta
Tarkistatte jokaisen muutoksen ensin komennolla nginx -t ja ladatte Nginxin uudelleen vasta sen jälkeen. Sen jälkeen testaatte toiminnan ulkopuolelta tavallisilla pyynnöillä omaan verkkotunnukseenne:
sudo nginx -t && sudo systemctl reload nginx
# Odotettu: 403 tai 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
# Odotettu: 404, koska vain front controller suoritetaan
curl -s -o /dev/null -w "%{http_code}\n" https://www.example.de/info.php
# Mitkä lohkot välittävät PHP-FPM:lle?
sudo nginx -T 2>/dev/null | grep -nE "location|fastcgi_pass"
Varmistakaa ennen jokaista suurempaa muutosta komennon nginx -T täydellinen tuloste päivämäärällä. Se sisältää koko voimassa olevan asetuksen kaikkine liitettyine tiedostoineen. Jos muutoksen jälkeen jokin menee pieleen, vertailu näyttää heti, mikä eroaa. Seuraavan kriittisen aukon kohdalla teillä on lisäksi luotettava perusta inventaariolle ilman tiedostojen keräilyä.
Muuttakaa asetuksia ensin testiympäristössä tai palvelinlohkon kopiossa. Unohtunut sisääntulopiste, esimerkiksi maksun callback, huomataan muuten vasta, kun tilaukset jäävät tulematta.
Miten PHP SOS auttaa konkreettisesti?
- Asetusten lukeminen: Käymme läpi koko Nginx-asetuksen komennolla
nginx -Tja yhdistämme jokaisen PHP-välityksen sen verkkosivustoon ja pooliin. - Sisääntulopisteiden määrittäminen: Määritämme yhdessä kehittäjienne kanssa, mitkä skriptit on suoritettava, ja estämme loput.
- Toteutus ja testaus: Mukautamme palvelinlohkot ja poolit, tarkistamme komennolla
nginx -tja testaamme lomakkeet, maksureitit ja lataukset. - Pysyvä suojaus: Asetuksesta tulee osa palvelimen koventamistamme ja palvelimenne dokumentaatiota.
Usein kysytyt kysymykset
Pitääkö Nginx käynnistää uudelleen PHP-päivityksen jälkeen?
PHP-korjausta varten ei, sillä Nginx ei sisällä PHP:tä. Uudelleen on käynnistettävä kaikki PHP-FPM-palvelut. Jos muutatte samalla Nginxin asetuksia, tarkistakaa ne ensin komennolla nginx -t ja ladatkaa Nginx sen jälkeen uudelleen.
Miksi vain index.php välitetään PHP:lle?
Monilla nykyaikaisilla sovelluksilla on yksi ainoa sisääntulopiste, front controller. Jos vain tämä tiedosto välitetään PHP-FPM:lle, muualle ujutettua PHP-tiedostoa ei voi suorittaa selaimen kautta. Järjestelmissä, joissa on monta sisääntulopistettä, tämä malli ei ole mahdollinen.
Mitä security.limit_extensions tuo PHP-FPM:ssä?
Asetus määrää, mitkä tiedostopäätteet PHP-FPM suorittaa skripteinä. PHP-käsikirjan mukaan oletus on .php .phar; suositus on rajata arvoon .php. Se sieppaa verkkopalvelimen asetusvirheet mutta ei korvaa niitä.
Ovatko Nginx-säännöt suoja PHP2Shelliä vastaan?
Eivät. PHP2Shell on PHP-tulkissa, ja se suljetaan vain päivityksellä korjattuun versioon ja kaikkien workerien uudelleenkäynnistyksellä. Turvallinen Nginx-asetus pienentää hyökkäyspintaa ja rajaa vahingon murron jälkeen.