Blogg

Bør hver leietaker få sin egen VM?

Velg mellom containere per leietaker, VM-er og hybride oppsett med et risikobasert beslutningsrammeverk og herdingstrinnene som gjør hvert alternativ forsvarlig.

Sammendrag

Flerleietaker-hosting tvinger deg til å velge hvor langt leietakere kan nå inn i hverandre. Containere bruker Linux-navnerom og cgroups for å isolere prosesser og ressurser, men de deler vertskjernen. Virtuelle maskiner legger til en grense på maskinvarenivå, på bekostning av hastighet og driftsbelastning. En hybrid tilnærming – containere i VM-er – kan gi deg begge deler, men den dobler overflaten du må patche. Denne artikkelen går gjennom en risikobasert beslutning, en sammenligning side om side, og Docker-herdingstrinnene som betyr noe selv inne i en VM. Når du er ferdig, vet du hvilken isolasjonsmodell som passer dine leietakere og hva du skal konfigurere før lansering.

Flerleietaker-appen din er nesten klar. Du har en Docker Compose-fil som starter en stack per kunde, og det er raskt. Så spør en venn som driver et hosting-selskap: «Gir du hver leietaker sin egen VM?» Du fryser. Du hadde ikke planlagt for det spørsmålet. Denne artikkelen gir deg en måte å svare på det i dag, uten et sikkerhetsteam. Du gjør dette alene, så beslutningen må være enkel nok til å forsvare klokken 2 om natten.

Slutt å lete etter den «beste» modellen. Start med å skrive ned hva som skjer hvis en leietakers kode tar over verten din. Definer eksplosjonsradiusen før du velger noe verktøy. Den øvelsen vil fortelle deg mer enn noen benchmark noensinne vil.

Kjernen er samboeren du ikke kan kaste ut

Containere er effektive fordi de deler vertskjernen. Den delingen er hele trikset, og hele risikoen. Linux-navnerom gir hver container sin egen visning av prosesser, nettverk og filsystem. Kontrollgrupper (cgroups) lar deg begrense CPU, minne og disk-I/O, slik at én leietaker ikke kan sulte ut de andre. Men ingen av dem skaper en maskinvarevegg.

Tenk på en container som en prosess med et veldig godt falskt ID-kort. Den tror den er på sin egen maskin. Kjernen er imidlertid én kopi av Linux som kjører på verten din. Hvis en leietaker utnytter en sårbarhet i kjernen, blir navnerom bare metadata og ikke noe mer. En angriper som kan kalle kjernefunksjoner, kan nå andre navnerom på samme kjerne. Det er container-utbruddet du stadig hører om.

La oss si at du hoster et lite B2B-verktøy med én container per kunde. En kunde installerer en tvilsom plugin med en feil som tillater ekstern kjøring av kode. Med standard Docker-innstillinger kjører den prosessen som root inne i containeren. Root i en container er fortsatt UID 0, og kjernen skiller ikke den UID-en fra vertens root med mindre du eksplisitt kartlegger brukere. Angriperen kan prøve å bryte seg ut, og den delte kjernen er målet.

Feilen trenger ikke være dramatisk. Én enkelt leietaker som lekker minne, kan presse verten til å bruke swap, noe som gjør alle andre leietakere tregere. Uten cgroup-grenser er én løkke som oppfører seg dårlig et angrep på tilgjengeligheten. Med dem er det en blokkert prosess og en alarm.

Betyr dette at containere er usikre? Nei. Det betyr at du må behandle kjernen som en felles tillitssone. Før du velger, skriv en risikouttalelse på ett avsnitt: «Hvis en leietakers container blir kompromittert, kan angriperen få tilgang til: [liste]. Forretningskostnaden vil være: [beløp eller konsekvens].» Hvis det avsnittet skremmer deg, er du ikke paranoid. Du er ærlig.

For en dypere titt på isolasjonsspekteret, fra delte containere til fullstendig separate stakker, se vår guide om å designe en flerleietaker Docker-arkitektur.

Tre måter å dele det på (velg én før du distribuerer)

Det finnes egentlig tre arkitekturer for flerleietaker-isolasjon. Enhver «beste praksis» er en kombinasjon av disse.

