Konfiguracja nginx za NAT

W tym poradniku skupimy się na poprawnym wystawieniu strony internetowej przez serwer WWW nginx.

1. Aktualizacja systemu

Na początku aktualizujemy listę pakietów oraz zainstalowane oprogramowanie:

apt update
apt upgrade -y

Następnie instalujemy podstawowe narzędzia:

apt install -y curl wget ca-certificates unzip

2. Instalacja nginx

Instalujemy pełną wersję nginx:

apt install -y nginx-full

Po instalacji nginx prawdopodobnie będzie próbował uruchomić się na standardowym porcie 80.

Możemy sprawdzić jego stan:

systemctl status nginx

oraz aktualnie otwarte porty:

ss -lntp

Na tym etapie interesuje nas zmiana konfiguracji nginx tak, aby nie używał portów 80 i 443.


3. Usunięcie domyślnej konfiguracji nginx

Debian domyślnie tworzy konfigurację:

/etc/nginx/sites-available/default

oraz link:

/etc/nginx/sites-enabled/default

Najprościej usunąć aktywny link:

rm -f /etc/nginx/sites-enabled/default

Nie jest konieczne usuwanie samego pliku z sites-available.


4. Instalacja PHP-FPM

Instalujemy PHP wraz z najczęściej używanymi rozszerzeniami:

apt install -y \
    php-fpm \
    php-cli \
    php-curl \
    php-gd \
    php-mbstring \
    php-mysql \
    php-xml \
    php-zip \
    php-intl \
    php-bcmath \
    php-opcache

Sprawdzamy zainstalowaną wersję PHP:

php -v

Przykładowo na Debianie może pojawić się:

PHP 8.4.x

Możemy również sprawdzić dostępny socket PHP-FPM:

ls -la /run/php/

Przykładowy wynik:

php8.4-fpm.sock
php8.4-fpm.pid

To właśnie socket:

/run/php/php8.4-fpm.sock

będziemy później wykorzystywać w nginx.

W dalszej części poradnika używam PHP 8.4. Jeżeli system posiada inną wersję, należy odpowiednio zmienić nazwę socketu.


5. Utworzenie katalogu strony

Załóżmy, że będziemy obsługiwali domenę:

example.pl

Tworzymy dla niej katalog:

mkdir -p /var/www/example.pl/public

Nadajemy odpowiednie uprawnienia:

chown -R www-data:www-data /var/www/example.pl

Możemy od razu utworzyć prosty plik PHP:

nano /var/www/example.pl/public/index.php

i wpisać:

<?php

phpinfo();

6. nginx na niestandardowym porcie HTTP

Tworzymy konfigurację:

nano /etc/nginx/sites-available/example.pl.conf

Na początek konfigurujemy wyłącznie HTTP:

server {
    listen 10080;
    listen [::]:10080;

    server_name example.pl www.example.pl;

    root /var/www/example.pl/public;
    index index.php index.html;

    access_log /var/log/nginx/example.pl-access.log;
    error_log /var/log/nginx/example.pl-error.log;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;

        fastcgi_pass unix:/run/php/php8.4-fpm.sock;
    }

    location ~ /\.ht {
        deny all;
    }
}

Najważniejszym elementem jest:

listen 10080;

Zamiast standardowego:

listen 80;

nginx będzie więc nasłuchiwał na porcie 10080.

Aktywujemy konfigurację:

ln -s /etc/nginx/sites-available/example.pl.conf \
      /etc/nginx/sites-enabled/example.pl.conf

Sprawdzamy składnię:

nginx -t

Jeżeli otrzymamy:

syntax is ok
test is successful

restartujemy nginx:

systemctl restart nginx

7. Sprawdzenie portu

Sprawdzamy:

ss -lntp | grep nginx

Powinniśmy zobaczyć między innymi:

LISTEN 0 511 0.0.0.0:10080

oraz ewentualnie:

LISTEN 0 511 [::]:10080

Strona będzie dostępna pod adresem:

http://example.pl:10080/

albo bezpośrednio przez IP:

http://PUBLICZNY_ADRES_IP:10080/

