Nginx reverse proxy konfigūravimas

Kas yra reverse proxy ir kodėl jis tau reikalingas

Jei esi bent kiek susidūręs su web serverių administravimu, tikriausiai girdėjai apie reverse proxy. Bet kas tai iš tikrųjų yra? Paprastai tariant, tai tarpininkas tarp tavo vartotojų ir backend serverių. Vartotojas kreipiasi į vieną adresą, o reverse proxy nukreipia jo užklausą į tinkamą serverį užkulisiuose.

Nginx šioje srityje yra tikras žvaigždė. Jis greitas, efektyvus ir nesuvalgys tavo serverio resursų kaip kai kurie kiti sprendimai. Galiu pasakyti iš patirties – kai pirmą kartą perkėliau projektą nuo Apache mod_proxy prie Nginx, skirtumas buvo akivaizdus. Serveris tiesiog atsikvėpė.

Reverse proxy naudojimas duoda daugybę privalumų: gali lengvai paskirstyti apkrovą tarp kelių serverių, pridėti SSL sertifikatus vienoje vietoje, paslėpti savo tikrąją infrastruktūrą nuo išorinio pasaulio, įdiegti papildomą saugumo sluoksnį. Be to, tai puikus būdas paleisti kelis skirtingus projektus ant vieno serverio su vienu IP adresu.

Pasiruošimas darbui: kas tau reikės

Prieš pradedant konfigūruoti, įsitikink, kad turi įdiegtą Nginx. Daugumoje Linux distribucijų tai paprasta:

sudo apt update
sudo apt install nginx

Arba jei naudoji CentOS/RHEL:

sudo yum install nginx

Patikrink, ar Nginx sėkmingai paleistas:

sudo systemctl status nginx

Jei viskas gerai, turėtum matyti „active (running)” būseną. Dabar jau gali pradėti konfigūruoti.

Nginx konfigūracijos failai paprastai guli /etc/nginx/ kataloge. Pagrindinis failas yra nginx.conf, bet daugelis administratorių (ir aš pats) mėgsta laikyti atskirus konfigūracijos failus kiekvienam projektui /etc/nginx/sites-available/ kataloge, o paskui juos suaktyvinti sukuriant simbolinį linką /etc/nginx/sites-enabled/ kataloge.

Paprasta reverse proxy konfigūracija

Pradėkime nuo paprasčiausio pavyzdžio. Tarkime, turi Node.js aplikaciją, kuri veikia ant 3000 porto, ir nori, kad ji būtų pasiekiama per standartinį 80 portą.

Sukurk naują konfigūracijos failą:

sudo nano /etc/nginx/sites-available/mano-projektas

Ir įrašyk tokią konfigūraciją:

server {
listen 80;
server_name example.com www.example.com;

location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}

Ką čia darome? listen 80 nurodo, kad klausomės 80 porto. server_name apibrėžia, kokiam domenui ši konfigūracija skirta. O location / blokas sako, kad visos užklausos turi būti nukreiptos į http://localhost:3000.

Tie proxy_set_header parametrai yra svarbūs – jie perduoda informaciją apie originalią užklausą tavo backend aplikacijai. Be jų, tavo aplikacija matytų, kad visos užklausos ateina iš localhost, o ne iš tikrųjų vartotojų.

Suaktyvink konfigūraciją:

sudo ln -s /etc/nginx/sites-available/mano-projektas /etc/nginx/sites-enabled/

Patikrink, ar konfigūracija teisinga:

sudo nginx -t

Jei viskas gerai, perkrauk Nginx:

sudo systemctl reload nginx

SSL sertifikato pridėjimas su Let’s Encrypt

Šiais laikais HTTPS yra ne prabanga, o būtinybė. Laimei, su Let’s Encrypt tai tampa beveik trivialiu dalyku. Pirmiausia įdiegk Certbot:

sudo apt install certbot python3-certbot-nginx

Dabar paleisk Certbot ir leisk jam automatiškai sukonfigūruoti SSL:

sudo certbot --nginx -d example.com -d www.example.com

Certbot pakeis tavo Nginx konfigūraciją, pridės SSL sertifikatus ir net sukonfigūruos automatinį nukreipimą iš HTTP į HTTPS. Po šio proceso tavo konfigūracija atrodys maždaug taip:

server {
listen 80;
server_name example.com www.example.com;
return 301 https://$server_name$request_uri;
}

server {
listen 443 ssl http2;
server_name example.com www.example.com;

ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;

location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_cache_bypass $http_upgrade;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}

Certbot automatiškai sukurs cron job sertifikatų atnaujinimui, tad tau nereikės apie tai galvoti.

Kelių aplikacijų valdymas viename serveryje

