HAProxy – švajcarski nož za administratore sistema
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 jedannocache
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 backendabk_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.