jeżeli przekierowanie NAT zostało odpowiednio skonfigurowane.


8. Firewall

Jeżeli na VPS działa ufw, należy zezwolić na nowe porty:

ufw allow 10080/tcp
ufw allow 10443/tcp

Możemy sprawdzić reguły:

ufw status

Jeżeli firewall obsługiwany jest przez nftables, odpowiednie porty również muszą być przepuszczone.

Przykładowo:

nft add rule inet filter input tcp dport 10080 accept
nft add rule inet filter input tcp dport 10443 accept

Należy przy tym pamiętać, że ręcznie dodane w ten sposób reguły mogą nie przetrwać restartu systemu. W środowisku produkcyjnym powinny znaleźć się w trwałej konfiguracji nftables.



9. Konfiguracja HTTPS na porcie 10443

Zakładając, że posiadamy już certyfikat:

/etc/ssl/example.pl/fullchain.pem
/etc/ssl/example.pl/privkey.pem

możemy rozszerzyć konfigurację nginx.

Edytujemy:

nano /etc/nginx/sites-available/example.pl.conf

Konfiguracja może wyglądać następująco:

server {
    listen 10080;
    listen [::]:10080;

    server_name example.pl www.example.pl;

    return 301 https://$host:10443$request_uri;
}

server {
    listen 10443 ssl;
    listen [::]:10443 ssl;

    server_name example.pl www.example.pl;

    root /var/www/example.pl/public;
    index index.php index.html;

    ssl_certificate     /etc/ssl/example.pl/fullchain.pem;
    ssl_certificate_key /etc/ssl/example.pl/privkey.pem;

    ssl_protocols TLSv1.2 TLSv1.3;

    access_log /var/log/nginx/example.pl-access.log;
    error_log /var/log/nginx/example.pl-error.log;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        include snippets/fastcgi-php.conf;

        fastcgi_pass unix:/run/php/php8.4-fpm.sock;
    }

    location ~ /\.ht {
        deny all;
    }
}

Sprawdzamy konfigurację:

nginx -t

i przeładowujemy nginx:

systemctl reload nginx

Strona HTTPS będzie dostępna jako:

https://example.pl:10443/

10. Przekierowanie HTTP → HTTPS

W przypadku niestandardowych portów trzeba pamiętać o jednym ważnym szczególe.

Typowa konfiguracja nginx zawiera:

return 301 https://$host$request_uri;

W naszym przypadku byłoby to jednak błędne.

Przeglądarka zinterpretowałaby:

https://example.pl/

jako połączenie na standardowy port:

443

Dlatego przy publicznym HTTPS działającym rzeczywiście na 10443 należy używać:

return 301 https://$host:10443$request_uri;

Dzięki temu:

http://example.pl:10080/test

zostanie przekierowane na:

https://example.pl:10443/test

11. Kiedy NIE dodawać :10443 do przekierowania

Istnieje jednak drugi scenariusz.

Załóżmy, że NAT wygląda tak:

PUBLIC_IP:80  -> VPS:10080
PUBLIC_IP:443 -> VPS:10443

Z punktu widzenia użytkownika strona działa wtedy normalnie:

https://example.pl/

Mimo że nginx wewnątrz VPS nasłuchuje na:

10443

W takim przypadku przekierowanie powinno być standardowe:

return 301 https://$host$request_uri;

a nie:

return 301 https://$host:10443$request_uri;

Trzeba więc rozróżnić port nginx na VPS od portu widocznego z Internetu.


12. PHP-FPM

nginx nie wykonuje kodu PHP samodzielnie.

Po otrzymaniu zapytania do:

index.php

przekazuje je do PHP-FPM poprzez:

/run/php/php8.4-fpm.sock

Możemy sprawdzić stan PHP-FPM:

systemctl status php8.4-fpm

oraz uruchomić usługę automatycznie przy starcie:

systemctl enable php8.4-fpm

Analogicznie dla nginx:

systemctl enable nginx

13. Test PHP

Tworzymy:

nano /var/www/example.pl/public/test.php

z zawartością:

<?php

