Blog

Treba li svaki stanar dobiti vlastitu VM?

Odaberite između kontejnera po stanaru, VM-ova i hibridnih postavki, uz okvir za odlučivanje temeljen na riziku i korake za jačanje sigurnosti koji svaku opciju čine opravdanom.

Sažetak

Višestanarski hosting prisiljava vas da odlučite koliko daleko stanari mogu posegnuti jedni prema drugima. Kontejneri koriste Linux imenske prostore i cgroups za izolaciju procesa i resursa, ali dijele kernel domaćina. Virtualni strojevi dodaju granicu na razini hardvera, po cijenu brzine i operativnog opterećenja. Hibridni pristup—kontejneri unutar VM-ova—može vam dati oboje, ali udvostručuje površinu koju morate zakrpiti. Ovaj članak provodi vas kroz odluku temeljenu na riziku, usporedbu jedan pored drugog i korake za jačanje sigurnosti Dockera koji su važni čak i unutar VM-a. Na kraju ćete znati koji model izolacije odgovara vašim stanarima i što konfigurirati prije pokretanja.

Vaša višestanarska aplikacija gotovo je spremna. Imate Docker Compose datoteku koja pokreće stack za svakog korisnika, i to je brzo. Onda prijatelj koji vodi hosting tvrtku pita: 'Daješ li svakom stanaru vlastiti VM?' Ukočite se. Niste planirali to pitanje. Ovaj članak daje vam način da na njega odgovorite danas, bez sigurnosnog tima. Radite to sami, pa odluka mora biti dovoljno jednostavna da je možete obraniti u 2 ujutro.

Prestanite tražiti 'najbolji' model. Počnite zapisujući što se događa ako stanarov kod preuzme vašeg domaćina. Definirajte radijus eksplozije prije nego što odaberete bilo koji alat. Ta vježba reći će vam više nego bilo koja referentna točka ikada.

Kernel je cimer kojeg ne možete izbaciti

Kontejneri su učinkoviti jer dijele kernel domaćina. To dijeljenje je cijeli trik i cijeli rizik. Linux imenski prostori daju svakom kontejneru vlastiti pogled na procese, mrežu i datotečni sustav. Kontrolne grupe (cgroups) omogućuju vam ograničavanje CPU-a, memorije i I/O diska tako da jedan stanar ne može izgladnjeti ostale. Ali nijedno od toga ne stvara hardverski zid.

Zamislite kontejner kao proces s jako dobrom lažnom iskaznicom. Vjeruje da je na vlastitom stroju. Međutim, kernel je jedna kopija Linuxa koja radi na vašem domaćinu. Ako stanar iskoristi ranjivost kernela, imenski prostori postaju samo metapodaci i ništa više. Napadač koji može pozivati kernel funkcije može doći do drugih imenskih prostora na istom kernelu. To je bijeg iz kontejnera o kojem stalno slušate.

Recimo da hostate mali B2B alat s jednim kontejnerom po klijentu. Klijent instalira sumnjiv dodatak s greškom daljinskog izvršavanja koda. Uz zadane Docker postavke, taj proces radi kao root unutar kontejnera. Root u kontejneru i dalje je UID 0, a kernel ne razlikuje taj UID od roota domaćina osim ako eksplicitno ne mapirate korisnike. Napadač može pokušati pobjeći, a zajednički kernel im je meta.

Kvar ne mora biti dramatičan. Jedan stanar koji curi memoriju može gurnuti domaćina u swap, usporavajući sve ostale stanare. Bez cgroup ograničenja, jedna petlja koja se loše ponaša je napad na dostupnost. S njima, to je blokirani proces i upozorenje.

Znači li to da su kontejneri nesigurni? Ne. To znači da se prema kernelu morate odnositi kao prema zajedničkoj zoni povjerenja. Prije nego što odaberete, napišite izjavu o riziku od jednog odlomka: 'Ako je kontejner stanara kompromitiran, napadač može pristupiti: [popis]. Poslovni trošak bio bi: [iznos ili utjecaj].' Ako vas taj odlomak plaši, niste paranoični. Iskreni ste.

Za dublji pogled na spektar izolacije, od zajedničkih kontejnera do potpuno odvojenih stackova, pogledajte naš vodič o dizajniranju višestanarske Docker arhitekture.

Tri načina da to podijelite (Odaberite jedan prije implementacije)

Stvarno postoje tri arhitekture za višestanarsku izolaciju. Svaka 'najbolja praksa' kombinacija je ovih.

