La API de Docker está completamente desprotegida de forma predeterminada, excepto por los permisos del sistema de archivos en su socket Unix. Debe configurar TLS cuando exponga la API de Docker a través de TCP para que Docker Engine y sus clientes puedan verificar la identidad de los demás. De lo contrario, cualquier persona con acceso al puerto TCP podría explorar sus contenedores Docker, iniciar nuevos y ejecutar acciones como root
en su sistema.
El TLS configurado requerirá que los clientes presenten un certificado válido firmado por la autoridad de certificación del servidor. Para que funcione, debe crear certificados SSL y luego configurar Docker Engine para que requiera conexiones TLS. Los clientes de Docker CLI también deben ajustarse para esperar un servidor TLS.
Exponiendo el socket TCP
Puede exponer el socket TCP de Docker usando -H
marca para definir un punto final adicional al iniciar el dockerd
proceso. Esta bandera se puede repetir varias veces; en este ejemplo, tanto el socket Unix como el socket TCP estarán disponibles:
/usr/bin/dockerd -H unix:///var/run/docker.sock -H tcp://0.0.0.0:2375
El puerto 2375 se usa convencionalmente para conexiones Docker sin cifrar. En su lugar, se debe usar el puerto 2376 una vez que se haya configurado TLS.
Puede configurar Docker para usar estos indicadores automáticamente modificando su definición de servicio de Docker. Agregue una anulación en /etc/systemd/system/docker.service.d/override.conf
que cambia el ExecStart
línea:
[Service] ExecStart=/usr/bin/dockerd -H ...
Vuelva a cargar systemd para aplicar el cambio:
sudo systemctl daemon-reload
Creación de su autoridad de certificación
Comience por crear una Autoridad de certificación (CA) para su configuración de TLS. Utilizará esta CA para firmar sus certificados; el servidor se negará a comunicarse con clientes que presenten un certificado de una CA diferente.
Use OpenSSL para generar claves de CA públicas y privadas en la máquina que aloja su servidor 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
Se le pedirá que proporcione una frase de contraseña, dirección de correo electrónico, código de país, nombres de estado y ciudad y nombre de la organización para incluir con su clave pública. Ingrese la información en su terminal, presionando enter después de cada línea para avanzar y crear la clave.
Generar una clave de servidor y una solicitud de firma de certificado
A continuación, cree una clave de servidor y una solicitud de firma de certificado:
# 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 solicitud de firma de certificado (CSR) contiene toda la información necesaria para producir un certificado firmado. Es importante verificar que el nombre común en la CSR sea correcto para su servidor. Esto se especifica en el CN
campo como example.com
sobre; debe establecerlo en el Nombre de dominio completo (FQDN) para su servidor.
Configuración de extensiones de certificado
El uso de este CSR permitiría las conexiones al servidor a través de su FQDN. Debe especificar extensiones de certificado si desea agregar otro dominio o usar una dirección IP. Cree un archivo de extensiones con subjectAltName
y extendedKeyUsage
campos para configurar esto:
echo subjectAltName = DNS:sub.example.com;IP=192.168.0.1 >> extfile.cnf echo extendedKeyUsage = serverAuth >> extFile.cnf
Este ejemplo también permitiría conexiones a través de sub.example.com
y 192.168.0.1
.
Generando un Certificado Firmado
Ahora está listo para combinar todos los componentes y generar un certificado firmado:
openssl x509 -req -days 365 -sha256 -in request.csr -CA ca-public.pem -CAkey ca-private.pem -CAcreateserial -extfile extfile.cnf -out certificate.pem
Esto toma la solicitud de firma del certificado, agrega su archivo de extensión y usa las claves de su CA para producir un certificado OpenSSL firmado. Deberá proporcionar la frase de contraseña de la CA para completar el proceso.
Este certificado expirará después de un año. Puede ajustar los -days
bandera para obtener una vida útil para sus requerimientos. Debe hacer arreglos para generar un certificado de reemplazo antes de que este caduque.
Generando un Certificado de Cliente
A continuación, debe generar otro certificado para que lo utilicen sus clientes de Docker. Esto debe estar firmado por la misma CA que el certificado del servidor. Use un archivo de extensiones con extendedKeyUsage = clientAuth
para preparar este certificado para su uso en un escenario de cliente.
# 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
Preparación para configurar Docker
Copie su ca-public.pem
, certificate.pem
y server-key.pem
archivos en un nuevo directorio listo para hacer referencia en su configuración de Docker. Luego, copie el ca-public.pem
, client-certificate.pem
y client-key.pem
archivos a la máquina desde la que se conectará.
Puede eliminar la solicitud de firma del certificado y los archivos de extensión en su directorio de trabajo. Tenga cuidado de no perder sus claves privadas, ya que no son recuperables. Sin ellos, no podrá validar certificados ni generar renovaciones.
Configurando el demonio Docker
Ahora puede iniciar el demonio de Docker con indicadores TLS que hacen referencia a su certificado y claves generados. El --tlscacert
, --tlscert
y --tlskey
Los parámetros especifican rutas a los respectivos recursos de OpenSSL generados anteriormente.
/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
Agregando el --tlsverify
bandera habilita la aplicación de conexiones TLS. Los clientes sin un certificado coincidente no podrán acceder al socket TCP de Docker.
Configuración del cliente Docker
Active TLS en el cliente proporcionando indicadores de TLS cuando utilice la docker
dominio. También debe agregar el -H
marca para especificar la dirección del socket Docker remoto a la que conectarse. Desde la perspectiva del cliente, --tlsverify
significa que el comando solo se conectará a servidores con un certificado TLS firmado por la misma autoridad de certificación que el suyo.
docker -H tcp://0.0.0.0:2376 --tlsverify --tlscacert=ca-public.pem --tlscert=client-certificate.pem --tlskey=client-key.pem ps
Proporcionar estas banderas cada vez que usa la CLI se vuelve repetitivo muy rápidamente. Si va a trabajar principalmente con el mismo host protegido por TLS, configure el DOCKER_HOST
y DOCKER_TLS_VERIFY
variables de entorno en su perfil de shell. Copie sus archivos de certificados a ca
, cert
y key
dentro de su ~/.docker
directorio. Estos corresponden a --tls
de Docker marca y define un certificado predeterminado para el cliente.
export DOCKER_HOST=tcp://0.0.0.0:2376 export DOCKER_TLS_VERIFY=1
Puede simplificar el trabajo con varios hosts mediante una combinación de conexiones locales, remotas, no seguras y TLS mediante la configuración de contextos de Docker. Esta función le permite alternar entre destinos mediante los comandos de la CLI de Docker.
El cliente de Docker también admite modos de verificación alternativos. Usando una mezcla de tls
, tlscacert
, tlscert
, tlskey
y tlsverify
flags activa varios niveles de aplicación de TLS.
Con solo tls
establecido, Docker autenticará el servidor utilizando el grupo de CA predeterminado. Agregando el tlscacert
y tlsverify
las banderas sin una clave de cliente obligarán a que el servidor use la CA dada sin ninguna otra verificación. Omitiendo tlscacert
y tlsverify
pero incluir las otras tres claves verificará el certificado del cliente sin autenticar la CA del servidor.
Conclusión
La protección del socket TCP de Docker con certificados TLS le permite exponer la API de manera más segura al evitar las conexiones de clientes no autorizados. Los actores que escanean puertos de su red no podrán conectarse a Docker, lo que le brinda una capa de protección que evita que su máquina se vea comprometida con privilegios de nivel raíz.
Una vez que haya generado sus certificados, puede usarlos para autenticarse con la CLI de Docker o con sus propios clientes HTTP. Curl los aceptará como --cert
, --key
y --cacert
banderas, por ejemplo.
TLS es solo un componente de una instancia segura de la API de Docker. Proporciona cifrado y una garantía de que los clientes son de confianza, pero no es un mecanismo de control de acceso granular.
Si desea limitar lo que los clientes individuales pueden hacer, debe configurar un complemento de autorización de Docker Engine. Los complementos pueden ponerse en contacto con un servicio externo para determinar si se permite continuar con una solicitud de API en particular. Como alternativa, podría usar un proxy inverso frente a su socket TCP para aplicar el control de acceso antes de que las solicitudes lleguen a Docker.