Die API von Docker ist standardmäßig vollständig ungeschützt, mit Ausnahme von Dateisystemberechtigungen auf seinem Unix-Socket. Sie sollten TLS einrichten, wenn Sie die Docker-API über TCP verfügbar machen, damit Docker Engine und Ihre Clients die Identität der anderen überprüfen können. Andernfalls könnte jeder mit Zugriff auf den TCP-Port Ihre Docker-Container durchsuchen, neue starten und Aktionen als root
ausführen auf Ihrem System.
Bei konfiguriertem TLS müssen Clients ein gültiges Zertifikat vorlegen, das von der Zertifizierungsstelle des Servers signiert ist. Damit es funktioniert, müssen Sie SSL-Zertifikate erstellen und dann die Docker Engine so einrichten, dass TLS-Verbindungen erforderlich sind. Docker-CLI-Clients müssen auch so eingestellt werden, dass sie einen TLS-Server erwarten.
Den TCP-Socket freigeben
Sie können den TCP-Socket von Docker mit -H
verfügbar machen Flag zum Definieren eines zusätzlichen Endpunkts beim Starten von dockerd
Prozess. Dieses Flag kann mehrfach wiederholt werden; In diesem Beispiel sind sowohl der Unix-Socket als auch der TCP-Socket verfügbar:
/usr/bin/dockerd -H unix:///var/run/docker.sock -H tcp://0.0.0.0:2375
Port 2375 wird üblicherweise für unverschlüsselte Docker-Verbindungen verwendet. Port 2376 sollte stattdessen verwendet werden, sobald TLS eingerichtet wurde.
Sie können Docker so konfigurieren, dass diese Flags automatisch verwendet werden, indem Sie Ihre Docker-Dienstdefinition ändern. Fügen Sie eine Überschreibung in /etc/systemd/system/docker.service.d/override.conf
hinzu das ändert den ExecStart
Zeile:
[Service] ExecStart=/usr/bin/dockerd -H ...
Laden Sie systemd neu, um die Änderung zu übernehmen:
sudo systemctl daemon-reload
Erstellen Ihrer Zertifizierungsstelle
Erstellen Sie zunächst eine Zertifizierungsstelle (CA) für Ihre TLS-Konfiguration. Sie verwenden diese CA, um Ihre Zertifikate zu signieren; Der Server weigert sich, mit Clients zu kommunizieren, die ein Zertifikat von einer anderen Zertifizierungsstelle vorlegen.
Verwenden Sie OpenSSL, um private und öffentliche CA-Schlüssel auf dem Computer zu generieren, der Ihren Docker-Server hostet:
# Generate the private key openssl genrsa -aes256 -out ca-private.pem 4096 # Generate a public key from the private key openssl req -new -x509 -days 365 -key ca-private.pem -sha256 -out ca-public.pem
Sie werden aufgefordert, eine Passphrase, eine E-Mail-Adresse, einen Ländercode, Namen von Bundesstaaten und Städten sowie einen Organisationsnamen anzugeben, die Sie Ihrem öffentlichen Schlüssel hinzufügen möchten. Geben Sie die Informationen in Ihr Terminal ein und drücken Sie nach jeder Zeile die Eingabetaste, um fortzufahren und den Schlüssel zu erstellen.
Generieren eines Serverschlüssels und einer Zertifikatssignierungsanforderung
Erstellen Sie als Nächstes einen Serverschlüssel und eine Zertifikatsignieranforderung:
# Generate the server key openssl genrsa -out server-key.pem 4096 # Generate a certificate signing request openssl req -subj "/CN=example.com" -sha256 -new -key server-key.pm -out request.csr
Der Certificate Signing Request (CSR) enthält alle Informationen, die zum Erstellen eines signierten Zertifikats erforderlich sind. Es ist wichtig, dass der allgemeine Name in der CSR für Ihren Server korrekt ist. Dies wird im CN
angegeben Feld als example.com
Oben; Sie sollten ihn auf den vollständig qualifizierten Domänennamen (FQDN) für Ihren Server setzen.
Zertifikatserweiterungen einrichten
Die Verwendung dieses CSR würde Verbindungen zum Server über seinen FQDN zulassen. Sie müssen Zertifikatserweiterungen angeben, wenn Sie eine weitere Domäne hinzufügen oder eine IP-Adresse verwenden möchten. Erstellen Sie eine Erweiterungsdatei mit subjectAltName
und extendedKeyUsage
Felder, um dies einzurichten:
echo subjectAltName = DNS:sub.example.com;IP=192.168.0.1 >> extfile.cnf echo extendedKeyUsage = serverAuth >> extFile.cnf
Dieses Beispiel würde zusätzlich Verbindungen über sub.example.com
zulassen und 192.168.0.1
.
Generieren eines signierten Zertifikats
Jetzt können Sie alle Komponenten kombinieren und ein signiertes Zertifikat generieren:
openssl x509 -req -days 365 -sha256 -in request.csr -CA ca-public.pem -CAkey ca-private.pem -CAcreateserial -extfile extfile.cnf -out certificate.pem
Dies übernimmt die Zertifikatsignierungsanforderung, fügt Ihre Erweiterungsdatei hinzu und verwendet die Schlüssel Ihrer Zertifizierungsstelle, um ein signiertes OpenSSL-Zertifikat zu erstellen. Sie müssen die Passphrase der Zertifizierungsstelle angeben, um den Vorgang abzuschließen.
Dieses Zertifikat läuft nach einem Jahr ab. Sie können die -days
anpassen Flag, um eine Nutzungsdauer für Ihre Anforderungen zu erhalten. Sie sollten veranlassen, ein Ersatzzertifikat zu erstellen, bevor dieses abläuft.
Generieren eines Clientzertifikats
Als Nächstes sollten Sie ein weiteres Zertifikat generieren, das Ihre Docker-Clients verwenden können. Dieses muss von derselben CA signiert sein wie das Serverzertifikat. Verwenden Sie eine Erweiterungsdatei mit extendedKeyUsage = clientAuth
um dieses Zertifikat für die Verwendung in einem Client-Szenario vorzubereiten.
# Generate a client key openssl genrsa -out client-key.pem 4096 # Create a certificate signing request openssl req -subj '/CN=client' -new -key client-key.pem -out client-request.csr # Complete the signing echo extendedKeyUsage = clientAuth >> extfile-client.cnf openssl x509 -req -days 365 -sha256 -in client-request.csr -CA ca-public.pem -CAkey ca-private.pem -CAcreateserial -extfile extfile-client.cnf -out client-certificate.pem
Vorbereitung der Konfiguration von Docker
Kopieren Sie Ihre ca-public.pem
, certificate.pem
und server-key.pem
Dateien in ein neues Verzeichnis, das in Ihrer Docker-Konfiguration referenziert werden kann. Kopieren Sie anschließend die ca-public.pem
, client-certificate.pem
und client-key.pem
Dateien auf den Computer, von dem aus Sie sich verbinden.
Sie können die Zertifikatsignieranforderung und die Erweiterungsdateien in Ihrem Arbeitsverzeichnis löschen. Achten Sie darauf, Ihre privaten Schlüssel nicht zu verlieren, da sie nicht wiederherstellbar sind. Ohne sie können Sie keine Zertifikate validieren oder Verlängerungen generieren.
Docker-Daemon konfigurieren
Jetzt können Sie den Docker-Daemon mit TLS-Flags starten, die auf Ihr generiertes Zertifikat und Ihre Schlüssel verweisen. Das --tlscacert
, --tlscert
, und --tlskey
Parameter spezifizieren Pfade zu den jeweiligen oben generierten OpenSSL-Ressourcen.
/usr/bin/dockerd -H unix:///var/run/docker.sock -H tcp://0.0.0.0:2376 --tlsverify --tlscacert=ca-public.pem --tlscert=certificate.pem --tlskey=server-key.pem
Hinzufügen von --tlsverify
Flag aktiviert die Erzwingung von TLS-Verbindungen. Clients ohne passendes Zertifikat werden am Zugriff auf den TCP-Socket von Docker gehindert.
Docker-Client konfigurieren
Aktivieren Sie TLS auf dem Client, indem Sie TLS-Flags bereitstellen, wenn Sie den docker
verwenden Befehl. Sie müssen auch das -H
hinzufügen -Flag, um die Remote-Docker-Socket-Adresse anzugeben, zu der eine Verbindung hergestellt werden soll. Aus Sicht des Clients --tlsverify
bedeutet, dass der Befehl nur eine Verbindung zu Servern mit einem TLS-Zertifikat herstellt, das von derselben Zertifizierungsstelle signiert wurde wie seine eigene.
docker -H tcp://0.0.0.0:2376 --tlsverify --tlscacert=ca-public.pem --tlscert=client-certificate.pem --tlskey=client-key.pem ps
Das Bereitstellen dieser Flags bei jeder Verwendung der CLI wiederholt sich sehr schnell. Wenn Sie hauptsächlich mit demselben TLS-geschützten Host arbeiten, legen Sie DOCKER_HOST
fest und DOCKER_TLS_VERIFY
Umgebungsvariablen in Ihrem Shell-Profil. Kopieren Sie Ihre Zertifikatsdateien nach ca
, cert
, und key
in Ihrem ~/.docker
Verzeichnis. Diese entsprechen Dockers --tls
Flags und definieren Sie ein Standardzertifikat für den Client.
export DOCKER_HOST=tcp://0.0.0.0:2376 export DOCKER_TLS_VERIFY=1
Sie können die Arbeit mit mehreren Hosts vereinfachen, indem Sie eine Mischung aus lokalen, Remote-, ungesicherten und TLS-Verbindungen verwenden, indem Sie Docker-Kontexte einrichten. Mit dieser Funktion können Sie mithilfe von Docker-CLI-Befehlen zwischen Zielen wechseln.
Der Docker-Client unterstützt auch alternative Überprüfungsmodi. Verwenden einer Mischung aus tls
, tlscacert
, tlscert
, tlskey
und tlsverify
flags aktiviert unterschiedliche TLS-Durchsetzungsstufen.
Mit nur tls
gesetzt, authentifiziert Docker den Server mithilfe des Standard-CA-Pools. Hinzufügen des tlscacert
und tlsverify
Flags ohne Client-Schlüssel erzwingen, dass der Server die angegebene Zertifizierungsstelle ohne weitere Überprüfungen verwendet. Weglassen von tlscacert
und tlsverify
aber das Einschließen der anderen drei Schlüssel verifiziert das Zertifikat des Clients, ohne die Zertifizierungsstelle des Servers zu authentifizieren.
Schlussfolgerung
Durch den Schutz des TCP-Sockets von Docker mit TLS-Zertifikaten können Sie die API sicherer verfügbar machen, indem Sie Verbindungen von nicht autorisierten Clients verhindern. Akteure, die Ihr Netzwerk nach Ports scannen, werden daran gehindert, sich mit Docker zu verbinden, wodurch Sie eine Schutzebene erhalten, die verhindert, dass Ihr Computer mit Berechtigungen auf Root-Ebene kompromittiert wird.
Sobald Sie Ihre Zertifikate generiert haben, können Sie sie verwenden, um sich bei der Docker-CLI oder Ihren eigenen HTTP-Clients zu authentifizieren. Curl akzeptiert sie als --cert
, --key
und --cacert
Flaggen, zum Beispiel.
TLS ist nur eine Komponente einer gesicherten Docker-API-Instanz. Es bietet Verschlüsselung und die Gewissheit, dass Clients vertrauenswürdig sind, ist aber kein granularer Zugriffskontrollmechanismus.
Wenn Sie einschränken möchten, was einzelne Clients tun dürfen, sollten Sie ein Autorisierungs-Plugin für die Docker-Engine einrichten. Plugins können einen externen Dienst kontaktieren, um festzustellen, ob eine bestimmte API-Anforderung fortgesetzt werden darf. Alternativ könnten Sie einen Reverse-Proxy vor Ihrem TCP-Socket verwenden, um die Zugriffskontrolle zu erzwingen, bevor Anfragen Docker erreichen.