Blog
Kojim klijentima zapravo treba vlastiti VM? Plan slojevite Docker izolacije
VM za svakog klijenta je pretjerano. Evo kako odlučiti koliko izolacije svaki stanar treba—i automatizirati odluku.
Sažetak
Agencije često paničare kada klijent pita koliko su njihovi podaci zapravo izolirani od drugih stanara. Dockerovi namespace-ovi i cgroup-ovi pružaju stvarnu izolaciju, ali nisu isto što i hardverska granica. Umjesto da svakog klijenta pokrenete na VM-u—ili još gore, da se prema svakom klijentu ponašate jednako—napravite mali set slojeva izolacije i prilagodite svakog klijenta jednom od njih prema osjetljivosti podataka, povjerenju i usklađenosti. Zaključani kontejner (non-root, uklonjene mogućnosti, seccomp, read-only root) pokriva većinu web-lokacija; regulirani ili neprijateljski workload-ovi dobivaju VM ili hibrid kontejner-u-VM-u. Ovaj post daje ponovljiv tijek odlučivanja, usporednu tablicu i iskren pogled na to kada je veća izolacija pretjerana.
Jeste li ikada na prodajnom pozivu gdje novi klijent kaže: “mi smo u zdravstvu, pokažite mi da su naši podaci izolirani od vaših drugih klijenata”, a vi biste radije razgovarali o bilo čemu drugom?
To je problem agencije: ne jedno savršeno postavljanje, već isto pouzdano postavljanje ponovljeno na desetak klijenata s različitim proračunima, profilima rizika i zahtjevima usklađenosti. Evo iskrene verzije. Docker izolacija je stvarna, ali je specifična. Namespace-ovi daju svakom kontejneru vlastiti prikaz procesa, mreže i datotečnog sustava; cgroup-ovi ograničavaju CPU, memoriju i disk I/O tako da stanari ne mogu jedni druge izgladnjeti. Ono što vam to ne kupuje je hardverski zid između kontejnera i jezgre hosta. Ako napadač pobjegne iz kontejnera, unutar je jedine jezgre koju imate. Ostatak ovog članka pretvara tu neugodnu činjenicu u ponovljivu odluku: klasificirajte svakog klijenta prema osjetljivosti podataka i povjerenju, primijenite osnovni profil otvrdnjavanja i posegnite za VM-om samo kada je cijena proboja veća od cijene VM-a.
Čekaj, zar kontejneri već nisu izolirani?
Docker radi na Linux namespace-ovima i cgroup-ovima, i te riječi rade pravi posao. Namespace-ovi odvajaju ID-jeve procesa, mrežne stogove, mount točke i korisnike tako da proces u jednom kontejneru ne može vidjeti tablicu procesa drugog. Cgroup-ovi postavljaju ograničenja: dajte kontejneru 0.5 CPU-a, 512 MB memorije i fiksnu težinu blok I/O-a, i to je točno ono što dobije. Odbigli loop u jednom stanaru se ograničava umjesto da sruši susjeda. Ako niste konfigurirali ograničenja, preskočili ste najosnovniju stvar za koju cgroup-ovi postoje.
Uzmite jednostavnu PHP aplikaciju u kontejneru A. On vidi vlastiti datotečni sustav, vlastito mrežno sučelje, vlastiti PID 1. Kontejner B ima isto, ali drugačiji prikaz. To su namespace-ovi. Sada se udaljite i preskočite ograničenje memorije: kontejner A može napuniti RAM hosta i učiniti da kontejner B jedva radi. To je ono što cgroup-ovi postoje da spriječe. Ali dva kontejnera mogu biti izolirana jedna od drugog namespace-ovima i i dalje dijeliti jezgru hosta, što je dio o kojem govori svaka priča o bijegu iz kontejnera. Eksploit koji dosegne jezgru može potencijalno dosegnuti svakog stanara na tom hostu.
“Docker je izoliran” je napola istinita rečenica. Točna verzija glasi: “Docker izolira pomoću namespace-ova i cgroup-ova, a ranjivost jezgre je radijus eksplozije.” Prije nego što povjerite stanaru pokretanje nepouzdanog koda, zastanite na trenutak s tom mišlju. Odgovor nije “nikad ne koristite kontejnere”—to je laka panika. Odgovor je sustav slojeva.
Pa zašto neki klijenti trebaju više od namespace-ova?
Iskren odgovor je da izolacija nije prekidač, nego spektar. Na jednom kraju imate potpuno dijeljeni kontejner gdje su svi učinkovito u jednoj aplikaciji. Na drugom kraju imate odvojeni VM za svakog stanara s vlastitom jezgrom. Većina agencijskog posla živi u neugodnoj sredini, a sredina nije binarni izbor između “Docker je dovoljan” i “pokrenite VM za sve”.
Ono što gura klijenta udesno nije njihova veličina. To su četiri pitanja:
- Čuvaju li regulirane podatke? Zdravstvene kartone, podatke o platnim karticama, bilo što što bi regulator nazvao osjetljivim.
- Ima li proboj na njihovom stanaru realan put do drugog stanara? Ako mogu pokretati proizvoljni kod, da.
- Vjerujete li kodu i ljudima koji ga postavljaju? Klijent koji angažira najjeftinijeg freelancera nije ista razina povjerenja kao klijent čiji development tim poznajete.
- Kaže li njihov ugovor “dedicated”, “izolirano” ili “privatno”? Ako da, već ste obećali sloj; jedini posao sada je odabrati pravi.
Ako još ne možete odgovoriti na ta pitanja, stavite klijenta u osnovni sloj i zapišite pretpostavke. To nije sigurnosni audit; to je provjera zdravog razuma koju ponavljate pri svakom uključivanju.
Kako odlučiti po klijentu bez pokretanja sigurnosnog audita svaki put?
Napravite malu tablicu i držite je se. Ne treba vam matrica s četrdeset ćelija. Četiri sloja pokrit će gotovo svakog klijenta kojeg agencija vidi.
| Pozicija klijenta | Što ih zapravo razdvaja | Kada koristiti |
|---|---|---|
| Sloj 1: Dijeljena aplikacija/kontejner | Samo logika aplikacije | Interne uslužne aplikacije, podaci niskog rizika, projekti gdje su svi eksplicitno u jednom sustavu prijave |
| Sloj 2: Isti host, odvojeni kontejneri | Namespace-ovi i cgroup-ovi | Većina marketinških web-lokacija, kontaktni obrasci, bez osjetljivih podataka |
| Sloj 3: Zaključani kontejner | Sloj 2 + non-root, uklonjene mogućnosti, seccomp, read-only root, segmentacija mreže | E-trgovina, PII (osobni podaci), prilagođeni kod kojem ne vjerujete u potpunosti |
| Sloj 4: VM po stanaru | Hipervizor i zasebna jezgra | Zdravstvo, financije, dokumentacija o usklađenosti, nepouzdani kod, bučni susjedi |
Evo kako to izgleda u praksi. Klijent pekara s kontakt obrasecom i Instagram poveznicom ide u Sloj 2: jedan kontejner na dijeljenom hostu, zadano Docker mrežno povezivanje, ograničenja resursa, posao obavljen. Online trgovina koja pohranjuje imena kupaca, adrese i preusmjeravanja plaćanja ide u Sloj 3: isti dijeljeni host, ali kontejner radi kao non-root korisnik, nema dodatne mogućnosti jezgre, koristi seccomp profil i izlaže samo port 443. Medicinski portal za unos koji pohranjuje zaštićene zdravstvene informacije ide u Sloj 4: VM po stanaru, jer cijena proboja nije “počistit ćemo”, nego “ne možemo klijentu pokazati da smo ih shvatili ozbiljno”.
Cijeli trik je u tome što ne razmišljate ponovno o arhitekturi za svakog klijenta. Birate redak iz tablice o kojoj ste se već dogovorili. Tako agencija od pet ljudi može voditi stotinu web-lokacija bez stotinu zasebnih sigurnosnih opsesija. Također znači da sljedeći klijent ne dobije odgovor koji ovisi o tome koji je član tima podignuo slušalicu. Za dublju arhitektonsku raspravu iza tih odluka, ovaj vodič o dizajniranju razina izolacije za više stanara detaljnije obrađuje kompromise.
Kako zapravo izgleda zaključani kontejner?
Prestanimo govoriti “zaključano” i budimo konkretni. Evo što Sloj 3 znači za tipičnog WordPress ili PHP klijenta.
Prvo, promijenite korisnika. Većina službenih slika još uvijek prema zadanim postavkama radi kao root; u svom Dockerfile-u stvorite non-root korisnika i pokrenite aplikaciju kao taj korisnik. To odmah uklanja najčešći način na koji kompromitacija kontejnera postaje kompromitacija hosta. Drugo, uklonite mogućnosti koje ne trebate. Pokrenite s --cap-drop ALL i vratite samo jednu, obično NET_BIND_SERVICE, kako bi aplikacija mogla slušati na portu 80. To samo po sebi je veća promjena nego što većina ljudi očekuje. Treće, učinite root datotečni sustav samo za čitanje s --read-only i montirajte zapisljive direktorije (uploadovi, direktorij baze podataka) kao volumene ili tmpfs. Četvrto, primijenite seccomp profil i, ako vaš host to podržava, AppArmor ili SELinux. Na kraju, stavite kontejner na namjensku Docker mrežu i izložite samo one portove koji zapravo trebaju biti dostupni.
Prođimo kroz WordPress primjer. Bazna slika vjerojatno radi kao root, pa dodajete korak useradd i direktivu USER. Pokrećete kontejner s ograničenjem memorije i CPU-a, tako da nalet prometa od dodataka ne našteti susjedu. Montirate /var/www/html/wp-content/uploads kao zapisljivi volumen. Postavite --read-only. Pričvrstite ga na mrežu koja nema --privileged zastavicu nigdje u blizini. Rezultat je kontejner koji je nekada bio “WordPress web-lokacija”, a sada je “WordPress web-lokacija koja je slučajno više zaključana od većine virtualnih privatnih servera”.
Ako vam se ručno postavljanje svega toga čini krhkim, postoji lakši srednji put: Dockerova poboljšana izolacija kontejnera (Enhanced Container Isolation), koja koristi izolaciju korisničkih namespace-ova i sigurno izvođenje kontejnera. To je legitiman prečac, ali nije slobodna propusnica da preskočite non-root ili uklanjanje mogućnosti. Stanar i dalje treba razumnu sliku. Razlika je u tome što se površina napada okrenuta jezgri smanjuje bez da preko noći postanete stručnjak za seccomp. Ako želite točan slijed za jednog stanara, vodič za otvrdnjavanje izolacije korak po korak pretvara ovaj odjeljak u naredbe za kopiranje i lijepljenje.
Kada prestajem dodavati slojeve i jednostavno im dam VM?
Ovdje je kontrarni dio: veća izolacija nije automatski bolja. VM-ovi vam daju izolaciju na razini hardvera, zasebnu jezgru i mnogo manju površinu napada ako gostujuća jezgra padne. To je točno ono što klijenti iz zdravstva i financija očekuju kada kažu “želimo biti izolirani”. Ali svaki VM dodaje trošak zakrpa, sigurnosnih kopija i računanja, te umnožava posao održavanja flote ažurnom. Ako stavite svakog klijenta na VM jer vam je jedan klijent jednom rekao da ga Docker plaši, kupili ste sigurnosno kazalište za pravi novac.
VM je pravi odgovor kada je rizik po stanaru veći od operativnog troška VM-a po stanaru. To znači regulirani podaci, pisani zahtjevi usklađenosti, nepouzdani kod treće strane ili klijent kojem treba ukloniti bučnog susjeda. Također je pravi odgovor kada klijentov ugovor doslovno obećava namjensko okruženje, jer “kontejner” nije ono što zamišljaju kada potpisuju “namjensko”.
Ali VM ne opravdava aljkav kontejner. Uobičajena zamka je staviti klijenta u VM i zatim preskočiti otvrdnjavanje jer “VM ih štiti”. VM štiti host od stanara, ne stanara od njegove vlastite loše slike. I dalje želite non-root, uklonjene mogućnosti i seccomp unutar tog VM-a. Hibridni pristup—kontejneri unutar VM-a—često je najbolja točka: VM pruža granicu za razgovore o usklađenosti, a kontejner vam daje radni tijek implementacije koji već poznajete. Duža verzija te rasprave nalazi se u Trebaju li svi stanari dobiti vlastiti VM?, ali kratki odgovor je da je VM za ugovor, ne za strah.
Kako to učiniti ponovljivim za svakog klijenta?
To činite ponovljivim tako da sustav slojeva učinite predloškom, a ne sjećanjem. Držite direktorij Compose datoteka, jednu po sloju: tier2-baseline, tier3-locked, tier4-vm-hybrid. Kada se pojavi novi klijent, kopirajte predložak, promijenite varijable okruženja i već znate oblik izolacije prije nego što napišete ijedan redak nove infrastrukture.
Zatim zapišite odluku. Ne 400-stranično sigurnosno izvješće, već kratki odlomak u klijentovom repozitoriju: koje podatke pohranjuju, na kojem su sloju, zašto i što bi ih pomaknulo na viši sloj. Taj odlomak vrijedi više od stotinu pravila vatrozida, jer je to stvar koju možete pokazati sljedećem auditoru ili sljedećem zabrinutom klijentu. Također vas sprječava da morate pamtiti zašto je pekara dobila Sloj 2, a e-trgovina Sloj 3 nakon što je originalni prodajni poziv izblijedio.
Automatizirajte dosadne provjere. Neka vaš CI skenira svaku klijentovu sliku i neka build ne uspije ako se pokreće kao root, ako ima sve mogućnosti ili ako pokušava objaviti port koji nije među onima koje sloj dopušta. Ništa od toga nije egzotično; to samo osigurava da predložak slučajno ne pokvari dobro namjerni programer. Ako već gradite okolni radni tijek hostinga, članak o produkcijski spremnim Docker strategijama hostinga pokriva dio koji dolazi nakon što su kontejneri definirani.
Ništa od ovoga nije glamurozno. Nijedan post na blogu neće učiniti da “izolacija stanara” zvuči uzbudljivo kao dijagram arhitekture na zelenoj površini. Ali to je razlika između agencije koja na pitanje “koliko smo izolirani?” odgovara prekriženih prstiju “potpuno” i one koja može pokazati sloj, konfiguraciju i razlog. Kontejneri nisu čarobni zid. VM-ovi nisu čarobni metak. Sustav slojeva samo je odluka koju zapišete i ponovno koristite—a za agenciju, ponovljivost je cijela igra.