TilnærmingIsolasjonsbarriereBest nårVanskeligste forbehold
Containere per leietakerKjerne-navnerom + cgroupsMange små leietakere, lav risiko per leietaker, behov for tetthetEtt kjerne-utbrudd kan knekke alle leietakere på den verten
Én VM per leietakerHypervisor/maskinvarevirtualiseringRegulerte data, fiendtlige leietakere, høy verdi per leietakerTyngre, tregere å klargjøre, du patcher ett OS per leietaker
Containere i VM-erVM-grense rundt containeriserte arbeidsbelastningerTetthet pluss et hardt skall mellom grupperKostnader og driftsmessig overhead nesten dobles

Containere per leietaker. Dette er standarden for de fleste SaaS-gründere. Hver leietaker får sin egen container eller lille Compose-stack. Klargjøring er øyeblikkelig, bilder er små, CI/CD er enkelt. Ressursgrenser hindrer støyende naboer fra å spise opp serveren. Avveiningen er den delte kjernen. Hvis du kan holde arbeidsbelastninger uten privilegier og patche verten jevnlig, er dette ofte det rette første trekket.

Ikke legg to leietakere i samme container. Det er en delt kjerne pluss en delt kjøretid pluss et delt filsystem. Hvis én leietaker laster opp en fil som oppretter en prosess, er den andre leietakeren allerede i samme prosess-tabell. En container er din isolasjonsenhet; gjør den til én leietaker per container.

Hva med databasen? Hvis hver leietaker kobler til én MongoDB- eller PostgreSQL-instans med de samme legitimasjonene, har du allerede lagt til en enorm felles komponent. Gi hver leietaker separate legitimasjoner, og ideelt sett en separat database eller et separat skjema. Containere isolerer appen; databasen er ofte den første lekkasjen en angriper vil teste.

Én VM per leietaker. Gi hver leietaker en full virtuell maskin. Hypervisoren legger til en grense på maskinvarenivå, som er akkurat det et kjerne-utbrudd må krysse for å nå verten. Dette betyr noe for regulerte miljøer eller når leietakere er upålitelige. Kostnaden er tetthet og tid. Du administrerer nå en flåte av operativsystemer, ikke bare containere. Hver VM trenger oppdateringer, sikkerhetsagenter og overvåking. For en solo-gründer er det reelt arbeid.

Mønstre som fungerer på dette nivået: bruk infrastruktur-som-kode for å opprette en VM fra det samme basisbildet, bygg inn oppdateringer i nye bilder i stedet for å patche levende systemer, og avslutt arbeidsbelastninger du ikke kjenner igjen. Hold VM-ens administrasjonsport lukket mot internett.

Containere i VM-er. Denne hybriden blir sjelden diskutert i nybegynnerveiledninger. Du legger en liten VM rundt hver leietaker (eller liten gruppe av leietakere), og kjører deretter containere inne i den VM-en. VM-en er en eksplosjonsradius-beholder; containerne er bare distribuerbare enheter. Dette gir deg den harde kanten av virtualisering og reproduserbarheten til bilder. Det koster mer, fordi du betaler for virtualiserings-overhead og containerfleksibilitet, men det kan være den fornuftigste langsiktige modellen når du ikke fullt ut kan stole på leietakere.

Et vanlig mikro-eksempel: en leietaker kjører et Node-API og en bakgrunnsarbeider. I stedet for én stor container med begge prosessene, bruk én VM, deretter to containere med forskjellige ressursgrenser, et delt nettverk, og ingen direkte internetteksponering for arbeideren. VM-en gir den harde kanten; containerne gir struktur.

Hvilken bør du velge? Tabellen er din kortliste. De neste delene gjør beslutningen konkret.

Hvis du velger containere, gjør disse seks tingene – eller la være

Containere per leietaker er greit hvis du behandler hver container som en potensiell angriper. Det starter med konfigurasjon, ikke ønsketenkning.

0. Begrens ressurser før du stoler på noen. Cgroups er en rettferdighetsmekanisme og et forsvar mot tilgjengelighetsangrep. Sett --memory og --cpus per container. En leietaker som lekker minne, bør treffe sin egen grense, ikke serverens. Dette er ikke en sikkerhetsgrense, men en støyende nabo er et angrep uten en eneste linje kode. En praktisk start: --memory 512m --cpus 0.5. For en arbeiderprosess, start lavere og skaler opp.

