Tehnologija Vodič

HAProxy – švajcarski nož za administratore sistema

HAProxy

HAProxy (High Availability Proxy) je load balancer i proxy server softver otvorenog koda. Ovaj alat se često koristi za distribuciju opterećenja između više servera kako bi se poboljšala dostupnost i performanse web aplikacija.

Glavna funkcija HAProxy-a je distribucija ulaznih zahteva od klijenata prema više serverskih instanci (backend serverima) koje nude određenu uslugu. Osim ravnoteže opterećenja, HAProxy pruža i druge mogućnosti, uključujući kontrolu pristupa, detekciju kvarova na serverima, i različite algoritme za distribuciju opterećenja.

Pored toga, može se koristiti za optimizaciju web stranica i aplikacija kroz pravilnu raspodelu opterećenja.

Kao alat postoji od 2001. godine i napisan je u programskom jeziku C. Poznat je po tome da koristi zanemarljivu količinu memorije i CPU resursa, čak i pri vrlo naprednim manipulacijama HTTP saobraćaja.

Takođe važi za veoma bezbedan softver, imajući u vidu da je za poslednjih sedam godina kod njega pronađeno samo petnaest sigurnosnih problema. Četiri od ovih problema bila su specifična za distribuciju, šest je zahtevalo vrlo visok nivo pristupa (što znači da bi sistem administrator koji održava server imao mnogo veći problem od samog HAProxy-a), a poslednjih pet su bili uglavnom vezani za DoS napade.

HAProxy se široko koristi od strane visoko-frekventnih web sajtova, kao što su Twitter, GitHub, Reddit i Stack Overflow, kako bi poboljšao performanse, pouzdanost i bezbednost njihovih usluga.

Balansiranje opterećenja (load balancing)

HAProxy podržava balansiranje opterećenja TCP (sloj 4) i HTTP (sloj 7) saobraćaja sa različitim algoritmima balansiranja opterećenja.

  • TCP mod je brži i idealan za balansiranje različitih protokola koji se oslanjaju na TCP, npr. MySQL, SMTP, Redis, pa čak i HTTP ako niste zainteresovani za inspekciju samog HTTP saobraćaja.
  • HTTP mod je sporiji u odnosu na TCP mod, međutim, brzina kojom HAProxy vrši analizu i manipulaciju HTTP saobraćaja meri se u milisekundama, tako da je termin „sporo“ prilično relativan.

Suzbijanje DoS napada i filtriranje saobraćaja

Osim balansiranja opterećenja, HAProxy ima nekoliko zanimljivih „trikova“ koji mogu pomoći u suzbijanju određenih vrsta napada na uskraćivanje usluge putem HTTP-a i obezbeđivanju stabilnosti servera. Evo nekoliko primera.

Suzbijanje Slowloris napada

Slowloris napadi su vrsta napada na web servere koji se fokusiraju na iskorišćavanje propusta u načinu na koji server obrađuje istovremene veze. Ovaj tip napada koristi tehniku „slow and low“ (sporo i malo) kako bi zauzeo resurse servera i održao otvorene veze sa serverom što je duže moguće.

Slowloris napad se ostvaruje slanjem malih HTTP zahteva ka ciljanom serveru, ali održava te veze otvorenim tako da se resursi servera postepeno iscrpljuju. Na taj način, napad može dovesti do situacije u kojoj server više nije u mogućnosti da prihvata nove veze i pruža usluge legitimnim korisnicima.

Ovaj tip napada može biti posebno efikasan jer se izvodi s malo resursa s napadačeve strane, a istovremeno može uzrokovati ozbiljne poteškoće za ciljani web server. Važno je implementirati određene sigurnosne mere, kao što su postavljanje limita na maksimalan broj otvorenih veza po IP adresi ili korišćenje zaštitnih rešenja poput firewall-a kako bi se sprečili Slowloris napadi.

Mitigacije su moguće pomoću Apache mod_reqtimeout modula, Nginx limit connections po određenoj IP adresi i slično.

HAProxy je takođe event-driven, ali sa inteligentnim mehanizmom zaštite. Da bi se suzbili Slowloris napadi, HAProxy-u je potrebna samo jedna direktiva – timeout http-request 10s – koja definiše maksimalno prihvatljivo vreme za primanje potpunih zaglavlja HTTP zahteva (bez podataka).

Primer:

# Maksimalno vreme za primanje potpunih zaglavlja HTTP zahteva
timeout http-request 10s

Filtriranje IP adresa

Može se reći da smo svi bili u situaciji gde treba filtrirati veliki broj zahteva na osnovu IP adrese klijenta (npr. prilikom suzbijanja DDoS napada koji dolazi iz određenih pod-mreža ili zemalja).

Dakle, pitanje je verovatno „Zašto koristiti HAProxy kada možete koristiti .htaccess ili Nginx vhost?“.

Odgovor je prilično jednostavan: HAProxy je mnogo lakši u smislu CPU i memorije, pogotovo kada je u pitanju filtriranje velikog broja istovremenih zahteva.

