Blog
Da li svaki zakupac treba da dobije sopstvenu VM?
Birajte između kontejnera po zakupcu, virtuelnih mašina i hibridnih postavki uz okvir za donošenje odluka zasnovan na riziku i korake za ojačavanje koji svaku opciju čine odbranjivom.
Sažetak
Višekorisničko hosting okruženje vas primorava da odlučite koliko duboko zakupci mogu doprijeti jedni do drugih. Kontejneri koriste Linux imenske prostore i cgroups za izolaciju procesa i resursa, ali dijele kernel domaćina. Virtuelne mašine dodaju granicu na nivou hardvera, po cijenu brzine i operativnog opterećenja. Hibridni pristup – kontejneri unutar virtuelnih mašina – može vam dati oboje, ali udvostručuje površinu koju morate zakrpati. Ovaj članak vas vodi kroz odluku zasnovanu na riziku, uporednu analizu i korake za ojačavanje Docker-a koji su važni čak i unutar virtuelne mašine. Do kraja ćete znati koji model izolacije odgovara vašim zakupcima i šta treba konfigurisati prije pokretanja.
Vaša višekorisnička aplikacija je gotovo spremna. Imate Docker Compose datoteku koja podiže stack za svakog kupca, i to brzo. Onda vas prijatelj koji vodi hosting kompaniju pita: 'Da li svakom zakupcu dajete sopstvenu VM?' Ukočite se. Niste planirali to pitanje. Ovaj članak vam daje način da na njega odgovorite danas, bez sigurnosnog tima. Radite ovo sami, pa odluka mora biti dovoljno jednostavna da se odbrani u dva sata ujutro.
Prestanite tražiti 'najbolji' model. Počnite tako što ćete zapisati šta se dešava ako kod zakupca preuzme vaš host. Definišite radijus eksplozije prije nego što odaberete bilo koji alat. Ta vježba će vam reći više nego bilo koji benchmark ikada.
Kernel je cimer kojeg ne možete izbaciti
Kontejneri su efikasni 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 sistem. Control groups (cgroups) omogućavaju vam da ograničite CPU, memoriju i disk I/O kako jedan zakupac ne bi izgladnjeo ostale. Ali nijedan od njih ne stvara hardverski zid.
Zamislite kontejner kao proces sa stvarno dobrom lažnom ličnom kartom. Vjeruje da je na vlastitoj mašini. Kernel, međutim, jeste jedna kopija Linuxa koja radi na vašem hostu. Ako zakupac iskoristi ranjivost kernela, imenski prostori postaju samo metapodaci. Napadač koji može pozivati kernel funkcije može doprijeti do drugih imenskih prostora na istom kernelu. To je ono bekstvo iz kontejnera o kojem stalno slušate.
Recimo da hostujete mali B2B alat s jednim kontejnerom po klijentu. Klijent instalira sumnjiv dodatak s greškom koja omogućava izvršavanje udaljenog koda. Uz podrazumijevane Docker postavke, taj proces radi kao root unutar kontejnera. Root u kontejneru je i dalje UID 0, i kernel ne razlikuje taj UID od root-a na hostu osim ako eksplicitno ne mapirate korisnike. Napadač može pokušati da pobjegne, a zajednički kernel je njegova meta.
Kvar ne mora biti dramatičan. Jedan zakupac koji prokišnjava memoriju može gurnuti host u swap, usporavajući sve ostale zakupce. Bez cgroup ograničenja, jedna petlja koja se loše ponaša je napad na dostupnost. S njima, to je blokiran proces i upozorenje.
Da li to znači da su kontejneri nesigurni? Ne. To znači da morate tretirati kernel kao zajedničku zonu povjerenja. Prije nego što odaberete, napišite izjavu o riziku od jednog pasusa: 'Ako je kontejner zakupca kompromitovan, napadač može pristupiti: [list]. Poslovni trošak bi bio: [amount or impact].' Ako vas taj pasus plaši, niste paranoični. Pošteni ste.
Za dublji uvid u spektar izolacije, od zajedničkih kontejnera do potpuno odvojenih stackova, pogledajte naš vodič o dizajniranju višekorisničke Docker arhitekture.
Tri načina da to podijelite (Odaberite jedan prije pokretanja)
Zaista postoje tri arhitekture za višekorisničku izolaciju. Svaka 'najbolja praksa' je kombinacija ovih.
| Pristup | Barijera izolacije | Najbolje kada | Najteži nedostatak |
|---|---|---|---|
| Kontejneri po zakupcu | Imenski prostori kernela + cgroups | Mnogo malih zakupaca, nizak rizik po zakupcu, potrebna gustina | Jedna ranjivost kernela može ugroziti svakog zakupca na tom hostu |
| Jedna VM po zakupcu | Hipervizor/virtualizacija hardvera | Regulisani podaci, neprijateljski zakupci, visoka vrijednost po zakupcu | Teže, sporije za proviziju, zakrpate OS za svakog zakupca |
| Kontejneri unutar VM-ova | VM granica oko kontejnerizovanih opterećenja | Gustina plus tvrda ljuska između grupa | Troškovi i operativni režijski troškovi gotovo se udvostručuju |
Kontejneri po zakupcu. Ovo je podrazumijevani izbor za većinu osnivača SaaS-a. Svaki zakupac dobija svoj kontejner ili mali Compose stack. Provizija je trenutna, slike su male, CI/CD je jednostavan. Ograničenja resursa sprečavaju bučne susjede da pojedu server. Kompromis je zajednički kernel. Ako radna opterećenja možete održati neprivilegovanim i redovno zakrpavati host, ovo je često pravi prvi potez.
Ne stavljajte dva zakupca u isti kontejner. To je zajednički kernel plus zajedničko okruženje za izvršavanje plus zajednički datotečni sistem. Ako jedan zakupac otpremi datoteku koja kreira proces, drugi zakupac je već u istoj tabeli procesa. Kontejner je vaša jedinica izolacije; neka bude jedan zakupac po kontejneru.
Šta je s bazom podataka? Ako se svaki zakupac povezuje na jednu MongoDB ili PostgreSQL instancu s istim vjerodajnicama, već ste dodali ogromnu zajedničku komponentu. Dajte svakom zakupcu zasebne vjerodajnice, i idealno zasebnu bazu podataka ili šemu. Kontejneri izoluju aplikaciju; baza podataka je često prvo curenje koje napadač testira.
Jedna VM po zakupcu. Dajte svakom zakupcu punu virtuelnu mašinu. Hipervizor dodaje granicu na nivou hardvera, što je tačno ono što napad na kernel mora preći da bi stigao do hosta. Ovo je važno za regulisana okruženja ili kada su zakupci nepouzdani. Cijena je gustina i vrijeme. Sada upravljate flotom operativnih sistema, ne samo kontejnerima. Svaka VM treba ažuriranja, sigurnosne agente i praćenje. Za samostalnog osnivača, to je pravi posao.
Obrasci koji funkcionišu na ovom nivou: koristite infrastrukturu kao kod za kreiranje VM-a iz iste osnovne slike, ugrađujte ažuriranja u nove slike umjesto zakrpanja sistema uživo i prekinite radna opterećenja koja ne prepoznajete. Držite upravljački port VM-a zatvorenim za internet.
Kontejneri unutar VM-ova. Ova hibridna varijanta rijetko se spominje u tutorijalima za početnike. Stavite malu VM oko svakog zakupca (ili male grupe zakupaca), a zatim pokrenete kontejnere unutar te VM. VM je kontejner radijusa eksplozije; kontejneri su samo jedinice za implementaciju. Ovo vam daje tvrdu ivicu virtualizacije i ponovljivost slika. Košta više, jer plaćate režijske troškove virtualizacije i fleksibilnost kontejnera, ali može biti najrazumniji dugoročni model kada ne možete u potpunosti vjerovati zakupcima.
Jedan uobičajeni mikroprimjer: zakupac pokreće Node API i pozadinskog radnika. Umjesto jednog ogromnog kontejnera s oba procesa, koristite jednu VM, zatim dva kontejnera s različitim ograničenjima resursa, zajedničkom mrežom i bez direktnog izlaganja internetu za radnika. VM pruža tvrdu ivicu; kontejneri pružaju strukturu.
Koji biste trebali odabrati? Tabela je vaša uža lista. Sljedeći odjeljci čine odluku konkretnom.
Ako odaberete kontejnere, uradite ovih šest stvari ili nemojte ni pokušavati
Kontejneri po zakupcu su u redu ako svaki kontejner tretirate kao potencijalnog napadača. To počinje konfiguracijom, a ne željnim razmišljanjem.
0. Ograničite resurse prije nego što nekome povjerujete. Cgroups su mehanizam pravednosti i odbrana za dostupnost. Postavite --memory i --cpus za svaki kontejner. Zakupac koji prokišnjava memoriju treba da udari u vlastito ograničenje, a ne u ograničenje vašeg servera. To nije sigurnosna granica, ali bučni susjed je napad bez ijednog retka koda. Praktičan početak: --memory 512m --cpus 0.5. Za radni proces, krenite niže i povećavajte.
1. Pokrenite kao korisnik koji nije root. Nikada ne dozvolite procesu u kontejneru da koristi UID 0 osim ako vam apsolutno treba. Postavite korisnika u Dockerfile-u i proslijedite --user kao dodatnu zaštitu. Iskorištavanje ranjivosti koje radi kao neprivilegovani korisnik ima mnogo manje puteva do kernela. U svom Dockerfile-u kreirajte korisnika: RUN useradd -u 10001 app i USER app. Nemojte ovo preskočiti da biste uštedjeli vrijeme.
2. Odbacite sve mogućnosti koje vam ne trebaju. Linux mogućnosti (capabilities) dijele root ovlasti na male dijelove. Većina web aplikacija ne treba gotovo nijednu. 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 privilegovani port, pokrenite je na visokom portu i stavite proxy ispred umjesto da dodijelite NET_BIND_SERVICE.
3. Učinite datotečni sistem 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 vrijeme u postavljanju perzistencije. Kompromitovana PHP aplikacija koja pokušava zapisati webshell neće uspjeti kada je root datotečni sistem samo za čitanje. Možete montirati imenovani volumen za direktorij koji vaša aplikacija zaista treba za pisanje.
4. Primijenite seccomp i AppArmor ili SELinux. Ovi šalju rizične sistemske pozive na gomilu za odbacivanje. Docker isporučuje podrazumijevani seccomp profil; koristite ga. Dodajte AppArmor profil za još jedan sloj. Ne morate savladati svaki sistemski poziv. Trebate uskratiti ono što normalni web radnik nikada ne zahtijeva. Nikada ne pokrećite s --privileged. Ta zastavica onemogućava gotovo svaku odbranu koju ste upravo postavili.
5. Segmentirajte mrežu. Ne dajte svakom kontejneru rutu do svakog drugog kontejnera. Podrazumijevano odbijanje, a zatim otvorite samo portove koje trebate. Kompromitovani kontejner baze podataka ne bi trebao moći skenirati vašu administratorsku ploču. Ako su zakupci 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 zakupca. Ovo nije potpuno, ali je daleko jača podrazumijevana postavka od one koju docker run daje iz kutije.
Za detaljniji vodič, koristite naš korak-po-korak vodič za ojačavanje Docker kontejnera u višekorisničkom hostingu.
Dockerova poboljšana izolacija kontejnera je izuzetak koji trebate znati
Ako radite unutar upravljanog Docker okruženja, potražite Dockerovu poboljšanu izolaciju kontejnera (ECI). Ona koristi izolaciju korisničkog imenskog prostora i sigurno okruženje za izvršavanje kontejnera ispod haube. Root unutar kontejnera preslikava se na neprivilegovanog korisnika na hostu, tako da čak i kontejner koji radi kao root ne dobija root privilegije hosta. Također blokira opasne mogućnosti i sistemske pozive po podrazumijevanoj postavci. To nije nešto što možete rekreirati s nekoliko zastavica na običnom Dockeru. Ako vaša platforma to podržava, uključite je. To ne uklanja potrebu za korisnicima koji nisu root i ograničenjima resursa, ali mijenja matematiku rizika.
Dio ovoga možete približiti preslikavanjem korisničkog imenskog prostora (userns-remap) u Docker demonu. To nije tako potpuno kao sigurno okruženje, ali je bolje nego ništa. Ako ga koristite, provjerite da UID preslikavanje radi prije nego što mu vjerujete.
VM zabluda: prelazak na virtuelne mašine nije ojačavanje
Evo kontroverznog dijela, i to je dio koji većina ljudi preskače. Ako pređete na jednu VM po zakupcu i zatim unutar nje rasporedite svoje uobičajene kontejnere, niste uklonili svoj sigurnosni problem s kontejnerima. Dodali ste širok kavez. Bekstvo iz kontejnera i dalje funkcioniše; napadač jednostavno sleti u VM umjesto na host. To je stvarno poboljšanje, ali i dalje trebate šest koraka.
Druga zamka je pretpostavka da je sama VM sigurna. Podrazumijevana slika sa slabom SSH lozinkom, nezapakiranim osnovnim paketima ili otvorenim upravljačkim portom je poklon. Granica hipervizora je važna samo ako je gostujući sistem ojačan i ažuriran. Inače, vaša 'sigurna VM' je brži put do kompromitacije jer se osjećate sigurno i prestanete provjeravati.
Ono što vam VM donosi jeste svodljiv radijus eksplozije. Katastrofa jednog zakupca ostaje u jednoj VM. Ono što vas košta jeste vaše vrijeme. Postajete sistemski administrator za onoliko operativnih sistema koliko imate zakupaca. Ako ste samostalni osnivač koji isporučuje proizvod, zapitajte se imate li sate za zakrpanje i praćenje flote. Ako da, VM po zakupcu može biti prava odluka. Ako ne, kontejneri sa snažnim ojačavanjem mogu biti iskreniji.
Također zapamtite da je vaš host hipervizora kritična meta. Kompromitovani hipervizor može vidjeti sve goste. Zakrpajte host, ne samo goste. VM vas ne oslobađa zakrpanja hosta; povećava uloge ako to propustite.
Napomena o hibridu: nemojte pretpostaviti da kontejneri unutar VM-a automatski daju 'dva sloja sigurnosti'. VM dodaje granicu; kontejner i dalje treba non-root, mogućnosti i seccomp. Inače je prvi sloj samo koliko i najslabiji kontejner.
Četiri pitanja koja rješavaju debatu za deset minuta
Ne optimizirajte u apstraktu. Postavite sebi ova četiri pitanja redom. Zapišite odgovore.
1. Čemu moj zakupac ima pristup? Ako zakupac može doseći samo vlastitu web aplikaciju i bazu podataka, kontejneri po zakupcu sa strogim mrežnim pravilima su odbranjivi. Ako su podaci zakupca regulisani ili finansijski osjetljivi, krenite prema VM-ovima.
2. Koliko bi me koštala kompromitacija jednog zakupca? 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 zakupaca imam i koliko oni plaćaju? Mnogo malih pretplatnika: gustina kontejnera je važna. Nekoliko velikih računa: dajte svakome VM i naplatite u skladu s tim. Zakupci koji vam plaćaju manje od kafe ne bi trebali svaki zahtijevati OS za upravljanje.
4. Mogu li zakrpavati stvari po rasporedu? Kontejneri dijele jedan kernel hosta, pa zakrpanje hosta štiti sve. VM-ovi umnožavaju vaše ciljeve zakrpanja. Ako znate da ćete preskakati ažuriranja, odaberite arhitekturu s manje pokretnih dijelova i težim podrazumijevanim postavkama.
Vaši odgovori će se grupirati. Dva ili više odgovora usmjerenih na VM znače da ne biste trebali podrazumijevano koristiti kontejnere po zakupcu. Tri ili više odgovora usmjerenih na kontejnere znače da su VM-ovi preuranjeni. Jedan kontraintuitivan rezultat: zakupac s niskim prihodom i pristupom osjetljivim podacima i dalje treba VM, jer regulatorni trošak nema veze s tim koliko plaća.
Isporučite najmanje što možete vjerovati, a zatim zaradite više izolacije
Vaša prva arhitektura ne mora biti vaša konačna. Počnite s najčvršćom postavkom koju zaista možete održavati, a zatim dodajte izolaciju kako je vaša baza zakupaca opravdava. Za većinu samostalnih operatera to znači kontejnere po zakupcu s non-root korisnikom, ograničenim mogućnostima, datotečnim sistemima samo za čitanje, seccomp-om i mrežnom segmentacijom. Za regulisane ili visokovrijedne zakupce, odmah pređite na jednu VM po zakupcu, s kontejnerima samo kao slojem za pakiranje unutra.
Šta god odabrali, zapišite odluku i preispitajte je kvartalno. Kada dobijete prvo pitanje 'trebamo li premjestiti ovog zakupca na VM?', imat ćete odgovor i listu za provjeru koja to potkrepljuje. To zapravo znači izolacija: kompromis kojim upravljate, a ne tehnologija koju kupujete.
Prije objave, prođite kroz naš praktični sigurnosni popis za Docker izolaciju – on ove odluke pretvara u listu koju možete provjeriti prije nego što prikažete stranicu kupcu.