Vienas iš gražiausių reverse proxy dalykų – galimybė valdyti kelis projektus ant vieno serverio. Tarkime, turi tris aplikacijas: pagrindinį website, API ir admin panelę.

Galima tai padaryti keliais būdais. Pirmas – naudoti skirtingus subdomenus:

server {
listen 443 ssl http2;
server_name example.com www.example.com;

# SSL konfigūracija...

location / {
proxy_pass http://localhost:3000;
# Kiti proxy_set_header parametrai...
}
}

server {
listen 443 ssl http2;
server_name api.example.com;

# SSL konfigūracija...

location / {
proxy_pass http://localhost:3001;
# Kiti proxy_set_header parametrai...
}
}

server {
listen 443 ssl http2;
server_name admin.example.com;

# SSL konfigūracija...

location / {
proxy_pass http://localhost:3002;
# Kiti proxy_set_header parametrai...
}
}

Antras būdas – naudoti skirtingus URL path’us:

server {
listen 443 ssl http2;
server_name example.com;

location / {
proxy_pass http://localhost:3000;
}

location /api {
proxy_pass http://localhost:3001;
}

location /admin {
proxy_pass http://localhost:3002;
}
}

Aš asmeniškai labiau mėgstu subdomenų variantą – jis aiškesnis ir lengviau valdomas, ypač kai projektai auga.

Load balancing ir failover mechanizmai

Kai tavo projektas auga, vieno serverio gali nepakakti. Čia ir ateina load balancing. Nginx gali paskirstyti apkrovą tarp kelių backend serverių labai elegantiškai.

Apibrėžk upstream bloką:

upstream backend_servers {
least_conn;
server 192.168.1.10:3000 weight=3;
server 192.168.1.11:3000 weight=2;
server 192.168.1.12:3000 weight=1 backup;
}