Primer koda koji koristi ACL pod nazivom „badguys“. HAProxy će pokušati upariti IP adresu posetioca za svaki HTTP zahtev u listi IP opsega u datoteci badguys.txt. Da bi se lista održala što je moguće kraćom, IP opsezi su navedeni u CIDR notaciji.

Primer:

# Vraća HTTP odgovor sa greškom 403 ako je zahtev došao iz crne liste IP adresa
acl badguys src -f /etc/haproxy/badguys.txt
http-request deny if badguys

Filtriranje User-Agenta

Slično IP adresama, liste datoteka se mogu koristiti za čuvanje drugih informacija. U ovom primeru, želimo blokirati sve zahteve sa određenim nizom u User-Agent headeru, osim kada je zahtev upućen određenom domenu.

Obratite pažnju na direktivu hdr_end, jer se ona podudara sa krajem domena u Host zaglavlju. U zavisnosti od konkretnog slučaja, možda ćete želeti da uparite vrednost koristeći alternativne promenljive kao što su hdr_beg, hdr_sub ili hdr_reg.

Uzvičnik ispred imena ACL označava negaciju. Takođe, imajte na umu da HAProxy ima evaluaciju ACL-a sa kratkim spojem (short-circuit), što znači da će evaluacija ACL-a prestati čim jedan od uslova nije zadovoljen.

Primer:

# Vraća HTTP odgovor sa greškom 403 ako je zahtev došao sa User-Agent headerom sa crne liste
acl badbot hdr_sub(User-Agent) -i -f /etc/haproxy/badbots.txt
acl excluded_domain hdr_end(Host) -i -f /etc/haproxy/exclude.txt
http-request deny if badbot !excluded_domain

Prevencija brute-force napada na prijavljivanje

HAProxy je vrlo koristan kada je reč o filtriranju automatskih napada na prijavljivanje i napada na kontakt forme. U ovom primeru, skoncentrisaćemo se na forme za prijavu.

Za automatske pokušaje prijavljivanja, botovi/skripte obično pokušavaju slanje jednog POST zahteva na određeni URL. Pametniji botovi će pokušati da limitiraju legitimnog korisnika slanjem GET zahteva unapred, ali kako bi uštedeli širinu opsega i vreme, oni neće učitati celu stranicu za prijavljivanje sa svim statičkim resursima.

Da bismo bolje razumeli primer konfiguracije u nastavku, prvo ćemo objasniti određene direktive konfiguracije koje smo pomenuli u ovom primeru:

  • Direktiva cookie insert u back-end-u nalaže HAProxy-u da doda kolačić "SB_TRACK" zaglavljima HTTP odgovora.
  • indirect nalaže HAProxy-u da umetne kolačić ako klijent već nema jedan
  • nocache znači da će HAProxy dodati i "Cache-Control: nocache" zaglavlje odgovora kako bi se sprečilo slučajno keširanje odgovora između klijenta i HAProxy-a (npr. ako postoji keš server ili CDN čvor između njih)
  • bk_nocookie je back-end koji pokazuje na isti web server, ali HAProxy neće dodati praćenje kolačića. Legitimni korisnici će pokupiti kolačić zahtevanjem bilo kog statičkog resursa koji se učitava iz podrazumevanog backenda bk_http.

Logika iza toga je jednostavna – ideja je blokirati botove i zlonamerne korisnike koji pokušavaju da pošalju što više zahteva, a koji neće prikupiti praćenje kolačića.

Pre nego što unesu prijavne podatke, korisnici obično treba da pristupe stranici za prijavljivanje. U našem primeru, legitimni korisnici će pokupiti SB_TRACK kolačić postavljen od strane HAProxy-a kada pristupe toj stranici za prijavljivanje, a prikupljeni kolačić će im kasnije omogućiti slanje prijavnih podataka korišćenjem POST HTTP metode.

Botovi i automatske skripte u većini slučajeva ne mare za prihvatanje kolačića. Oni se lako blokiraju od slanja prijavnih zahteva samo proverom da li su njihovi zahtevi došli sa prethodno prikupljenim SB_TRACK kolačićem.

Primer:

frontend ft_http
...
   acl cms_cookie hdr_sub(cookie) SB_TRACK=c1
   acl cms_admin url_sub /wp-login.php
   acl cms_admin url_beg /admin/

   http-request deny if cms_admin METH_POST !cms_cookie

   use_backend bk_nocookie if cms_admin
   default_backend bk_http

backend bk_http
cookie SB_TRACK insert indirect nocache
server web1 192.168.10.10:80 cookie c1

backend bk_nocookie
server web1 192.168.10.10:80

Osnovno ograničavanje HTTP zahteva

HAProxy je idealan alat za dobijanje maksimuma od servera koji će biti pod povećanim opterećenjem tokom kratkog perioda. Odlični primeri takvih situacija su Black Friday promocije, praznične rasprodaje i slično.

