DockerのAPIは、Unixソケットのファイルシステム権限を除いて、デフォルトでは完全に保護されていません。 Docker API over TCPを公開するときにTLSを設定して、DockerEngineとクライアントが互いのIDを確認できるようにする必要があります。そうしないと、TCPポートにアクセスできる人なら誰でも、Dockerコンテナを参照して新しいコンテナを起動し、root
としてアクションを実行できます。 システム上で。
構成されたTLSでは、クライアントはサーバーの認証局によって署名された有効な証明書を提示する必要があります。これを機能させるには、SSL証明書を作成してから、TLS接続を要求するようにDockerエンジンを設定する必要があります。 Docker CLIクライアントも、TLSサーバーを期待するように調整する必要があります。
TCPソケットの公開
-H
を使用して、DockerのTCPソケットを公開できます。 dockerd
を開始するときに追加のエンドポイントを定義するフラグ 処理する。このフラグは複数回繰り返すことができます。この例では、UnixソケットとTCPソケットの両方が使用可能になります:
/usr/bin/dockerd -H unix:///var/run/docker.sock -H tcp://0.0.0.0:2375
ポート2375は、従来、暗号化されていないDocker接続に使用されます。 TLSが設定されたら、代わりにポート2376を使用する必要があります。
Dockerサービス定義を変更することで、これらのフラグを自動的に使用するようにDockerを構成できます。 /etc/systemd/system/docker.service.d/override.conf
にオーバーライドを追加します ExecStart
を変更します 行:
[Service] ExecStart=/usr/bin/dockerd -H ...
systemdをリロードして変更を適用します:
sudo systemctl daemon-reload
TLS構成の認証局(CA)を作成することから始めます。このCAを使用して証明書に署名します。サーバーは、別のCAからの証明書を提示するクライアントとの通信を拒否します。
OpenSSLを使用して、Dockerサーバーをホストしているマシンで秘密および公開のCAキーを生成します。
# 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
公開鍵に含めるパスフレーズ、メールアドレス、国コード、州名と市名、組織名を入力するよう求められます。ターミナルに情報を入力し、各行の後でEnterキーを押して先に進み、キーを作成します。
次に、サーバーキーと証明書署名要求を作成します。
# 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を使用すると、FQDNを介したサーバーへの接続が許可されます。別のドメインを追加したり、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
これにより、証明書署名要求が取得され、拡張ファイルが追加され、CAのキーを使用して署名されたOpenSSL証明書が生成されます。プロセスを完了するには、CAのパスフレーズを入力する必要があります。
この証明書は、1年後に期限切れになるように設定されています。 -days
を調整できます 要件の有効期間を取得するためのフラグ。この証明書の有効期限が切れる前に、交換用の証明書を生成するように手配する必要があります。
次に、Dockerクライアントが使用する別の証明書を生成する必要があります。これは、サーバー証明書と同じCAによって署名されている必要があります。 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デーモンの構成
これで、生成された証明書とキーを参照するTLSフラグを使用してDockerデーモンを起動できます。 --tlscacert
、--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接続の実施を有効にします。一致する証明書がないクライアントは、DockerのTCPソケットへのアクセスがブロックされます。
Dockerクライアントの構成
docker
を使用するときにTLSフラグを指定して、クライアントでTLSをアクティブ化します 指図。 -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
Dockerコンテキストを設定することで、ローカル、リモート、セキュリティで保護されていない、TLS接続を組み合わせて使用する複数のホストでの作業を簡素化できます。この機能を使用すると、DockerCLIコマンドを使用してターゲットを切り替えることができます。
Dockerクライアントは、代替の検証モードもサポートしています。 tls
を組み合わせて使用する 、tlscacert
、tlscert
、tlskey
、およびtlsverify
フラグはさまざまなTLS施行レベルをアクティブにします。
tls
だけで 設定すると、DockerはデフォルトのCAプールを使用してサーバーを認証します。 tlscacert
を追加する およびtlsverify
クライアントキーのないフラグは、サーバーが他のチェックなしで指定されたCAを使用することを強制します。 tlscacert
を省略します およびtlsverify
ただし、他の3つのキーを含めると、サーバーのCAを認証せずにクライアントの証明書を検証します。
DockerのTCPソケットをTLS証明書で保護すると、許可されていないクライアントからの接続を防ぐことで、APIをより安全に公開できます。ネットワークをポートスキャンするアクターはDockerへの接続を禁止され、ルートレベルの権限でマシンが危険にさらされるのを防ぐ保護レイヤーを提供します。
証明書を生成したら、それらを使用してDockerCLIまたは独自のHTTPクライアントで認証できます。 Curlはそれらを--cert
として受け入れます 、--key
、および--cacert
たとえば、フラグ。
TLSは、セキュリティで保護されたDockerAPIインスタンスの1つのコンポーネントにすぎません。暗号化を提供し、クライアントが信頼されていることを保証しますが、きめ細かいアクセス制御メカニズムではありません。
個々のクライアントに許可される機能を制限する場合は、DockerEngine認証プラグインを設定する必要があります。プラグインは外部サービスに接続して、特定のAPIリクエストの続行が許可されているかどうかを判断できます。別の方法として、TCPソケットの前でリバースプロキシを使用して、リクエストがDockerに到達する前にアクセス制御を適用することもできます。