Поиск по сайту:

Как защитить TCP-сокет Docker с помощью TLS


API Docker по умолчанию полностью незащищен, за исключением разрешений файловой системы на сокет Unix. Вам следует настроить TLS при предоставлении Docker API через TCP, чтобы Docker Engine и ваши клиенты могли проверять личность друг друга. В противном случае любой, у кого есть доступ к TCP-порту, сможет просматривать ваши контейнеры Docker, запускать новые и выполнять действия от имени root в вашей системе.

Настроенный TLS потребует от клиентов предоставления действительного сертификата, подписанного центром сертификации сервера. Чтобы заставить его работать, вам нужно создать SSL-сертификаты, а затем настроить Docker Engine так, чтобы он требовал подключения TLS. Клиенты Docker CLI также должны быть настроены так, чтобы они ожидали сервер TLS.

Открытие сокета TCP

Вы можете открыть TCP-сокет Docker, используя флаг -H, чтобы определить дополнительную конечную точку при запуске процесса dockerd. Этот флаг может повторяться несколько раз; в этом примере будут доступны как сокет Unix, так и сокет TCP:

/usr/bin/dockerd -H unix:///var/run/docker.sock -H tcp://0.0.0.0:2375

Порт 2375 обычно используется для незашифрованных соединений Docker. Вместо этого следует использовать порт 2376 после настройки TLS.

Вы можете настроить Docker на автоматическое использование этих флагов, изменив определение службы Docker. Добавьте переопределение в /etc/systemd/system/docker.service.d/override.conf, которое изменяет строку ExecStart:

[Service]
ExecStart=/usr/bin/dockerd -H ...

Перезагрузите systemd, чтобы применить изменения:

sudo systemctl daemon-reload

Создание вашего центра сертификации

Начните с создания центра сертификации (ЦС) для вашей конфигурации TLS. Вы будете использовать этот ЦС для подписи своих сертификатов; сервер откажется взаимодействовать с клиентами, которые представляют сертификат другого ЦС.

Используйте OpenSSL для создания закрытых и открытых ключей CA на компьютере, на котором размещен ваш сервер 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

Вам будет предложено ввести парольную фразу, адрес электронной почты, код страны, названия штатов и городов, а также название организации, которые необходимо включить в открытый ключ. Введите информацию в свой терминал, нажимая ввод после каждой строки, чтобы двигаться вперед и создать ключ.

Генерация ключа сервера и запроса на подпись сертификата

Затем создайте ключ сервера и запрос на подпись сертификата:

# 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

Запрос на подпись сертификата (CSR) содержит всю информацию, необходимую для создания подписанного сертификата. Важно проверить правильность общего имени в CSR для вашего сервера. Это указано в поле CN как example.com выше; вы должны установить его на полное доменное имя (FQDN) для вашего сервера.

Настройка расширений сертификата

Использование этого CSR разрешит подключения к серверу через его полное доменное имя. Вам необходимо указать расширения сертификата, если вы хотите добавить еще один домен или использовать IP-адрес. Создайте файл расширений с полями subjectAltName и extendedKeyUsage, чтобы настроить это:

echo subjectAltName = DNS:sub.example.com;IP=192.168.0.1 >> extfile.cnf
echo extendedKeyUsage = serverAuth >> extFile.cnf

Этот пример дополнительно разрешает подключения через sub.example.com и 192.168.0.1 .

Создание подписанного сертификата

Теперь вы готовы объединить все компоненты и сгенерировать подписанный сертификат:

openssl x509 -req -days 365 -sha256 
    -in request.csr 
    -CA ca-public.pem 
    -CAkey ca-private.pem 
    -CAcreateserial 
    -extfile extfile.cnf 
    -out certificate.pem

Это берет запрос на подпись сертификата, добавляет ваш файл расширения и использует ключи вашего ЦС для создания подписанного сертификата OpenSSL. Вам нужно будет указать парольную фразу ЦС для завершения процесса.

Срок действия этого сертификата истекает через год. Вы можете настроить флаг -days, чтобы получить полезное время жизни для ваших требований. Вы должны договориться о создании нового сертификата до истечения срока действия этого.

Генерация клиентского сертификата