1. Kjør som en ikke-root-bruker. La aldri containerprosessen bruke UID 0 med mindre du absolutt trenger det. Sett en bruker i Dockerfile og send --user som en ekstra beskyttelse. Et utbrudd som kjører som en uprivilegert bruker, har langt færre veier til kjernen. I Dockerfilen din oppretter du en bruker: RUN useradd -u 10001 app og USER app. Ikke hopp over dette for å spare tid.

2. Slipp alle capabilities du ikke trenger. Linux-capabilities deler roottens makt i små biter. De fleste nettapper trenger nesten ingen. Start med --cap-drop=ALL og legg tilbake bare det du vet du trenger. En container uten CAP_SYS_ADMIN er mye vanskeligere å bruke til navnerom-triks. Hvis appen din prøver å binde en privilegert port, kjør den på en høy port og sett en proxy foran i stedet for å gi NET_BIND_SERVICE.

3. Gjør filsystemet skrivebeskyttet. Appen din bør ikke skrive til sitt eget containerlag. Monter en tmpfs for tilstand. En angriper som ikke kan skrive til disk, har mye vanskeligere for å etablere vedvarende tilgang. En kompromittert PHP-app som prøver å skrive en webshell, vil mislykkes når rotfilsystemet er skrivebeskyttet. Du kan montere en navngitt volum for en skrivbar katalog som appen din virkelig trenger.

4. Bruk seccomp og AppArmor eller SELinux. Disse sender risikable syscalls til søppelhaugen. Docker leverer en standard seccomp-profil; bruk den. Legg til en AppArmor-profil for et ekstra lag. Du trenger ikke å mestre alle syscalls. Du må nekte det en vanlig webworker aldri krever. Kjør aldri med --privileged. Det flagget deaktiverer nesten alle forsvar du nettopp satte opp.

5. Segmenter nettverket. Ikke gi hver container en rute til alle andre containere. Nekt som standard, og åpne bare portene du trenger. En kompromittert databasecontainer skal ikke kunne skanne administrasjonspanelet ditt. Hvis leietakere er i separate nettverk, kan et brudd i ett nettverk ikke spre seg sideveis.

En praktisk start:

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

Legg de samme flaggene i en Compose-fil og bruk dem på hver leietaker. Dette er ikke komplett, men det er en langt sterkere standard enn det docker run gir deg ut av boksen.

For en mer detaljert gjennomgang, bruk vår steg-for-steg-herdingsguide for Docker-containere i flerleietaker-hosting.

Docker sin Enhanced Container Isolation er unntaket du bør kjenne til

Hvis du kjører i et administrert Docker-miljø, se etter Docker sin Enhanced Container Isolation (ECI). Den bruker bruker-navnerom-isolasjon og en sikker container-kjøretid under panseret. Root inne i en container kartlegges til en uprivilegert bruker på verten, så selv en container som kjører som root, får ikke vertens root-rettigheter. Den blokkerer også farlige capabilities og syscalls som standard. Dette er ikke noe du kan gjenskape med noen få flagg på vanlig Docker. Hvis plattformen din støtter det, skru den på. Den fjerner ikke behovet for ikke-root-brukere og ressursgrenser, men den endrer risikomatematikken.

Du kan tilnærme deg deler av dette med bruker-navnerom-tilordning (userns-remap) i Docker-demonen. Det er ikke like komplett som en sikker kjøretid, men det er bedre enn ingenting. Hvis du bruker det, kontroller at UID-tilordningen fungerer før du stoler på den.

VM-feilslutningen: Å flytte til virtuelle maskiner er ikke herding

Her kommer den kontrære delen, og den delen de fleste hopper over. Hvis du flytter til én VM per leietaker og deretter distribuerer de vanlige containerne dine inne i den, har du ikke fjernet container-sikkerhetsproblemet ditt. Du har lagt til et vidt bur. Container-utbruddet fungerer fortsatt; angriperen lander bare i VM-en i stedet for på verten. Det er en reell forbedring, men du trenger fortsatt de seks trinnene.