PristupBarijera izolacijeNajbolje kadaNajteža zamjerka
Kontejneri po stanaruImenski prostori kernela + cgroupsMnogo malih stanara, nizak rizik po stanaru, potrebna gustoćaJedan iskorak kernela može srušiti svakog stanara na tom domaćinu
Jedan VM po stanaruHipervizor/virtualizacija na razini hardveraRegulirani podaci, neprijateljski stanari, visoka vrijednost po stanaruTeži, sporije se provisionira, zakrpate OS po stanaru
Kontejneri unutar VM-ovaVM granica oko kontejneriziranih radnih opterećenjaGustoća plus tvrda ljuska između grupaTroškovi i operativno opterećenje gotovo se udvostručuju

Kontejneri po stanaru. Ovo je zadano za većinu SaaS osnivača. Svaki stanar dobiva vlastiti kontejner ili mali Compose stack. Provizioniranje je trenutačno, slike su male, CI/CD je jednostavan. Ograničenja resursa sprječavaju bučne susjede da pojedu poslužitelj. Kompromis je zajednički kernel. Ako možete zadržati radna opterećenja neprivilegiranima i redovito zakrpiti domaćina, ovo je često pravi prvi potez.

Ne stavljajte dva stanara u isti kontejner. To je zajednički kernel plus zajedničko izvođenje (runtime) plus zajednički datotečni sustav. Ako jedan stanar učita datoteku koja stvara proces, drugi stanar je već u istoj tablici procesa. Kontejner je vaša jedinica izolacije; napravite jedan stanar po kontejneru.

Što je s bazom podataka? Ako se svaki stanar povezuje na jednu MongoDB ili PostgreSQL instancu s istim vjerodajnicama, već ste dodali ogromnu zajedničku komponentu. Dajte svakom stanaru zasebne vjerodajnice, a idealno i zasebnu bazu podataka ili shemu. Kontejneri izoliraju aplikaciju; baza podataka često je prvo curenje koje će napadač testirati.

Jedan VM po stanaru. Dajte svakom stanaru puni virtualni stroj. Hipervizor dodaje granicu na razini hardvera, što je točno ono što iskorak kernela mora prijeći da bi stigao do domaćina. Ovo je važno za regulirana okruženja ili kada su stanari nepovjerljivi. Cijena je gustoća i vrijeme. Sada upravljate flotom operativnih sustava, ne samo kontejnerima. Svaki VM treba ažuriranja, sigurnosne agente i nadzor. Za samostalnog osnivača to je stvaran posao.

Obrasci koji rade na ovoj razini: koristite infrastrukturu kao kod za stvaranje VM-a iz iste osnovne slike, upecite ažuriranja u nove slike umjesto da zakrpate žive sustave i prekinite radna opterećenja koja ne prepoznajete. Držite upravljački port VM-a zatvoren prema internetu.

Kontejneri unutar VM-ova. Ova hibridna opcija rijetko se spominje u tutorijalima za početnike. Stavite mali VM oko svakog stanara (ili male grupe stanara), a zatim pokrenete kontejnere unutar tog VM-a. VM je granica radijusa eksplozije; kontejneri su samo jedinice za implementaciju. To vam daje tvrdu granicu virtualizacije i ponovljivost slika. Košta više jer plaćate režijski trošak virtualizacije i fleksibilnost kontejnera, ali može biti najrazumniji dugoročni model kada ne možete u potpunosti vjerovati stanarima.

Jedan čest mikro primjer: stanar pokreće Node API i pozadinskog radnika. Umjesto jednog velikog kontejnera s oba procesa, upotrijebite jedan VM, zatim dva kontejnera s različitim ograničenjima resursa, zajedničkom mrežom i bez izravnog izlaganja internetu za radnika. VM pruža tvrdu granicu; kontejneri pružaju strukturu.

Koju biste trebali odabrati? Tablica je vaš uži izbor. Sljedeći odjeljci čine odluku konkretnom.

Ako odaberete kontejnere, napravite ovih šest stvari ili se ne trudite

Kontejneri po stanaru su u redu ako svaki kontejner tretirate kao potencijalnog napadača. To počinje konfiguracijom, a ne praznim željama.

0. Ograničite resurse prije nego što ikome vjerujete. Cgroups su mehanizam pravednosti i obrana dostupnosti. Postavite --memory i --cpus po kontejneru. Stanar koji curi memoriju trebao bi udariti u vlastito ograničenje, a ne u ograničenje vašeg poslužitelja. To nije sigurnosna granica, ali bučni susjed je napad bez ijedne linije koda. Praktičan početak: --memory 512m --cpus 0.5. Za radni proces krenite niže i povećavajte.