echo 'PHP działa poprawnie.<br>';
echo 'Wersja PHP: ' . PHP_VERSION;

Następnie otwieramy:

http://example.pl:10080/test.php

lub:

https://example.pl:10443/test.php

Powinniśmy otrzymać informację o działającym PHP.

Po wykonaniu testów plik można usunąć:

rm /var/www/example.pl/public/test.php

Szczególnie nie należy pozostawiać publicznie dostępnego:

phpinfo();

na serwerze produkcyjnym.


14. Testowanie nginx z poziomu VPS

Jeżeli DNS nie jest jeszcze skonfigurowany, możemy sprawdzić nginx lokalnie.

HTTP:

curl -I \
    -H 'Host: example.pl' \
    http://127.0.0.1:10080/

HTTPS:

curl -kI \
    -H 'Host: example.pl' \
    https://127.0.0.1:10443/

Możemy także przetestować stronę przez publiczny adres:

curl -I http://PUBLIC_IP:10080/

Jeżeli nginx działa lokalnie, ale nie działa przez publiczny adres IP, problem najprawdopodobniej znajduje się po stronie:

  • DNAT,
  • FORWARD,
  • firewalla hosta,
  • firewalla VPS,
  • albo routingu.

15. Sprawdzanie logów

Najważniejszym źródłem informacji podczas diagnostyki są logi nginx.

Dla naszej domeny:

tail -f /var/log/nginx/example.pl-access.log

oraz:

tail -f /var/log/nginx/example.pl-error.log

Log samej usługi nginx:

journalctl -u nginx -f

PHP-FPM:

journalctl -u php8.4-fpm -f

16. Podstawowe zabezpieczenia nginx

Możemy nieco poprawić domyślną konfigurację.

Edytujemy:

nano /etc/nginx/nginx.conf

Można między innymi wyłączyć prezentowanie wersji nginx:

server_tokens off;

W sekcji http warto również ustawić rozsądne limity:

client_max_body_size 64M;

Po każdej zmianie:

nginx -t && systemctl reload nginx

17. PHP — podstawowa konfiguracja

Konfigurację PHP-FPM znajdziemy przykładowo w:

/etc/php/8.4/fpm/php.ini

Możemy dostosować między innymi:

memory_limit = 256M
upload_max_filesize = 64M
post_max_size = 64M
max_execution_time = 60

Po zmianach restartujemy PHP-FPM:

systemctl restart php8.4-fpm

18. Przykładowa kompletna konfiguracja nginx

Docelowy plik:

/etc/nginx/sites-available/example.pl.conf

może wyglądać następująco:

server {
    listen 10080;
    listen [::]:10080;

    server_name example.pl www.example.pl;

    return 301 https://$host:10443$request_uri;
}

server {
    listen 10443 ssl;
    listen [::]:10443 ssl;

    server_name example.pl www.example.pl;

    root /var/www/example.pl/public;
    index index.php index.html;

    ssl_certificate     /etc/ssl/example.pl/fullchain.pem;
    ssl_certificate_key /etc/ssl/example.pl/privkey.pem;

    ssl_protocols TLSv1.2 TLSv1.3;

    access_log /var/log/nginx/example.pl-access.log;
    error_log /var/log/nginx/example.pl-error.log;

    client_max_body_size 64M;

    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    location ~ \.php$ {
        try_files $uri =404;

        include fastcgi_params;

        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param SCRIPT_NAME $fastcgi_script_name;

        fastcgi_pass unix:/run/php/php8.4-fpm.sock;
        fastcgi_index index.php;
    }

    location ~ /\.(?!well-known).* {
        deny all;
    }
}

Aktywujemy stronę:

ln -s /etc/nginx/sites-available/example.pl.conf \
      /etc/nginx/sites-enabled/example.pl.conf

a następnie:

nginx -t && systemctl reload nginx

 

Czy ta informacja była pomocna?

Podobne artykuły

Konfiguracja serwera FTP za NAT

Jeżeli korzystasz z VPS-a naszej firmy działającego za NAT-em, możesz bez problemu uruchomić na...