Den andre fellen er å anta at VM-en i seg selv er trygg. Et standardbilde med et svakt SSH-passord, upatchede basispakker eller en åpen administrasjonsport er en gave til angripere. Hypervisorgrensen betyr bare noe hvis gjesten er herdet og oppdatert. Ellers er din «sikre VM» en raskere vei til kompromittering, fordi du føler deg trygg og slutter å sjekke.

Det en VM gir deg, er en reduserbar eksplosjonsradius. Én leietakers katastrofe blir i én VM. Det det koster deg, er tiden din. Du blir systemadministrator for like mange operativsystemer som du har leietakere. Hvis du er en solo-gründer som lanserer et produkt, spør om du har timene til å patche og overvåke en flåte. Hvis ja, kan én VM per leietaker være det rette valget. Hvis nei, kan containere med sterk herding være mer ærlig.

Husk også at hypervisor-verten din er et kritisk mål. En kompromittert hypervisor kan se alle gjester. Patche verten, ikke bare gjestene. VM-en fritar deg ikke fra å patche verten; den øker innsatsen for å gå glipp av det.

Et forbehold om hybriden: ikke anta at containere i en VM gir deg «to sikkerhetslag» gratis. VM-en legger til en grense; containerne trenger fortsatt ikke-root, capabilities og seccomp. Ellers er det første laget bare like sterkt som den svakeste containeren.

Fire spørsmål som avgjør debatten på ti minutter

Ikke optimaliser i det abstrakte. Still deg selv disse fire spørsmålene i rekkefølge. Skriv ned svarene.

1. Hva har leietakeren min tilgang til? Hvis en leietaker bare kan nå sin egen nettapp og database, er containere per leietaker med strenge nettverksregler forsvarlige. Hvis en leietakers data er regulert eller økonomisk sensitiv, bør du bevege deg mot VM-er.

2. Hvor mye vil én leietakers kompromittering koste meg? Legg sammen tapte kunder, juridisk eksponering og tillit. Hvis tallet er større enn kostnaden ved å kjøre VM-er, bruk pengene. Hvis ikke, er containere et rasjonelt valg.

3. Hvor mange leietakere har jeg, og hvor mye betaler de? Mange små abonnenter: container-tetthet betyr noe. En håndfull store kontoer: gi hver en VM og fakturer deretter. Leietakere som betaler deg mindre enn en kaffe, bør ikke hver kreve et OS å administrere.

4. Kan jeg patche ting etter en plan? Containere deler én vertskjerne, så å patche verten beskytter alle. VM-er multipliserer patchemålene dine. Hvis du vet at du vil hoppe over oppdateringer, velg arkitekturen med færre bevegelige deler og hardere standardinnstillinger.

Svarene dine vil samle seg i grupper. To eller flere VM-fokuserte svar betyr at du ikke bør bruke containere per leietaker som standard. Tre eller flere container-fokuserte svar betyr at VM-er er for tidlig. Ett kontraintuitivt resultat: en leietaker med lav inntekt som har tilgang til sensitive data, trenger fortsatt VM-en, fordi den regulatoriske kostnaden ikke har noe med hvor mye de betaler å gjøre.

Lever det minste du kan stole på, og oppnå mer isolasjon

Den første arkitekturen din trenger ikke å være den endelige. Start med det strammeste oppsettet du faktisk kan vedlikeholde, og legg deretter til isolasjon når leietakerbasen din rettferdiggjør det. For de fleste solo-operatører betyr det containere per leietaker med ikke-root, begrensede capabilities, skrivebeskyttede filsystemer, seccomp og nettverkssegmentering. For regulerte eller høyverdige leietakere, hopp rett til én VM per leietaker, med containere bare som et pakkelag inni.

Uansett hva du velger, skriv ned beslutningen og gå gjennom den kvartalsvis. Når du får ditt første spørsmål om «bør vi flytte denne leietakeren til en VM?», vil du ha et svar, og du vil ha sjekklisten som støtter det. Det er det isolasjon faktisk betyr: en avveining du håndterer, ikke en teknologi du kjøper.

Før lansering, gå gjennom vår praktiske Docker-isolasjonssjekkliste – den gjør disse beslutningene om til en liste du kan verifisere før du viser en side til en kunde.

Sources (5)