1. Pokrenite kao ne-root korisnik. Nikada ne dopustite procesu u kontejneru da koristi UID 0 osim ako to apsolutno ne trebate. Postavite korisnika u Dockerfileu i proslijedite --user kao dodatnu zaštitu. Iskorak koji radi kao neprivilegirani korisnik ima mnogo manje putova do kernela. U svom Dockerfileu stvorite korisnika: RUN useradd -u 10001 app i USER app. Ne preskačite ovo da biste uštedjeli vrijeme.

2. Odbacite svaku mogućnost koju ne trebate. Linux mogućnosti dijele rootovu moć na male dijelove. Većina web aplikacija ne treba gotovo ništa. Počnite s --cap-drop=ALL i vratite samo ono što znate da trebate. Kontejner bez CAP_SYS_ADMIN mnogo je teže iskoristiti za trikove s imenskim prostorima. Ako vaša aplikacija pokušava vezati privilegirani port, pokrenite je na visokom portu i stavite proxy ispred umjesto da odobrite NET_BIND_SERVICE.

3. Učinite datotečni sustav samo za čitanje. Vaša aplikacija ne bi trebala pisati u vlastiti sloj kontejnera. Montirajte tmpfs za stanje. Napadač koji ne može pisati na disk ima mnogo teže posaditi postojanost. Kompromitirana PHP aplikacija koja pokušava napisati webshell neće uspjeti ako je korijenski datotečni sustav samo za čitanje. Možete montirati imenovani volumen za zapisivi direktorij koji vaša aplikacija stvarno treba.

4. Primijenite seccomp i AppArmor ili SELinux. Oni blokiraju rizične sistemske pozive. Docker isporučuje zadani seccomp profil; koristite ga. Dodajte AppArmor profil za dodatni sloj. Ne morate savladati svaki sistemski poziv. Morate odbiti ono što normalni web radnik nikada ne zahtijeva. Nikada ne pokrećite s --privileged. Ta zastavica onemogućuje gotovo svaku obranu koju ste upravo postavili.

5. Segmentirajte mrežu. Ne dajte svakom kontejneru rutu do svakog drugog kontejnera. Zadano odbijanje, zatim otvorite samo portove koje trebate. Kompromitirani kontejner baze podataka ne bi trebao moći skenirati vašu administratorsku ploču. Ako su stanari u odvojenim mrežama, proboj u jednoj mreži ne može se lateralno širiti.

Praktičan početak:

docker run --user 10001 --cap-drop=ALL --security-opt no-new-privileges --read-only --tmpfs /tmp:rw,size=64M --security-opt seccomp=default.json --memory 512m --cpus 0.5 myimage

Stavite iste zastavice u Compose datoteku i primijenite ih na svakog stanara. Ovo nije potpuno, ali je daleko jača zadana postavka od one koju vam docker run daje iz kutije.

Za dublji vodič, upotrijebite naš detaljni vodič za jačanje sigurnosti Docker kontejnera u višestanarskom hostingu.

Dockerova poboljšana izolacija kontejnera iznimka je koju biste trebali znati

Ako radite unutar upravljanog Docker okruženja, potražite Dockerovu Enhanced Container Isolation (ECI). Ona koristi izolaciju korisničkih imenskih prostora i sigurno izvođenje kontejnera ispod haube. Root unutar kontejnera mapira se na neprivilegiranog korisnika na domaćinu, tako da čak ni kontejner koji radi kao root ne dobiva root privilegije domaćina. Također blokira opasne mogućnosti i sistemske pozive prema zadanim postavkama. To nije nešto što možete ponoviti s nekoliko zastavica na običnom Dockeru. Ako vaša platforma to podržava, uključite to. To ne uklanja potrebu za ne-root korisnicima i ograničenjima resursa, ali mijenja računicu rizika.

Dio toga možete približiti premapiranjem korisničkih imenskih prostora (userns-remap) u Docker daemonu. To nije tako potpuno kao sigurno izvođenje, ali je bolje nego ništa. Ako ga koristite, provjerite funkcionira li UID mapiranje prije nego što mu vjerujete.

VM zabluda: prelazak na virtualne strojeve nije jačanje sigurnosti

Ovdje je kontradiktorni dio, i to je dio koji većina ljudi preskače. Ako prijeđete na jedan VM po stanaru i zatim unutar njega implementirate svoje uobičajene kontejnere, niste uklonili problem sigurnosti kontejnera. Dodali ste široki kavez. Bijeg iz kontejnera i dalje funkcionira; napadač samo sleti u VM umjesto na domaćina. To je stvarno poboljšanje, ali i dalje trebate šest koraka.

