安全的docker远程连接

94 min read

一键配置安全的Docker远程连接脚本

#!/bin/bash


#

# Created by L.STONE <[email protected]>

# Mod By Ryan.L <[email protected]>

# -------------------------------------------------------------

# 自动创建 Docker TLS 证书

# -------------------------------------------------------------



# 以下是配置信息

# Config start

IP="<your vps ip>"

PASSWORD="123456"

COUNTRY="CN"

STATE="Beijing"

CITY=""

ORGANIZATION="iPlayLoli"

ORGANIZATIONAL_UNIT="Dev"

COMMON_NAME="$IP"

EMAIL="[email protected]"

# Config end

# 工作目录

mkdir -p /etc/docker ~/.docker

cd ~/.docker

# 停止 docker

service docker stop

# 生成 CA 密钥

if [[ ! -f ca-key.pem ]]; then

echo " - 生成 CA 密钥"

openssl genrsa -aes256 -passout "pass:$PASSWORD" -out "ca-key.pem" 4096

fi

# 生成 CA

if [[ ! -f ca.pem ]]; then

echo " - 生成 CA"

openssl req -new -x509 -days 365 -key "ca-key.pem" -sha256 -out "ca.pem" -passin "pass:$PASSWORD" -subj "/C=$COUNTRY/ST=$STATE/L=$CITY/O=$ORGANIZATION/OU=$ORGANIZATIONAL_UNIT/CN=$COMMON_NAME/emailAddress=$EMAIL"

fi

# 生成服务器密钥 & 服务器证书

if [[ ! -f server-key.pem ]]; then

echo " - 生成服务器密钥"

openssl genrsa -out "server-key.pem" 4096

fi

if [[ ! -f server.csr ]]; then

openssl req -subj "/CN=$COMMON_NAME" -sha256 -new -key "server-key.pem" -out server.csr

fi

if [[ ! -f server-cert.pem ]]; then

echo " - 生成服务器证书"

echo "subjectAltName = IP:$IP,IP:127.0.0.1" >> extfile.cnf

echo "extendedKeyUsage = serverAuth" >> extfile.cnf

openssl x509 -req -days 365 -sha256 -in server.csr -passin "pass:$PASSWORD" -CA "ca.pem" -CAkey "ca-key.pem" -CAcreateserial -out "server-cert.pem" -extfile extfile.cnf

fi

rm -f extfile.cnf

# 生成客户端证书

if [[ ! -f key.pem ]]; then

openssl genrsa -out "key.pem" 4096

fi

if [[ ! -f cert.pem ]]; then

openssl req -subj '/CN=client' -new -key "key.pem" -out client.csr

echo extendedKeyUsage = clientAuth >> extfile.cnf

openssl x509 -req -days 365 -sha256 -in client.csr -passin "pass:$PASSWORD" -CA "ca.pem" -CAkey "ca-key.pem" -CAcreateserial -out "cert.pem" -extfile extfile.cnf

fi



chmod -v 0400 "ca-key.pem" "key.pem" "server-key.pem"

chmod -v 0444 "ca.pem" "server-cert.pem" "cert.pem"



# 打包客户端证书

echo " - 打包客户端证书为 tls-client-certs.tar.gz"

mkdir -p "tls-client-certs"

cp -f "ca.pem" "cert.pem" "key.pem" "tls-client-certs/"

cd "tls-client-certs"

tar zcf "tls-client-certs.tar.gz" *

mv "tls-client-certs.tar.gz" ../

cd ..

rm -rf "tls-client-certs"



# 拷贝服务端证书

mkdir -p /etc/docker/certs.d

cp -f "ca.pem" "server-cert.pem" "server-key.pem" /etc/docker/certs.d/

echo " - 修改 /etc/docker/daemon.json 文件"

if [[ -f /etc/docker/daemon.json ]]; then

grep "/etc/docker/certs.d/server-key.pem" /etc/docker/daemon.json > /dev/null

if [[ ! $? -eq 0 ]]; then

cat >/etc/docker/daemon.json<<EOF

{

"tlsverify": true,

"tlscacert": "/etc/docker/certs.d/ca.pem",

"tlscert": "/etc/docker/certs.d/server-cert.pem",

"tlskey": "/etc/docker/certs.d/server-key.pem",

"hosts": ["tcp://0.0.0.0:2376", "unix:///var/run/docker.sock"]

}

EOF

fi

else

cat >/etc/docker/daemon.json<<EOF

{

"tlsverify": true,

"tlscacert": "/etc/docker/certs.d/ca.pem",

"tlscert": "/etc/docker/certs.d/server-cert.pem",

"tlskey": "/etc/docker/certs.d/server-key.pem",

"hosts": ["tcp://0.0.0.0:2376", "unix:///var/run/docker.sock"]

}

