Was bedeutet es, wenn ein Linux-Container (LXC-Container) "unprivilegiert" heißt?
Was bedeutet es, wenn ein Linux-Container (LXC-Container) "unprivilegiert" heißt?
Antworten:
Unprivilegierte LXC-Container verwenden Benutzernamensräume ( userns ). Dh einer Kernel - Funktion , die eine Reihe von UIDs auf dem Host in einen Namensraum kartieren ermöglicht innerhalb von denen ein Benutzer mit UID 0 wieder vorhanden sein.
Im Gegensatz zu meiner anfänglichen Wahrnehmung von nichtprivilegierten LXC-Containern für eine Weile bedeutet dies nicht, dass der Container einem nichtprivilegierten Hostbenutzer gehören muss. Das ist nur eine Möglichkeit.
Relevant ist:
usermod [-v|-w|--add-sub-uids|--add-sub-gids]
)lxc.id_map = ...
)So root
können auch nichtprivilegierte Container Eigentümer sein, da die effektiven UIDs der Containerprozesse auf dem Host innerhalb des durch das Mapping definierten Bereichs landen.
Dazu müssen root
Sie jedoch zuerst die untergeordneten IDs definieren. Im Gegensatz zu Benutzern, die über erstellt wurden adduser
, root
wird standardmäßig kein Bereich von untergeordneten IDs definiert.
Denken Sie auch daran, dass Ihnen der gesamte Bereich zur Verfügung steht, sodass Sie 3 Container mit den folgenden Konfigurationszeilen haben können (nur UID-Zuordnung wird angezeigt):
lxc.id_map = u 0 100000 100000
lxc.id_map = u 0 200000 100000
lxc.id_map = u 0 300000 100000
Angenommen, root
die untergeordneten UIDs liegen zwischen 100000 und 400000. Alle Dokumente, die ich gefunden habe, schlagen vor, 65536 untergeordnete IDs pro Container zu verwenden. Einige verwenden jedoch 100000, um die Lesbarkeit zu verbessern.
Mit anderen Worten: Sie müssen nicht jedem Container den gleichen Bereich zuweisen.
Mit über 4 Milliarden (~ 2^32
) möglichen untergeordneten IDs können Sie die untergeordneten Bereiche großzügig an Ihre Hostbenutzer weitergeben.
Um das noch einmal einzureiben. Ein nicht privilegierter LXC-Gast muss nicht von einem nicht privilegierten Benutzer auf dem Host ausgeführt werden.
Konfigurieren Sie Ihren Container mit einer untergeordneten UID / GID-Zuordnung wie folgt:
lxc.id_map = u 0 100000 100000
lxc.id_map = g 0 100000 100000
Wenn der Benutzer root
auf dem Host diesen untergeordneten ID-Bereich besitzt, können Sie die Gäste noch besser einschränken.
Es gibt jedoch einen wichtigen zusätzlichen Vorteil in einem solchen Szenario (und ja, ich habe überprüft, dass es funktioniert): Sie können Ihren Container beim Systemstart automatisch starten.
Wenn Sie im Internet nach Informationen zu LXC suchen, werden Sie normalerweise darauf hingewiesen, dass es nicht möglich ist, einen nicht privilegierten LXC-Gast automatisch zu starten. Dies gilt jedoch standardmäßig nur für solche Container, die sich nicht im systemweiten Speicher für Container befinden (in der Regel so etwas wie /var/lib/lxc
). Wenn dies der Fall ist (was normalerweise bedeutet, dass sie von root erstellt und von root gestartet wurden), ist dies eine ganz andere Geschichte.
lxc.start.auto = 1
wird den Job ganz nett machen, sobald du ihn in deine Containerkonfiguration gesetzt hast.
Ich habe selbst ein bisschen damit zu kämpfen, also füge ich hier einen Abschnitt hinzu.
Zusätzlich zu dem Konfigurations-Snippet, über lxc.include
das normalerweise der Name /usr/share/lxc/config/$distro.common.conf
(wo $distro
ist der Name einer Distribution) angegeben wird, sollten Sie prüfen, ob sich /usr/share/lxc/config/$distro.userns.conf
auf Ihrem System auch ein befindet , und dies auch einschließen. Z.B:
lxc.include = /usr/share/lxc/config/ubuntu.common.conf
lxc.include = /usr/share/lxc/config/ubuntu.userns.conf
Fügen Sie außerdem die untergeordneten ID-Zuordnungen hinzu:
lxc.id_map = u 0 100000 65535
lxc.id_map = g 0 100000 65535
Dies bedeutet, dass sich die Host-UID 100000 root
im Benutzernamensraum des LXC-Gasts befindet.
Stellen Sie nun sicher, dass die Berechtigungen korrekt sind. Wenn der Name Ihres Gastes in der Umgebungsvariablen gespeichert wäre, würden $lxcguest
Sie Folgendes ausführen:
# 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
Auf diese Weise können Sie den Container ausführen, nachdem bei Ihrem ersten Versuch möglicherweise einige berechtigungsbezogene Fehler aufgetreten sind.
chroot
dieser zu kombinieren, kann helfen, aber LXC kombiniert verschiedene der Namensräume (UTS, Mount usw.), um das gesamte System zu containerisieren.
unshare
funktioniert dies bewundernswert für jeden / alle der verschiedenen Namespaces - und Sie erhalten sogar ein separates, privates /proc
Mount mit einem einzigen CLI-Switch. Wenn Ihre einzige Anwendung ist init
und Sie chroot
ist initramfs
dann erhalten Sie einen ganzen Container in Sekunden flach.
Um followup auf 0xC0000022L, deren Lösung funktionierte gut für mich, habe ich einen increase-uid-gid.pl Perl - Skript der notwendige Besitz zu automatisieren Änderungen erforderlich , um Dateien innerhalb des LXC Behälters richtig abgebildet.
Ohne diese Option wird bei dieser vorgeschlagenen Konfiguration eine Datei in LXC-Container-Rootfs, die zu 0 / root auf dem Haupthost gehört, im LXC-Container selbst 65534 / nobody zugeordnet. Um im LXC-Container auf 0 / root abgebildet zu werden, müssen sie zu 100000 auf dem Host gehören.
Dies ist hier beschrieben https://yeupou.wordpress.com/2017/06/23/setting-up-lxc-containers-with-mapped-giduid/ und das Skript kann direkt von gitlab https://gitlab.com bezogen werden /yeupou/stalag13/blob/master/usr/local/bin/increase-uid-gid.pl
lxc
keine Notwendigkeit für so etwas. Mit demutil-linux
Tool können Sie einen Namespace-Container beliebiger Art erstellenunshare
. Sie können diesen Container mit demutil-linux
Tool eingebennsenter
. Mit dem letzteren Tool können Sie auch laufende Prozesse zu einem bereits erstellten Container hinzufügen, ohne diesen zu verwenden. Die Namespace-Unterstützung wird im Kernel implementiert.