U određenim situacijama, server se može spasiti pomoću HAProxy-ovog mehanizma za čekanje.

U ovom primeru, politika čekanja je definisana u back-end konfiguracionom odeljku. Ključne direktive su:

`minconn` – predstavlja trenutni broj konekcija ka back-end serveru u mirnim uslovima. Svi zahtevi iznad limita `minconn` će biti stavljani u red.

`fullconn` – određuje pod kojim teretom back-end serveri će dostići svoj maksimalni broj konekcija.

`maxconn` – definiše trenutni broj konekcija ka back-end serveru kada se dostigne limit `fullconn`.

backend bk_http
   fullconn 100
   server web1 192.168.10.10:80 check inter 2s minconn 20 maxconn 30
maxconn 30
   server web2 192.168.10.20:80 check inter 2s minconn 20 maxconn 30

U ovom primeru, postavili smo proizvoljne „mekane“ i „tvrđe“ limite za broj istovremenih sesija koje određeni backend serveri mogu obraditi.

Svaki server će obraditi 20 istovremenih sesija (definisano sa `minconn`). U slučaju naglog porasta zahteva, HAProxy će automatski staviti te zahteve u red. Ako broj zahteva u redu premaši limit `fullconn` (u ovom primeru 100 sesija), HAProxy će povećati konkurisanje na 30 sesija po serveru (definisano sa `maxconn`) kako bi smanjio broj zahteva u redu.

Zahtevi se stavljaju u red sve dok se ne dostigne limit vremena čekanja u redu (npr. 60 sekundi), tokom kojeg korisnici čekaju da se stranica prikaže u njihovom browseru.

Ako se dostigne limit vremena čekanja, HAProxy će vratiti grešku 504 – gateway timeout.

Upotreba HAProxy redova ima smisla samo za kratkotrajna opterećenja zahteva, jer čak i ako se povećaju limiti `minconn` ili `maxconn`, bottleneck će uvek biti brzina obrade backend servera.

Napredno ograničavanje HTTP zahteva

Ograničavanje saobraćaja, kako je opisano u prethodnom primeru, primenljivo je u određenim situacijama (pre svega ako svi zahtevi dolaze od legitimnih korisnika). Ali šta ako jedan ili više zlonamernih korisnika pošalje veliki broj zahteva serveru i uspori ga za sve druge korisnike?

Problematski korisnici mogu se sprečiti u ranoj fazi pomoću nekoliko trikova koji se oslanjaju na funkcionalnost "stick table" u HAProxy-u.

"Stick table" je HAProxy-eva in-memory key-value tabela za čuvanje različitih brojača.

Pogledajmo bliže primer konfiguracije HAProxy-ja ispod:

listen ft_http
…
   acl static_file path_end .css .js .jpg .jpeg .gif .ico .png .bmp .woff .pdf

   stick-table type ip size 100k expire 10s store http_req_rate(10s),conn_cur
   http-request track-sc0 src if !static_file

   acl fast_client sc0_gpc0_rate gt 10
   acl max_connections sc0_conn_cur gt 20

   use_backend bk_error_429 if max_connections
   use_backend bk_http_slow if fast_client

bk_error_429
   timeout tarpit 2s
   errorfile 429 /etc/haproxy/429.html

   http-request tarpit deny_status 429

Direktiva "stick-table" deklariše "stick-table" sa nekoliko argumenata:

`type ip` – deklariše ključ čiji je tip IP (ostali tipovi su integer, string, binary)

`size` – definiše broj unosa (1 unos = ~ 50B… ~ 5 MB za 100,000 unosa)

`expire` – definiše TTL (vreme trajanja) ključeva u memoriji

`store` – definiše koje vrednosti ili metrike čuvati sa ključem (u ovom slučaju broj HTTP zahteva u okviru kliznog prozora od 10 sekundi i trenutni broj otvorenih konekcija za određenu IP adresu)

Direktiva "http-request track-sc0" deklariše praćenje izvora (klijentske) IP adrese. Brojač se povećava za svaki zahtev koji dolazi sa određene IP adrese, pod uslovom da zahtev nije za statički resurs, jer smo te zahteve isključili deklarisanjem `!static_file` ACL negacije.

Direktiva "acl fast_client" proverava da li je stopa zahteva unutar kliznog prozora veća od 10, a "acl max_connections" proverava da li je broj trenutno otvorenih konekcija sa IP adrese veći od 20.

Direktiva "errorfile" u backendu nije neophodna, ali je navedena kao opcija ako želimo vratiti prilagođenu stranicu greške zloupotrebljavajućim klijentima (npr. greška 429 – too many requests).

Zaključak

Sada imate bar osnovni uvid u neke od funkcionalnosti HAProxy-ja koje vam mogu pomoći da ublažite osnovne DoS napade i držite naporne i zlonamerne botove podalje.

Da li i vi koristite HAProxy? Pišite nam u komentarima.

Tagovi:

Ostavi komentar

Vaša adresa neće biti objavljena