server {
listen 443 ssl http2;
server_name example.com;

location / {
proxy_pass http://backend_servers;
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503;
proxy_connect_timeout 2s;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}

Šioje konfigūracijoje naudojame least_conn algoritmą, kuris nukreipia užklausas į serverį su mažiausiai aktyvių ryšių. weight parametras leidžia nurodyti, kiek daugiau apkrovos konkretus serveris turėtų gauti. Serveris su backup žyma bus naudojamas tik tada, kai visi kiti neveiks.

proxy_next_upstream direktyva nurodo, kokiais atvejais Nginx turėtų bandyti kitą serverį. Tai labai naudinga, kai vienas iš serverių laikinai neveikia arba grąžina klaidas.

Caching ir performance optimizacija

Reverse proxy gali ne tik nukreipti užklausas, bet ir padėti sumažinti apkrovą backend serveriams naudojant cache. Štai kaip tai padaryti:

Pirmiausia, apibrėžk cache zoną nginx.conf faile arba atskirame konfigūracijos faile:

http {
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m max_size=1g inactive=60m use_temp_path=off;

# Kita konfigūracija...
}

Dabar naudok šį cache savo server bloke:

server {
listen 443 ssl http2;
server_name example.com;

location / {
proxy_cache my_cache;
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
proxy_cache_background_update on;
proxy_cache_lock on;
proxy_cache_valid 200 60m;
proxy_cache_valid 404 10m;
add_header X-Cache-Status $upstream_cache_status;

proxy_pass http://localhost:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}

location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
proxy_cache my_cache;
proxy_cache_valid 200 24h;
expires 30d;
add_header Cache-Control "public, immutable";
proxy_pass http://localhost:3000;
}
}

proxy_cache_use_stale leidžia Nginx atiduoti seną cache turinį, kai backend serveris nepasiekiamas – tai gali išgelbėti tavo svetainę nuo visiško nutrūkimo. add_header X-Cache-Status prideda header’į, kuris parodo, ar atsakymas atėjo iš cache (HIT), ar ne (MISS) – tai labai naudinga debugging’ui.

Statiniams failams (paveikslėliams, CSS, JS) naudojame ilgesnį cache laiką – nėra prasmės kas kartą kreiptis į backend dėl failų, kurie retai keičiasi.

Saugumo aspektai ir geriausia praktika

Reverse proxy gali būti puiki saugumo priemonė, bet tik jei jį tinkamai sukonfigūruoji. Štai keletas svarbių dalykų, į kuriuos verta atkreipti dėmesį.

Pirma, apribokite prieigą prie jūsų backend serverių. Jei Nginx veikia ant to paties serverio, backend aplikacija turėtų klausytis tik localhost. Jei backend’ai yra atskiruose serveriuose, naudokite firewall taisykles, kad jie būtų pasiekiami tik iš Nginx serverio.

Antra, pridėkite rate limiting, kad apsisaugotumėte nuo DDoS atakų:

http {
limit_req_zone $binary_remote_addr zone=general:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=api:10m rate=30r/s;

# Kita konfigūracija...
}

server {
location / {
limit_req zone=general burst=20 nodelay;
proxy_pass http://localhost:3000;
}

location /api {
limit_req zone=api burst=50 nodelay;
proxy_pass http://localhost:3001;
}
}

Trečia, paslėpkite Nginx versiją ir kitus identifikuojančius header’ius:

http {
server_tokens off;
more_clear_headers Server;

# Arba jei neturite ngx_headers_more modulio:
# Tiesiog naudokite server_tokens off;
}

Ketvirta, naudokite timeout’us, kad apsisaugotumėte nuo slowloris tipo atakų:

server {
client_body_timeout 12;
client_header_timeout 12;
keepalive_timeout 15;
send_timeout 10;

location / {
proxy_pass http://localhost:3000;
proxy_read_timeout 60s;
proxy_connect_timeout 5s;
}
}

Taip pat rekomenduoju reguliariai atnaujinti Nginx ir stebėti jo log’us. Įdiekite fail2ban, kuris automatiškai blokuos IP adresus, rodančius įtartiną elgesį:

sudo apt install fail2ban

Sukurkite fail2ban filter’į Nginx log’ams /etc/fail2ban/filter.d/nginx-limit-req.conf:

[Definition]
failregex = limiting requests, excess:.* by zone.*client:
ignoreregex =

Ir pridėkite jail /etc/fail2ban/jail.local:

[nginx-limit-req]
enabled = true
filter = nginx-limit-req
logpath = /var/log/nginx/error.log
maxretry = 5
findtime = 600
bantime = 3600

Debugging ir problemų sprendimas

Net ir su geriausia konfigūracija, kartais kažkas nueina ne taip. Štai keletas patarimų, kaip diagnozuoti ir išspręsti dažniausias problemas.

Pirmiausia, visada tikrinkite log’us. Nginx turi du pagrindinius log’us: access log ir error log. Paprastai jie yra /var/log/nginx/ kataloge.

Realiu laiku stebėti error log’ą:

sudo tail -f /var/log/nginx/error.log

Jei reikia daugiau informacijos, padidinkite logging level’į savo konfigūracijoje:

error_log /var/log/nginx/error.log debug;

Bet atsargiai – debug režimas generuoja LABAI daug informacijos ir gali užpildyti diską.

Dažna problema – 502 Bad Gateway klaida. Ji paprastai reiškia, kad Nginx negali prisijungti prie backend serverio. Patikrinkite:
– Ar backend aplikacija tikrai veikia?
– Ar teisingas portas konfigūracijoje?
– Ar firewall neblokuoja ryšio?

Jei matote 504 Gateway Timeout, tai reiškia, kad backend per ilgai atsako. Padidinkite timeout’us:

location / {
proxy_pass http://localhost:3000;
proxy_read_timeout 300s;
proxy_connect_timeout 75s;
}

Kartais problema būna su WebSocket’ais. Jei jūsų aplikacija naudoja WebSocket’us (pavyzdžiui, Socket.io), įsitikinkite, kad turite šias eilutes:

proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";

Dar vienas naudingas debugging’o įrankis – curl su verbose režimu:

curl -v https://example.com

Tai parodys visą komunikaciją tarp jūsų ir serverio, įskaitant visus header’ius.

Kai viskas sueina į vieną vietą

Nginx reverse proxy konfigūravimas iš pradžių gali atrodyti sudėtingas, bet kai supranti pagrindinius principus, viskas tampa daug aiškiau. Pradėk nuo paprasto setup’o, testuok, eksperimentuok, ir palaipsniui pridėk sudėtingesnes funkcijas pagal poreikį.

Svarbiausias dalykas – neskubėk. Geriau turėti paprastą, bet veikiančią konfigūraciją, nei sudėtingą, kurios niekas nesupranta (įskaitant tave patį po trijų mėnesių). Visada darykite konfigūracijos backup’us prieš darydami pakeitimus, ir naudokite nginx -t prieš perkraudami serverį.

Reverse proxy yra galingas įrankis, kuris gali ne tik supaprastinti jūsų infrastruktūrą, bet ir padaryti ją greitesnę, saugesnę ir lankstesnę. Su Nginx turite patikimą ir efektyvų sprendimą, kuris atlaikys net ir didelę apkrovą.

Ir nepamirškite – dokumentacija yra jūsų draugas. Nginx dokumentacija yra išsami ir gerai parašyta. Kai kyla klausimų, pirmiausia pažiūrėkite ten. O jei vis tiek neaišku – IT bendruomenė visada pasiruošusi padėti. Tik nepamirškite pasidalinti savo sprendimais su kitais, kai patys išspręsite kokią nors sudėtingą problemą. Taip mes visi tampame geresniais specialistais.

Daugiau

Jupyter Notebook duomenų analizei