Затем вы должны сгенерировать еще один сертификат для использования вашими клиентами Docker. Он должен быть подписан тем же ЦС, что и сертификат сервера. Используйте файл расширений с extendedKeyUsage=clientAuth, чтобы подготовить этот сертификат для использования в клиентском сценарии.

# 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

Подготовка к настройке Docker

Скопируйте файлы ca-public.pem, certificate.pem и server-key.pem в новый каталог, готовый к использованию в Docker. конфиг. После этого скопируйте файлы ca-public.pem, client-certificate.pem и client-key.pem на компьютер, который вы Подключу из.

Вы можете удалить запрос на подпись сертификата и файлы расширения в своем рабочем каталоге. Будьте осторожны, чтобы не потерять свои закрытые ключи, поскольку их невозможно восстановить. Без них вы не сможете проверять сертификаты или генерировать обновления.

Настройка демона Docker

Теперь вы можете запустить демон Docker с флагами TLS, ссылающимися на ваш сгенерированный сертификат и ключи. Параметры --tlscert, --tlscert и --tlskey указывают пути к соответствующим ресурсам OpenSSL, созданным выше.

/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

Добавление флага --tlsverify включает принудительное использование соединений TLS. Клиентам без соответствующего сертификата будет заблокирован доступ к TCP-сокету Docker.

Настройка Docker-клиента

Активируйте TLS на клиенте, указав флаги TLS при использовании команды docker. Вы также должны добавить флаг -H, чтобы указать адрес удаленного сокета Docker для подключения. С точки зрения клиента --tlsverify означает, что команда будет подключаться только к серверам с сертификатом TLS, подписанным тем же центром сертификации, что и ее собственный.

docker 
    -H tcp://0.0.0.0:2376 
    --tlsverify 
    --tlscacert=ca-public.pem 
    --tlscert=client-certificate.pem 
    --tlskey=client-key.pem 
    ps

Предоставление этих флагов каждый раз, когда вы используете CLI, очень быстро повторяется. Если вы в основном будете работать с одним и тем же хостом, защищенным TLS, установите переменные среды DOCKER_HOST и DOCKER_TLS_VERIFY в своем профиле оболочки. Скопируйте файлы сертификатов в ca, cert и key внутри вашего каталога ~/.docker. Они соответствуют флагам Docker --tls и определяют сертификат по умолчанию для клиента.

export DOCKER_HOST=tcp://0.0.0.0:2376
export DOCKER_TLS_VERIFY=1

Вы можете упростить работу с несколькими хостами, используя сочетание локальных, удаленных, незащищенных и TLS-подключений, настроив контексты Docker. Эта функция позволяет переключаться между целями с помощью команд Docker CLI.

Клиент Docker также поддерживает альтернативные режимы проверки. Использование комбинации флагов tls, tlscacert, tlscert, tlskey и tlsverify активирует различные уровни принудительного использования TLS.

Только с установленным tls Docker будет аутентифицировать сервер, используя пул ЦС по умолчанию. Добавление флагов tlscacert и tlsverify без ключа клиента приведет к тому, что сервер будет использовать данный ЦС без каких-либо других проверок. Если не указывать tlscacert и tlsverify, но включать остальные три ключа, сертификат клиента будет проверен без аутентификации ЦС сервера.

Заключение

Защита TCP-сокета Docker с помощью сертификатов TLS позволяет более безопасно раскрывать API, предотвращая подключения от неавторизованных клиентов. Субъектам, которые сканируют порты вашей сети, будет запрещено подключаться к Docker, предоставляя вам уровень защиты, который предотвращает компрометацию вашей машины с привилегиями корневого уровня.

Создав сертификаты, вы можете использовать их для аутентификации с помощью интерфейса командной строки Docker или ваших собственных HTTP-клиентов. Curl примет их, например, как флаги --cert, --key и --cacert.

TLS — это только один компонент защищенного экземпляра Docker API. Он обеспечивает шифрование и гарантию того, что клиентам доверяют, но не является детальным механизмом контроля доступа.

Если вы хотите ограничить то, что разрешено делать отдельным клиентам, вам следует настроить плагин авторизации Docker Engine. Плагины могут связываться с внешней службой, чтобы определить, разрешено ли выполнение конкретного запроса API. В качестве альтернативы вы можете использовать обратный прокси-сервер перед вашим TCP-сокетом, чтобы обеспечить контроль доступа до того, как запросы достигнут Docker.