Cosa significa se un contenitore Linux (contenitore LXC) è chiamato "senza privilegi"?
Cosa significa se un contenitore Linux (contenitore LXC) è chiamato "senza privilegi"?
Risposte:
I contenitori LXC non privilegiati sono quelli che fanno uso degli spazi dei nomi utente ( userns ). Vale a dire una funzione del kernel che consente di mappare un intervallo di UID sull'host in uno spazio dei nomi all'interno del quale può esistere di nuovo un utente con UID 0.
Contrariamente alla mia percezione iniziale di contenitori LXC non privilegiati per un po ', ciò non significa che il contenitore debba essere di proprietà di un utente host non privilegiato. Questa è solo una possibilità.
Rilevante è:
usermod [-v|-w|--add-sub-uids|--add-sub-gids]
)lxc.id_map = ...
)Quindi anche i root
contenitori non privilegiati possono essere posseduti, poiché gli UID efficaci dei processi contenitore sull'host finiranno all'interno dell'intervallo definito dalla mappatura.
Tuttavia, per root
te devi prima definire gli ID subordinati. A differenza degli utenti creati tramite adduser
, root
non avranno un intervallo di ID subordinati definiti per impostazione predefinita.
Tieni inoltre presente che l'intera gamma che fornisci è a tua disposizione, quindi potresti avere 3 contenitori con le seguenti linee di configurazione (mostrata solo la mappatura UID):
lxc.id_map = u 0 100000 100000
lxc.id_map = u 0 200000 100000
lxc.id_map = u 0 300000 100000
supponendo che root
possieda gli UID subordinati tra 100000 e 400000. Tutta la documentazione che ho trovato suggerisce di usare 65536 ID subordinati per contenitore, alcuni usano 100000 per renderlo più leggibile dall'uomo, però.
In altre parole: non è necessario assegnare lo stesso intervallo a ciascun contenitore.
Con oltre 4 miliardi (~ 2^32
) possibili ID subordinati significa che puoi essere generoso quando gestisci gli intervalli subordinati con gli utenti host.
Per strofinarlo di nuovo. Un guest LXC non privilegiato non deve essere eseguito da un utente non privilegiato sull'host.
Configurazione del contenitore con un mapping UID / GID subordinato come questo:
lxc.id_map = u 0 100000 100000
lxc.id_map = g 0 100000 100000
dove l'utente root
dell'host possiede quel dato intervallo di ID subordinato, ti permetterà di confinare gli ospiti ancora meglio.
Tuttavia, esiste un importante vantaggio aggiuntivo in tale scenario (e sì, ho verificato che funzioni): è possibile avviare automaticamente il contenitore all'avvio del sistema.
Di solito, durante la ricerca del Web per informazioni su LXC, viene indicato che non è possibile avviare automaticamente un ospite LXC senza privilegi. Tuttavia, questo è vero solo per impostazione predefinita per quei contenitori che non si trovano nella memoria di sistema per i contenitori (di solito qualcosa del genere /var/lib/lxc
). Se lo sono (che di solito significa che sono stati creati da root e sono stati avviati da root), è una storia completamente diversa.
lxc.start.auto = 1
farà il lavoro abbastanza bene, una volta inserito nel tuo contenitore di configurazione.
Ho lottato un po 'con questo, quindi sto aggiungendo una sezione qui.
Oltre allo snippet di configurazione incluso tramite il lxc.include
quale di solito va sotto il nome /usr/share/lxc/config/$distro.common.conf
(dove si $distro
trova il nome di una distro), dovresti controllare se c'è anche un /usr/share/lxc/config/$distro.userns.conf
nel tuo sistema e includerlo anche. Per esempio:
lxc.include = /usr/share/lxc/config/ubuntu.common.conf
lxc.include = /usr/share/lxc/config/ubuntu.userns.conf
Inoltre aggiungi i mapping degli ID subordinati:
lxc.id_map = u 0 100000 65535
lxc.id_map = g 0 100000 65535
il che significa che l'host UID 100000 è root
dentro lo spazio dei nomi utente del guest LXC.
Ora assicurati che le autorizzazioni siano corrette. Se il nome del tuo ospite fosse archiviato nella variabile d'ambiente $lxcguest
, eseguiresti quanto segue:
# Directory for the container
chown root:root $(lxc-config lxc.lxcpath)/$lxcguest
chmod ug=rwX,o=rX $(lxc-config lxc.lxcpath)/$lxcguest
# Container config
chown root:root $(lxc-config lxc.lxcpath)/$lxcguest/config
chmod u=rw,go=r $(lxc-config lxc.lxcpath)/$lxcguest/config
# Container rootfs
chown 100000:100000 $(lxc-config lxc.lxcpath)/$lxcguest/rootfs
chmod u=rwX,go=rX $(lxc-config lxc.lxcpath)/$lxcguest/rootfs
Ciò dovrebbe consentire di eseguire il contenitore dopo che il primo tentativo potrebbe aver fornito alcuni errori relativi alle autorizzazioni.
chroot
questo può aiutare, ma LXC combina vari spazi dei nomi (UTS, mount ecc ...) per containerizzare l'intero sistema.
unshare
già detto, lo fa già in modo ammirevole per qualsiasi / tutti i vari spazi dei nomi - e ti offrirà anche un /proc
montaggio separato e privato con un singolo cli-switch. Se la tua singola applicazione è init
e la tua chroot
è initramfs
, otterrai un intero contenitore in pochi secondi.
Per il follow-up su 0xC0000022L, la cui soluzione ha funzionato bene per me, ho scritto uno script perl aumenta-uid-gid.pl per automatizzare le necessarie modifiche di proprietà necessarie in modo che i file all'interno dei contenitori LXC siano correttamente mappati.
Senza di essa, con questa proposta di installazione, un file all'interno del container LXC rootfs appartenente a 0 / root sull'host principale verrà, all'interno del contenitore LXC stesso, mappato a 65534 / nobody. Per essere mappati su 0 / root all'interno del contenitore LXC, devono appartenere a 100000 sull'host.
Questo è descritto qui https://yeupou.wordpress.com/2017/06/23/setting-up-lxc-containers-with-mapped-giduid/ e lo script può essere ottenuto direttamente su gitlab https://gitlab.com /yeupou/stalag13/blob/master/usr/local/bin/increase-uid-gid.pl
lxc
non è una necessità per questo tipo di cose. È possibile creare un contenitore dello spazio dei nomi di qualsiasi tipo utilizzando loutil-linux
strumentounshare
. Puoi inserire detto contenitore usando loutil-linux
strumentonsenter
. Quest'ultimo strumento consente anche di aggiungere processi in esecuzione a un contenitore già creato dall'esterno. Il supporto dello spazio dei nomi è implementato nel kernel.