L'API di Docker non è completamente protetta per impostazione predefinita, ad eccezione dei permessi del filesystem sul suo socket Unix. Dovresti configurare TLS quando esponi l'API Docker su TCP in modo che Docker Engine e i tuoi client possano verificarsi l'identità dell'altro. Altrimenti chiunque abbia accesso alla porta TCP potrebbe sfogliare i tuoi contenitori Docker, avviarne di nuovi ed eseguire azioni come root
sul tuo sistema.
Il TLS configurato richiederà ai client di presentare un certificato valido firmato dall'autorità di certificazione del server. Per farlo funzionare, devi creare certificati SSL, quindi configurare Docker Engine per richiedere connessioni TLS. Anche i client Docker CLI devono essere adattati per prevedere un server TLS.
Esposizione del socket TCP
Puoi esporre il socket TCP di Docker usando il -H
flag per definire un endpoint aggiuntivo all'avvio di dockerd
processi. Questo flag può essere ripetuto più volte; in questo esempio saranno disponibili sia il socket Unix che il socket TCP:
/usr/bin/dockerd -H unix:///var/run/docker.sock -H tcp://0.0.0.0:2375
La porta 2375 viene convenzionalmente utilizzata per le connessioni Docker non crittografate. La porta 2376 dovrebbe essere utilizzata invece una volta che TLS è stato configurato.
È possibile configurare Docker per l'utilizzo automatico di questi flag modificando la definizione del servizio Docker. Aggiungi un override in /etc/systemd/system/docker.service.d/override.conf
che cambia il ExecStart
riga:
[Service] ExecStart=/usr/bin/dockerd -H ...
Ricarica systemd per applicare la modifica:
sudo systemctl daemon-reload
Creazione della tua autorità di certificazione
Inizia creando un'autorità di certificazione (CA) per la tua configurazione TLS. Utilizzerai questa CA per firmare i tuoi certificati; il server rifiuterà di comunicare con i client che presentano un certificato da un'altra CA.
Usa OpenSSL per generare chiavi CA private e pubbliche sulla macchina che ospita il tuo server Docker:
# 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
Ti verrà chiesto di fornire una passphrase, un indirizzo e-mail, il prefisso internazionale, i nomi di stato e città e il nome dell'organizzazione da includere con la tua chiave pubblica. Inserisci le informazioni nel tuo terminale, premendo invio dopo ogni riga per andare avanti e creare la chiave.
Generazione di una chiave server e di una richiesta di firma del certificato
Quindi crea una chiave del server e una richiesta di firma del certificato:
# 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
La richiesta di firma del certificato (CSR) contiene tutte le informazioni necessarie per produrre un certificato firmato. È importante verificare che il nome comune nella CSR sia corretto per il tuo server. Questo è specificato nel CN
campo come example.com
sopra; dovresti impostarlo sul nome di dominio completo (FQDN) per il tuo server.
Configurazione delle estensioni del certificato
L'utilizzo di questo CSR consentirebbe le connessioni al server tramite il suo FQDN. È necessario specificare le estensioni del certificato se si desidera aggiungere un altro dominio o utilizzare un indirizzo IP. Crea un file di estensioni con subjectAltName
e extendedKeyUsage
campi per impostarlo:
echo subjectAltName = DNS:sub.example.com;IP=192.168.0.1 >> extfile.cnf echo extendedKeyUsage = serverAuth >> extFile.cnf
Questo esempio consentirebbe inoltre connessioni tramite sub.example.com
e 192.168.0.1
.
Generazione di un certificato firmato
Ora sei pronto per combinare tutti i componenti e generare un certificato firmato:
openssl x509 -req -days 365 -sha256 -in request.csr -CA ca-public.pem -CAkey ca-private.pem -CAcreateserial -extfile extfile.cnf -out certificate.pem
Questo prende la richiesta di firma del certificato, aggiunge il tuo file di estensione e usa le chiavi della tua CA per produrre un certificato OpenSSL firmato. Dovrai fornire la passphrase della CA per completare il processo.
Questo certificato scadrà dopo un anno. Puoi modificare i -days
flag per ottenere una vita utile per le tue esigenze. Dovresti organizzare la generazione di un certificato sostitutivo prima della scadenza di questo.
Generazione di un certificato cliente
Successivamente dovresti generare un altro certificato da utilizzare per i tuoi client Docker. Questo deve essere firmato dalla stessa CA del certificato del server. Usa un file di estensioni con extendedKeyUsage = clientAuth
per preparare questo certificato per l'uso in uno scenario client.
# 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
Preparazione alla configurazione della finestra mobile
Copia il tuo ca-public.pem
, certificate.pem
e server-key.pem
file in una nuova directory pronta per fare riferimento nella tua configurazione Docker. Successivamente, copia il ca-public.pem
, client-certificate.pem
e client-key.pem
file alla macchina da cui ti connetterai.
È possibile eliminare la richiesta di firma del certificato e i file di estensione nella directory di lavoro. Fai attenzione a non perdere le tue chiavi private perché non sono recuperabili. Senza di essi non sarai in grado di convalidare certificati o generare rinnovi.
Configurazione del demone Docker
Ora puoi avviare il demone Docker con i flag TLS che fanno riferimento al certificato e alle chiavi generati. Il --tlscacert
, --tlscert
e --tlskey
i parametri specificano i percorsi delle rispettive risorse OpenSSL generate sopra.
/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
Aggiunta di --tlsverify
flag abilita l'applicazione delle connessioni TLS. Ai client senza un certificato corrispondente verrà impedito di accedere al socket TCP di Docker.
Configurazione del client Docker
Attiva TLS sul client fornendo i flag TLS quando utilizzi la docker
comando. Devi anche aggiungere il -H
flag per specificare l'indirizzo del socket Docker remoto a cui connettersi. Dal punto di vista del cliente, --tlsverify
significa che il comando si connetterà solo ai server con un certificato TLS firmato dalla stessa autorità di certificazione.
docker -H tcp://0.0.0.0:2376 --tlsverify --tlscacert=ca-public.pem --tlscert=client-certificate.pem --tlskey=client-key.pem ps
Fornire questi flag ogni volta che si utilizza la CLI diventa ripetitivo molto rapidamente. Se lavorerai principalmente con lo stesso host protetto da TLS, imposta il DOCKER_HOST
e DOCKER_TLS_VERIFY
variabili di ambiente nel tuo profilo shell. Copia i file dei tuoi certificati in ca
, cert
e key
all'interno del tuo ~/.docker
directory. Questi corrispondono a --tls
di Docker flag e definire un certificato predefinito per il client.
export DOCKER_HOST=tcp://0.0.0.0:2376 export DOCKER_TLS_VERIFY=1
Puoi semplificare il lavoro con più host utilizzando una combinazione di connessioni locali, remote, non protette e TLS configurando contesti Docker. Questa funzione ti consente di passare da un target all'altro utilizzando i comandi Docker CLI.
Il client Docker supporta anche modalità di verifica alternative. Usando una combinazione di tls
, tlscacert
, tlscert
, tlskey
e tlsverify
flags attiva diversi livelli di imposizione TLS.
Con solo tls
impostato, Docker autenticherà il server utilizzando il pool CA predefinito. Aggiunta del tlscacert
e tlsverify
i flag senza una chiave client imporranno che il server utilizzi la CA specificata senza altri controlli. Omissione di tlscacert
e tlsverify
ma includendo le altre tre chiavi verificherà il certificato del client senza autenticare la CA del server.
Conclusione
La protezione del socket TCP di Docker con i certificati TLS ti consente di esporre l'API in modo più sicuro impedendo connessioni da client non autorizzati. Agli attori che effettuano la scansione delle porte della tua rete verrà impedito di connettersi a Docker, offrendoti un livello di protezione che impedisce che la tua macchina venga compromessa con privilegi a livello di root.
Dopo aver generato i certificati, puoi utilizzarli per autenticarti con Docker CLI o con i tuoi client HTTP. Curl li accetterà come --cert
, --key
e --cacert
bandiere, per esempio.
TLS è solo un componente di un'istanza dell'API Docker protetta. Fornisce la crittografia e la garanzia che i client sono affidabili, ma non è un meccanismo di controllo degli accessi granulare.
Se desideri limitare ciò che i singoli client possono fare, devi configurare un plug-in di autorizzazione Docker Engine. I plugin possono contattare un servizio esterno per determinare se una particolare richiesta API può procedere. In alternativa, puoi utilizzare un proxy inverso davanti al tuo socket TCP per imporre il controllo dell'accesso prima che le richieste raggiungano Docker.