Kako ograničiti broj veza (zahtjeva) u NGINX-u


NGINX se isporučuje s različitim modulima koji korisnicima omogućavaju kontrolu prometa na svojim web stranicama, web aplikacijama, kao i drugim web resursima. Jedan od ključnih razloga za ograničavanje saobraćaja ili pristupa je sprečavanje zloupotreba ili napada određenih vrsta kao što su DoS (Odbijanje usluge) napadi.

Postoje tri glavna načina ograničavanja upotrebe ili prometa u NGINX-u:

  1. Ograničavanje broja veza (zahtjeva).
  2. Ograničavanje broja zahtjeva.
  3. Ograničavanje propusnog opsega.

Gore navedeni NGINX pristupi upravljanju prometom, u zavisnosti od slučaja upotrebe, mogu se konfigurirati za ograničenje na osnovu definiranog ključa, a najčešći je IP adresa klijenta. NGINX također podržava druge varijable kao što je kolačić sesije i mnoge druge.

U ovom prvom dijelu naše serije od tri dijela, razgovarat ćemo o tome kako ograničiti broj veza u NGINXu da zaštitite svoje web stranice/aplikacije.

  • Kako ograničiti broj veza (zahtjeva) u NGINX-u – 1. dio
  • Kako ograničiti brzinu konekcija (zahtjeva) u NGINX-u – 2. dio
  • Kako ograničiti upotrebu propusnog opsega u NGINX-u – 3. dio

Imajte na umu da će NGINX smatrati vezu za ograničenje samo ako ima zahtjev koji server obrađuje i cijelo zaglavlje zahtjeva je već pročitano. Stoga se ne računaju sve klijentske veze.

Ograničavanje broja veza u NGINX-u

Prvo, trebate definirati zonu dijeljene memorije koja pohranjuje metriku veze za različite ključeve, koristeći limit_conn_zone direktivu. Kao što je već spomenuto, ključ može biti tekst, varijabla kao što je klijentova udaljena IP adresa ili kombinacija to dvoje.

Ova direktiva koja je važeća unutar HTTP konteksta uzima dva parametra: ključ i zonu (u formatu zone_name:size).

limit_conn_zone $binary_remote_addr zone=limitconnbyaddr:20m;

Za postavljanje koda statusa odgovora koji se vraća na odbijene zahtjeve, koristite limit_conn_status direktivu koja uzima HTTP statusni kod kao parametar. Vrijedi unutar HTTP, serverskog i lokacijskog konteksta.

limit_conn_status 429;

Da ograničite veze, koristite limint_conn direktivu da postavite memorijsku zonu koja će se koristiti i maksimalni broj dozvoljenih veza kao što je prikazano u sljedećem isječku konfiguracije. Ova direktiva je važeća unutar HTTP, serverskog i lokacijskog konteksta.

limit_conn   limitconnbyaddr  50;

Evo kompletne konfiguracije:

upstream api_service {
    server 127.0.0.1:9051;
    server 10.1.1.77:9052;
}
limit_conn_zone $binary_remote_addr zone=limitconnbyaddr:20m;
limit_conn_status 429;

server {
    listen 80;
    server_name testapp.linux-console.net;
    root /var/www/html/testapp.linux-console.net/build;
    index index.html;

    limit_conn   limitconnbyaddr  50;

    #include snippets/error_pages.conf;
    proxy_read_timeout 600;
    proxy_connect_timeout 600;
    proxy_send_timeout 600;
    location / {
        try_files $uri $uri/ /index.html =404 =403 =500;
    }
    location /api {
        proxy_pass http://api_service;

        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
   }
}

Sačuvajte datoteku i zatvorite je.

Zatim provjerite da li je NGINX konfiguracija u redu tako što ćete pokrenuti sljedeću naredbu:

sudo nginx -t

Zatim ponovo učitajte uslugu NGINX da izvršite nedavne promjene:

sudo systemctl reload nginx

Provjera ograničenja Nginx veze

Kada klijent premaši maksimalan broj dozvoljenih veza, NGINX vraća grešku “429 Previše zahtjeva” klijentu i registruje unos kao što je onaj ispod u grešci log fajl:

2022/03/15 00:14:00 [error] 597443#0: *127 limiting connections by zone "limitconnbyaddr", client: x.x.x.x, server: testapp.tecmimt.com, request: "GET /static/css/main.63fdefff.chunk.css.map HTTP/1.1", host: "testapp.tecmimt.com"

Ograničavanje Nginx broja konekcija na aplikaciju

Također možete ograničiti broj veza za dati server korištenjem varijable $server_name:

upstream api_service {
    server 127.0.0.1:9051;
    server 10.1.1.77:9052;
}
limit_conn_zone $server_name zone=limitbyservers:10m;
limit_conn_status 429;

server {
    listen 80;
    server_name testapp.linux-console.net;
    root /var/www/html/testapp.linux-console.net/build;
    index index.html;

     limit_conn  limitbyservers  2000;

    #include snippets/error_pages.conf;
    proxy_read_timeout 600;
    proxy_connect_timeout 600;
    proxy_send_timeout 600;
    location / {
        try_files $uri $uri/ /index.html =404 =403 =500;
    }
    location /api {
        proxy_pass http://api_service;

        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
   }
}

Ova konfiguracija omogućava NGINX-u da ograniči ukupan broj konekcija na virtuelni server koji pokreće aplikaciju testapp.linux-console.net, na 2000 veza.

Napomena: Ograničavanje konekcija na osnovu IP adrese klijenta ima lošu stranu. Možda ćete na kraju ograničiti veze za više od jednog korisnika, posebno ako je mnogo korisnika koji pristupaju vašoj aplikaciji na istoj mreži i rade iza NAT – sve njihove veze poticat će sa iste IP adrese.

U takvom scenariju, možete koristiti jednu ili više varijabli dostupnih u NGINX-u koje mogu identificirati klijenta na razini aplikacije, primjer je kolačić sesije.

Možda će vam se svidjeti i sljedeći članci vezani za Nginx:

  • Kako kreirati prilagođenu stranicu sa greškom 404 u NGINX-u
  • Kako kontrolisati pristup na osnovu IP adrese klijenta u NGINX-u
  • Kako keširati sadržaj u NGINX-u
  • Kako omogućiti HTTP/2.0 u Nginxu
  • Kako koristiti Nginx kao HTTP balanser opterećenja u Linuxu

To je to za sada! U sljedećem dijelu ove serije raspravljat ćemo o još jednoj korisnoj tehnici upravljanja prometom u NGINX-u – ograničavanju stope zahtjeva. Do tada ostanite s nama.