EOF

fi

# 覆盖启动参数,解决 docker 启动失败

if [[ ! -z $(command -v systemctl) ]];then

mkdir -p /etc/systemd/system/docker.service.d

if [[ ! -f /etc/systemd/system/docker.service.d/override.conf ]]; then

cat >/etc/systemd/system/docker.service.d/override.conf<<EOF

[Service]

ExecStart=

ExecStart=/usr/bin/dockerd

EOF

systemctl daemon-reload

fi

fi

# 清理

rm -vf client.csr server.csr extfile.cnf ca.srl server-cert.pem server-key.pem cert.pem

# 启动 docker

service docker start

# 客户端远程连接

echo "Connect to server via docker-cli:"

echo "docker -H $IP:2376 --tlsverify --tlscacert ~/.docker/ca.pem --tlscert ~/.docker/cert.pem --tlskey ~/.docker/key.pem ps -a"



# 客户端使用 cURL 连接

echo "Connect to server via curl:"

echo "curl --cacert ~/.docker/ca.pem --cert ~/.docker/cert.pem --key ~/.docker/key.pem https://$IP:2376/containers/json"



echo -e "\e[1;32mAll be done.\e[0m"



[root@VM-0-7-centos ~]# tee /etc/docker/daemon.json <<-'EOF'
> {
> "registry-mirrors": ["https://ff07df3q.mirror.aliyuncs.com"]
> }
> EOF
{
"registry-mirrors": ["https://ff07df3q.mirror.aliyuncs.com"]
}
[root@VM-0-7-centos ~]# systemctl daemon-reload
[root@VM-0-7-centos ~]# systemctl restart docker
[root@VM-0-7-centos ~]# ls
get-docker.sh
[root@VM-0-7-centos ~]# vim #!/bin/bash
 
[root@VM-0-7-centos ~]# vim gen.sh
[root@VM-0-7-centos ~]# chmod +x gen.sh
[root@VM-0-7-centos ~]# ./gen.sh 
Redirecting to /bin/systemctl stop docker.service
Warning: Stopping docker.service, but it can still be activated by:
  docker.socket
 - 生成 CA 密钥
Generating RSA private key, 4096 bit long modulus
.....................................................................................................................................................................++
..................................................++
e is 65537 (0x10001)
 - 生成 CA
No value provided for Subject Attribute L, skipped
 - 生成服务器密钥
Generating RSA private key, 4096 bit long modulus
...........++
.........................................................................................++
e is 65537 (0x10001)
 - 生成服务器证书
Signature ok
subject=/CN=129.28.194.191
Getting CA Private Key
Generating RSA private key, 4096 bit long modulus
...++
................................................................................................++
e is 65537 (0x10001)
Signature ok
subject=/CN=client
Getting CA Private Key
mode of ‘ca-key.pem’ changed from 0644 (rw-r--r--) to 0400 (r--------)
mode of ‘key.pem’ changed from 0644 (rw-r--r--) to 0400 (r--------)
mode of ‘server-key.pem’ changed from 0644 (rw-r--r--) to 0400 (r--------)
mode of ‘ca.pem’ changed from 0644 (rw-r--r--) to 0444 (r--r--r--)
mode of ‘server-cert.pem’ changed from 0644 (rw-r--r--) to 0444 (r--r--r--)
mode of ‘cert.pem’ changed from 0644 (rw-r--r--) to 0444 (r--r--r--)
 - 打包客户端证书为 tls-client-certs.tar.gz
 - 修改 /etc/docker/daemon.json 文件
removed ‘client.csr’
removed ‘server.csr’
removed ‘extfile.cnf’
removed ‘ca.srl’
removed ‘server-cert.pem’
removed ‘server-key.pem’
removed ‘cert.pem’
Redirecting to /bin/systemctl start docker.service
Connect to server via docker-cli:
docker -H <your vps ip>:2376 --tlsverify --tlscacert ~/.docker/ca.pem --tlscert ~/.docker/cert.pem --tlskey ~/.docker/key.pem ps -a
Connect to server via curl:
curl --cacert ~/.docker/ca.pem --cert ~/.docker/cert.pem --key ~/.docker/key.pem https://<your vps ip>:2376/containers/json

生成的证书位于 ~/.docker/tls-client-certs.tar.gz下,通过 rsync 取回

rsync -avv 47:/root/.docker/tls-client-certs.tar.gz /Users/pan/cert

通过证书控制远程docker

docker -H your-vps-ip:2376 --tlsverify --tlscacert ./ca.pem --tlscert ./cert.pem --tlskey ./key.pem ps -a