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


NGINX isporučuje se s raznim modulima koji korisnicima omogućuju kontrolu prometa na njihovim web-mjestima, web-aplikacijama, kao i drugim web-resursima. Jedan od ključnih razloga za ograničavanje prometa ili pristupa je sprječavanje zloupotreba ili napada određenih vrsta kao što su DoS (Uskraćivanje usluge) napadi.

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

  1. Ograničenje broja veza (zahtjeva).
  2. Ograničenje stope zahtjeva.
  3. Ograničenje propusnosti.

Gore navedeni NGINX pristupi upravljanju prometom, ovisno o slučaju upotrebe, mogu se konfigurirati za ograničavanje na temelju definiranog ključa, a najčešći je klijentova IP adresa. 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, raspravljat ćemo o tome kako ograničiti broj veza u NGINXu radi zaštite vaših web stranica/aplikacija.

  • Kako ograničiti broj veza (zahtjeva) u NGINX-u – 1. dio
  • Kako ograničiti stopu povezivanja (zahtjeva) u NGINX-u – 2. dio
  • Kako ograničiti korištenje propusnosti u NGINX-u – 3. dio

Imajte na umu da će NGINX uzeti u obzir vezu za ograničavanje samo ako ima zahtjev koji poslužitelj obrađuje i cijelo je zaglavlje zahtjeva već pročitano. Stoga se ne broje sve veze klijenata.

Ograničenje broja veza u NGINX

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

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

limit_conn_zone $binary_remote_addr zone=limitconnbyaddr:20m;

Za postavljanje koda statusa odgovora koji se vraća na odbijene zahtjeve, upotrijebite direktivu limit_conn_status koja uzima HTTP kod statusa kao parametar. Vrijedi unutar konteksta HTTP-a, poslužitelja i lokacije.

limit_conn_status 429;

Da biste ograničili veze, upotrijebite direktivu limint_conn za postavljanje memorijske zone koja će se koristiti i najveći broj dopuštenih veza kao što je prikazano u sljedećem konfiguracijskom isječku. Ova je direktiva važeća unutar konteksta HTTP-a, poslužitelja i lokacije.

limit_conn   limitconnbyaddr  50;

Ovdje je kompletna konfiguracija:

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";
   }
}

Spremite datoteku i zatvorite je.

Zatim provjerite je li konfiguracija NGINX u redu pokretanjem sljedeće naredbe:

sudo nginx -t

Zatim ponovno učitajte uslugu NGINX kako biste izvršili nedavne promjene:

sudo systemctl reload nginx

Provjera Nginx ograničenja veze

Kada klijent premaši maksimalan broj dopuštenih veza, NGINX klijentu vraća pogrešku “429 Previše zahtjeva” i registrira unos kao što je ovaj ispod u pogrešci log datoteka:

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 veza s aplikacijom

Također možete ograničiti broj veza za određeni poslužitelj 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ćuje NGINX da ograniči ukupan broj veza na virtualni poslužitelj koji pokreće aplikaciju testapp.linux-console.net, na 2000 veza.

Napomena: Ograničavanje veza na temelju klijentovog IP-a ima lošu stranu. Možete na kraju ograničiti veze za više od samo jednog korisnika, posebno ako je mnogo korisnika koji pristupaju vašoj aplikaciji na istoj mreži i rade iza NAT-a – sve njihove veze potjecat će s iste IP adrese.

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

Možda bi vam se svidjeli i sljedeći članci povezani s Nginxom:

  • Kako stvoriti prilagođenu stranicu s pogreškom 404 u NGINX-u
  • Kako kontrolirati pristup na temelju IP adrese klijenta u NGINX-u
  • Kako predmemorirati sadržaj u NGINX
  • Kako omogućiti HTTP/2.0 u Nginxu
  • Kako koristiti Nginx kao HTTP Load Balancer u Linuxu

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