Druga zamka je pretpostavka da je sam VM siguran. Zadana slika sa slabom SSH lozinkom, nezakrpanim osnovnim paketima ili otvorenim upravljačkim portom je dar. Granica hipervizora važna je samo ako je gostujući sustav ojačan i ažuriran. Inače, vaš 'sigurni VM' brži je put do kompromitacije jer se osjećate sigurno i prestanete provjeravati.

Ono što VM dobivate je smanjivi radijus eksplozije. Katastrofa jednog stanara ostaje u jednom VM-u. Ono što vas košta je vaše vrijeme. Postajete sistemski administrator za onoliko operacijskih sustava koliko imate stanara. Ako ste samostalni osnivač koji isporučuje proizvod, zapitajte se imate li sate za zakrpanje i nadzor flote. Ako da, VM po stanaru može biti prava odluka. Ako ne, kontejneri sa snažnim jačanjem sigurnosti mogu biti iskreniji.

Također zapamtite da je vaš domaćin hipervizora kritična meta. Kompromitirani hipervizor može vidjeti sve goste. Zakrpajte domaćina, ne samo goste. VM vas ne oslobađa zakrpanja domaćina; to povećava uloge za propuštanje.

Oprez o hibridu: nemojte pretpostaviti da kontejneri unutar VM-a daju 'dva sloja sigurnosti' besplatno. VM dodaje granicu; kontejner i dalje treba ne-root, mogućnosti i seccomp. Inače je prvi sloj samo jak koliko i najslabiji kontejner.

Četiri pitanja koja rješavaju raspravu za deset minuta

Nemojte optimizirati u apstraktu. Postavite si ova četiri pitanja redom. Zapišite odgovore.

1. Čemu moj stanar ima pristup? Ako stanar može doseći samo vlastitu web aplikaciju i bazu podataka, kontejneri po stanaru sa strogim mrežnim pravilima obranljivi su. Ako su stanarovi podaci regulirani ili financijski osjetljivi, krenite prema VM-ovima.

2. Koliko bi me koštala kompromitacija jednog stanara? Zbrojite izgubljene kupce, pravnu izloženost i povjerenje. Ako je broj veći od troška pokretanja VM-ova, potrošite novac. Ako nije, kontejneri su racionalan izbor.

3. Koliko stanara imam i koliko plaćaju? Mnogo malih pretplatnika: gustoća kontejnera je važna. Nekoliko velikih računa: dajte svakome VM i naplaćujte u skladu s tim. Stanari koji vam plaćaju manje od kave ne bi trebali svaki zahtijevati OS za upravljanje.

4. Mogu li stvari zakrpavati prema rasporedu? Kontejneri dijele jedan kernel domaćina, pa zakrpanje domaćina štiti sve. VM-ovi umnožavaju vaše ciljeve zakrpanja. Ako znate da ćete preskakati ažuriranja, odaberite arhitekturu s manje pokretnih dijelova i tvrđim zadanim postavkama.

Vaši će se odgovori grupirati. Dva ili više odgovora usmjerenih na VM znači da ne biste trebali prema zadanim postavkama koristiti kontejnere po stanaru. Tri ili više odgovora usmjerenih na kontejnere znači da su VM-ovi prerani. Jedan kontraintuitivan rezultat: stanar s niskim prihodom koji ima pristup osjetljivim podacima i dalje treba VM, jer regulatorni trošak nema veze s time koliko plaćaju.

Isporučite najmanje što možete vjerovati, zatim zaslužite više izolacije

Vaša prva arhitektura ne mora biti vaša konačna. Počnite s najčvršćom postavkom koju stvarno možete održavati, zatim dodajte izolaciju kako je vaša baza stanara opravdava. Za većinu samostalnih operatera to znači kontejnere po stanaru s ne-root korisnikom, ograničenim mogućnostima, datotečnim sustavima samo za čitanje, seccompom i segmentacijom mreže. Za regulirane ili visokovrijedne stanare, skočite izravno na jedan VM po stanaru, s kontejnerima samo kao slojem za pakiranje unutra.

Što god odabrali, zapišite odluku i preispitajte je tromjesečno. Kada dobijete prvo pitanje 'bismo li trebali premjestiti ovog stanara na VM?', imat ćete odgovor i popis za provjeru koji to podupire. To zapravo znači izolacija: kompromis kojim upravljate, a ne tehnologija koju kupujete.

Prije pokretanja, prođite kroz naš praktični popis za provjeru sigurnosti Docker izolacije—pretvara te odluke u popis koji možete provjeriti prije nego što pokažete stranicu kupcu.

Sources (5)