保護 Docker daemon 通訊端
預設情況下,Docker 透過非網路 UNIX 通訊端執行。它也可以選擇使用 SSH 或 TLS (HTTPS) 通訊端進行通訊。
使用 SSH 保護 Docker Daemon 通訊端
**注意**
指定的 `USERNAME` 必須具有存取遠端機器上 docker 通訊端的權限。請參閱以非 root 使用者身分管理 Docker,瞭解如何授予非 root 使用者存取 docker 通訊端的權限。
以下範例建立一個`docker context`,使用 SSH 以遠端機器上的 `docker-user` 使用者身分連線到 `host1.example.com` 上的遠端 `dockerd` daemon。
$ docker context create \
--docker host=ssh://docker-user@host1.example.com \
--description="Remote engine" \
my-remote-engine
my-remote-engine
Successfully created context "my-remote-engine"
建立上下文後,使用 `docker context use` 切換 `docker` CLI 以使用它,並連線到遠端引擎。
$ docker context use my-remote-engine
my-remote-engine
Current context is now "my-remote-engine"
$ docker info
<prints output of the remote engine>
使用 `default` 上下文切換回預設(本機)daemon。
$ docker context use default
default
Current context is now "default"
或者,使用 `DOCKER_HOST` 環境變數暫時切換 `docker` CLI 以使用 SSH 連線到遠端主機。這不需要建立上下文,並且可以用於與不同的引擎建立臨時連線。
$ export DOCKER_HOST=ssh://docker-user@host1.example.com
$ docker info
<prints output of the remote engine>
SSH 秘訣
為了獲得最佳的 SSH 使用體驗,請如下設定 `~/.ssh/config`,以便允許多次叫用 `docker` CLI 時重複使用 SSH 連線。
ControlMaster auto
ControlPath ~/.ssh/control-%C
ControlPersist yes
使用 TLS (HTTPS) 保護 Docker Daemon 通訊端
如果您需要 Docker 以安全的方式透過 HTTP 而非 SSH 連線,您可以透過指定 `tlsverify` 旗標,並將 Docker 的 `tlscacert` 旗標指向受信任的 CA 憑證來啟用 TLS (HTTPS)。
在 daemon 模式下,它只允許來自經該 CA 簽署的憑證驗證的用戶端連線。在用戶端模式下,它只連線到具有經該 CA 簽署的憑證的伺服器。
**重要**
使用 TLS 和管理 CA 是一個進階主題。在生產環境中使用它之前,請先熟悉 OpenSSL、x509 和 TLS。
使用 OpenSSL 建立 CA、伺服器和用戶端金鑰
**注意**
在以下範例中,將所有 `$HOST` 執行個體替換為 Docker daemon 主機的 DNS 名稱。
首先,在 Docker daemon 的主機上,產生 CA 私鑰和公鑰。
$ openssl genrsa -aes256 -out ca-key.pem 4096
Generating RSA private key, 4096 bit long modulus
..............................................................................++
........++
e is 65537 (0x10001)
Enter pass phrase for ca-key.pem:
Verifying - Enter pass phrase for ca-key.pem:
$ openssl req -new -x509 -days 365 -key ca-key.pem -sha256 -out ca.pem
Enter pass phrase for ca-key.pem:
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:
State or Province Name (full name) [Some-State]:Queensland
Locality Name (eg, city) []:Brisbane
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Docker Inc
Organizational Unit Name (eg, section) []:Sales
Common Name (e.g. server FQDN or YOUR name) []:$HOST
Email Address []:Sven@home.org.au
現在您已擁有 CA,您可以建立伺服器金鑰和憑證簽署請求 (CSR)。請確保「通用名稱」與您用來連線到 Docker 的主機名稱相符。
**注意**
在以下範例中,將所有 `$HOST` 執行個體替換為 Docker daemon 主機的 DNS 名稱。
$ openssl genrsa -out server-key.pem 4096
Generating RSA private key, 4096 bit long modulus
.....................................................................++
.................................................................................................++
e is 65537 (0x10001)
$ openssl req -subj "/CN=$HOST" -sha256 -new -key server-key.pem -out server.csr
接下來,我們將使用 CA 簽署公鑰。
由於 TLS 連線可以透過 IP 位址以及 DNS 名稱進行,因此在建立憑證時需要指定 IP 位址。例如,允許使用 10.10.10.20
和 127.0.0.1
進行連線。
$ echo subjectAltName = DNS:$HOST,IP:10.10.10.20,IP:127.0.0.1 >> extfile.cnf
將 Docker daemon 金鑰的延伸使用屬性設定為僅用於伺服器驗證。
$ echo extendedKeyUsage = serverAuth >> extfile.cnf
現在,產生已簽署的憑證。
$ openssl x509 -req -days 365 -sha256 -in server.csr -CA ca.pem -CAkey ca-key.pem \
-CAcreateserial -out server-cert.pem -extfile extfile.cnf
Signature ok
subject=/CN=your.host.com
Getting CA Private Key
Enter pass phrase for ca-key.pem:
授權插件 提供更精細的控制,以補充來自相互 TLS 的驗證。除了上述文件中描述的其他資訊外,在 Docker daemon 上執行的授權插件還會接收連線 Docker 用戶端的憑證資訊。
對於用戶端驗證,請建立用戶端金鑰和憑證簽署請求。
**注意**
為了簡化接下來的幾個步驟,您也可以在 Docker daemon 的主機上執行此步驟。
$ openssl genrsa -out key.pem 4096
Generating RSA private key, 4096 bit long modulus
.........................................................++
................++
e is 65537 (0x10001)
$ openssl req -subj '/CN=client' -new -key key.pem -out client.csr
要使金鑰適用於用戶端驗證,請建立新的延伸設定檔。
$ echo extendedKeyUsage = clientAuth > extfile-client.cnf
現在,產生已簽署的憑證。
$ openssl x509 -req -days 365 -sha256 -in client.csr -CA ca.pem -CAkey ca-key.pem \
-CAcreateserial -out cert.pem -extfile extfile-client.cnf
Signature ok
subject=/CN=client
Getting CA Private Key
Enter pass phrase for ca-key.pem:
產生 cert.pem
和 server-cert.pem
後,您可以安全地刪除兩個憑證簽署請求和延伸設定檔。
$ rm -v client.csr server.csr extfile.cnf extfile-client.cnf
使用預設的 umask
值 022,您的私鑰將會是 *全球可讀*,並且您可以和您的群組進行寫入。
為了保護您的金鑰免於意外損壞,請移除其寫入權限。若要使其僅供您讀取,請如下所示更改檔案模式。
$ chmod -v 0400 ca-key.pem key.pem server-key.pem
憑證可以是全球可讀的,但您可能需要移除寫入權限以防止意外損壞。
$ chmod -v 0444 ca.pem server-cert.pem cert.pem
現在您可以讓 Docker daemon 只接受來自提供受 CA 信任之憑證的用戶端的連線。
$ dockerd \
--tlsverify \
--tlscacert=ca.pem \
--tlscert=server-cert.pem \
--tlskey=server-key.pem \
-H=0.0.0.0:2376
要連線到 Docker 並驗證其憑證,請提供您的用戶端金鑰、憑證和受信任的 CA。
提示
此步驟應在您的 Docker 用戶端機器上執行。因此,您需要將您的 CA 憑證、伺服器憑證和用戶端憑證複製到該機器。
**注意**
在以下範例中,將所有 `$HOST` 執行個體替換為 Docker daemon 主機的 DNS 名稱。
$ docker --tlsverify \
--tlscacert=ca.pem \
--tlscert=cert.pem \
--tlskey=key.pem \
-H=$HOST:2376 version
**注意**
Docker over TLS 應在 TCP 埠 2376 上執行。
警告
如上例所示,當您使用憑證驗證時,您不需要使用
sudo
或docker
群組來執行docker
用戶端。這表示任何擁有金鑰的人都可以向您的 Docker daemon 發出任何指令,讓他們擁有對託管 daemon 之機器的 root 權限。請像保護 root 密碼一樣保護這些金鑰!
預設安全
如果您想預設保護 Docker 用戶端連線的安全,您可以將檔案移動到您家目錄中的 .docker
目錄 --- 並設定 DOCKER_HOST
和 DOCKER_TLS_VERIFY
變數 (而不是在每次呼叫時傳遞 -H=tcp://$HOST:2376
和 --tlsverify
)。
$ mkdir -pv ~/.docker
$ cp -v {ca,cert,key}.pem ~/.docker
$ export DOCKER_HOST=tcp://$HOST:2376 DOCKER_TLS_VERIFY=1
Docker 現在預設以安全的方式連線。
$ docker ps
其他模式
如果您不想進行完整的雙向驗證,您可以透過混合使用旗標,在各種其他模式下執行 Docker。
Daemon 模式
- 設定
tlsverify
、tlscacert
、tlscert
、tlskey
:驗證用戶端。 tls
、tlscert
、tlskey
:不驗證用戶端。
用戶端模式
tls
:根據公開/預設 CA 池驗證伺服器。tlsverify
、tlscacert
:根據指定的 CA 驗證伺服器。tls
、tlscert
、tlskey
:使用用戶端憑證進行驗證,不根據指定的 CA 驗證伺服器。tlsverify
、tlscacert
、tlscert
、tlskey
:使用用戶端憑證進行驗證,並根據指定的 CA 驗證伺服器。
如果找到,用戶端會發送其用戶端憑證,因此您只需將您的金鑰放入 ~/.docker/{ca,cert,key}.pem
即可。或者,如果您想將金鑰儲存在其他位置,您可以使用環境變數 DOCKER_CERT_PATH
指定該位置。
$ export DOCKER_CERT_PATH=~/.docker/zone1/
$ docker --tlsverify ps
使用 curl
連線到安全的 Docker 埠。
要使用 curl
進行測試 API 請求,您需要使用三個額外的命令列旗標。
$ curl https://$HOST:2376/images/json \
--cert ~/.docker/cert.pem \
--key ~/.docker/key.pem \
--cacert ~/.docker/ca.pem