Docker安全开放远程访问连接权限方式
作者:龙茶清欢
1、Docker完全开放远程访问
Docker服务完全开放对外访问权限操作如下:
# 开启端口命令 (--permanent永久生效,没有此参数重启后失效) firewall-cmd --zone=public --add-port=2375/tcp --permanent # 重新载入 firewall-cmd --reload # 使用 vim 编辑docker服务配置文件 vim /lib/systemd/system/docker.service # 找到如下配置行 ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock # 将其注释掉或者直接删除,替换成下面的配置行.然后保存退出 ExecStart=/usr/bin/dockerd -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock # 重新加载docker配置并重启服务 systemctl daemon-reload && systemctl restart docker # 然后直接在命令行客户端输入如下命令,IP地址改为自己的 curl http://192.168.56.20:2375/version # 或者在浏览器直接访问,IP地址改为自己的 http://192.168.56.20:2375/version
出现如下信息则代表修改Docker服务设置远程访问成功。
特别注意的点:
完全开放Docker对外访问权限有可能会遭到别人攻击,这是很不安全的,只要别人知道你的服务器地址就能够随意连接你的Docker服务,而不需要任何认证,因此,完全开放只推荐自己在内网使用,不推荐在云服务器上直接完全开放。
2、Docker开放远程访问并开启认证和通信加密
为了解决上面Docker完全开放远程访问所带来的安全隐患,我们需要对Docker服务进行通信认证和加密,操作如下:
首先创建一个文件目录,用于存放证书和私钥
mkdir -p /data/certificate/linux-ca && cd /data/certificate/linux-ca
然后在 linux-ca 文件夹下进行以下操作:
生成自签名的根证书和私钥
- a. 执行以下命令生成根证书私钥文件(例如
ca-key.pem
):
openssl genrsa -aes256 -passout pass:123456 -out ca-key.pem 4096
- b. 执行以下命令生成根证书文件(例如
ca.pem
)并使用私钥进行签名。在生成证书时,你需要为其分配一个有效期,通常为几年。
# 直接指定证书的主题信息 openssl req -x509 -new -key ca-key.pem -sha256 -days 365 -passin pass:123456 -out ca.pem
生成自签名的服务端证书和私钥
- a. 执行以下命令生成私钥文件(例如
server-key.pem
):
openssl genrsa -out server-key.pem 4096
- b. 执行以下命令生成证书签名请求文件(例如
server.csr
)。
在生成 CSR 文件时,你需要提供一些信息,如组织名称、组织单位、所在国家等。
# 直接指定证书的主题信息 openssl req -new -key server-key.pem -out server.csr
- c. 执行以下命令生成自签名的服务器证书(例如
server-cert.pem
),并使用 CSR 文件和私钥进行签名。
echo extendedKeyUsage = serverAuth >> extfile-server.cnf openssl x509 -req -in server.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -days 365 -sha256 -passin pass:123456 -out server-cert.pem -extfile extfile-server.cnf
生成自签名的客户端证书和私钥
- a. 执行以下命令生成客户端私钥文件(例如
key.pem
):
openssl genrsa -out key.pem 4096
- b. 执行以下命令生成客户端证书签名请求文件(例如
client.csr
)。在生成 CSR 文件时,你需要提供一些信息,如组织名称、组织单位、所在国家等。
openssl req -new -key key.pem -out client.csr
- c. 执行以下命令生成自签名的客户端证书(例如
cert.pem
),并使用 CSR 文件和私钥进行签名。在生成证书时,你需要为其分配一个有效期,通常为几年。
echo extendedKeyUsage = clientAuth > extfile-client.cnf openssl x509 -req -in client.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -days 365 -sha256 -passin pass:123456 -out cert.pem -extfile extfile-client.cnf
删除多余的四个请求文件:
rm -f server.csr client.csr extfile-server.cnf extfile-client.cnf
完成了上述步骤后,你将获得以下文件:
- 根证书文件:
ca.pem
- 根证书私钥文件:
ca-key.pem
- 服务器端证书文件:
server-cert.pem
- 服务器端私钥文件:
server-key.pem
- 客户端证书文件:
cert.pem
- 客户端私钥文件:
key.pem
特别要注意的是以下四点:
- 根证书名称必须为 ca.pem
- 客户端证书必须为 cert.pem
- 客户端私钥必须为 key.pem
- 在输入 commonName 信息时必须添加服务器的IP地址,否则Docker可能启动失败
服务端和客户端创建私钥是不能额外添加加密密码,不然会导致服务端、客户端无法解析。
然后是配置Docker守护进程配置文件 daemon.json 具体操作如下:
# 先查看 /etc/docker/daemon.json 是否存在,如果不存在则创建,存在则直接修改 cat /etc/docker/daemon.json mkdir -p /etc/docker tee /etc/docker/daemon.json <<-'EOF' { "tls": true, "tlsverify": true, "tlscacert": "/data/certificate/linux-ca/ca.pem", "tlscert": "/data/certificate/linux-ca/server-cert.pem", "tlskey": "/data/certificate/linux-ca/server-key.pem", "registry-mirrors": [ "http://hub-mirror.c.163.com", "https://ung2thfc.mirror.aliyuncs.com", "https://mirror.ccs.tencentyun.com", "https://registry.docker-cn.com", "https://docker.mirrors.ustc.edu.cn", "https://mirror.baidubce.com" ] } EOF systemctl daemon-reload && systemctl restart docker
在以上操作中,我们需要填写正确的证书和私钥存放地址,如果你是按照我上面的步骤来,那没有问题,你什么都不用改。
如果你的证书和私钥的存放地址是自己定义的地址,那么,你需要将 daemon.json 中的地址也相应的修改一下。
完成以上内容后,此时我们在浏览器使用 https://192.168.56.10:2375/version 就无法获取信息了,提示需要身份认证
3、快速完成Docker服务开启认证和通信加密
为了解决第二步流程比较繁琐的问题,我编写了两个自动化配置Shell脚本并且我将其上传到了公网,它们能够帮助我们非常快速的完成第二步的所有流程,
你们可以直接选择使用我创建好的脚本,操作如下:
# 证书脚本 curl -O https://backup-1305596318.cos.ap-guangzhou.myqcloud.com/shell/cert.sh chmod +x cert.sh source cert.sh # Docker守护进程脚本 curl -O https://backup-1305596318.cos.ap-guangzhou.myqcloud.com/shell/daemon.sh chmod +x daemon.sh source daemon.sh
如果自己创建然后使用,可以参考下面的步骤,具体操作如下:
首先是创建证书和私钥的Shell脚本
我们只需要创建一个 cert.sh 脚本文件,名称可以任取,然后填入如下内容:
#!/bin/bash # 从控制台读取必要输入信息 read -p "please input the cert store path: " certDir echo your cert store path is: "$certDir" read -p "please input the ca-key's password: " password echo your password is: "$password" read -p "please input the IP of your server: " ip echo your server IP is: "$ip" # 检查输入的证书路径是否已经存在 # 如果不存在,则创建;如果存在则删除后创建 if [ ! -d "$certDir" ]; then echo "" echo "$certDir , not exist, it will be create" echo "" mkdir -p $certDir else echo "" echo "$certDir , already exist , it will be delete then create" echo "" rm -rf $certDir mkdir -p $certDir fi cd $certDir # 定义服务端证书扩展配置 server_conf="[req] prompt = no distinguished_name = req_distinguished_name req_extensions = v3_req [req_distinguished_name] countryName = CN stateOrProvinceName = JX localityName = SR organizationName = PY organizationalUnitName = XS commonName = $ip emailAddress = 2320391937@qq.com [v3_req] extendedKeyUsage = serverAuth subjectAltName = @alt_names [alt_names] IP.1 = 0.0.0.0" # 将服务端证书的扩展配置写入extfile-server.cnf文件 echo "$server_conf" > extfile-server.cnf # 定义客户端证书扩展配置 client_conf="[req] prompt = no distinguished_name = req_distinguished_name req_extensions = v3_req [req_distinguished_name] countryName = CN stateOrProvinceName = JX localityName = SR organizationName = PY organizationalUnitName = XS commonName = $ip emailAddress = 2320391937@qq.com [v3_req] extendedKeyUsage = clientAuth" # 将客户端证书的扩展配置写入extfile-client.cnf文件 echo "$client_conf" > extfile-client.cnf # 创建根证书RSA私钥 openssl genrsa -aes256 -passout pass:$password -out ca-key.pem 4096 # 创建CA证书 openssl req -new -x509 -days 365 -key ca-key.pem -passin pass:$password -sha256 -out ca.pem -subj "/C=CN/CN=$ip" # 创建服务端私钥 openssl genrsa -out server-key.pem 4096 # 创建服务端签名请求证书文件 openssl req -subj "/CN=$ip" -sha256 -new -key server-key.pem -out server.csr # 创建签名生效的服务端证书文件 openssl x509 -req -days 365 -sha256 -in server.csr -CA ca.pem -CAkey ca-key.pem -passin "pass:$password" -CAcreateserial -out server-cert.pem -extfile extfile-server.cnf # 创建客户端私钥 openssl genrsa -out key.pem 4096 # 创建客户端签名请求证书文件 openssl req -subj "/CN=$ip" -new -key key.pem -out client.csr # 创建签名生效的客户端证书文件 openssl x509 -req -days 365 -sha256 -in client.csr -CA ca.pem -CAkey ca-key.pem -passin "pass:$password" -CAcreateserial -out cert.pem -extfile extfile-client.cnf # 删除多余文件 # 使用了 -v 参数,rm 命令将会显示每个被删除的文件或目录的名称,以便您能够看到操作的进展和结果。 rm -f -v client.csr server.csr extfile-server.cnf extfile-client.cnf # 为所有用户设置对这些文件的读取权限 chmod -v 444 ca-key.pem key.pem server-key.pem chmod -v 444 ca.pem server-cert.pem cert.pem
该脚本只需要我们在控制台输入证书和私钥的存放地址、根私钥密码以及服务器IP地址三个参数即可,其他的什么都不用做。
如果你按照上面的步骤创建好了 cert.sh 脚本文件并填入了脚本内容,那么接下来我们就可以通过如下命令来执行脚本了
source /xxx/cert.sh
使用 source 命令后接脚本的绝对地址或者相对地址即可执行脚本。
创建Docker守护进程配置脚本
我们创建一个 daemon.sh 脚本文件,名称可以任取,然后填入如下内容:
#!/bin/bash # 读取控制台输入,需要输入一个目录 read -p "please input the cert store path: " certDir echo your cert store path is: "$certDir" # 检查输入的证书路径是否已经存在 # 如果不存在,则直接退出 if [ ! -d "$certDir" ]; then echo "" echo "$certDir , not exist, please input a correct cert path" exit fi json_content='{ "tls": true, "tlsverify": true, "tlscacert": "$certDir/ca.pem", "tlscert": "$certDir/server-cert.pem", "tlskey": "$certDir/server-key.pem", "registry-mirrors": [ "http://hub-mirror.c.163.com", "https://ung2thfc.mirror.aliyuncs.com", "https://mirror.ccs.tencentyun.com", "https://registry.docker-cn.com", "https://docker.mirrors.ustc.edu.cn", "https://mirror.baidubce.com" ] }' # 替换变量 json_content=$(echo "$json_content" | sed "s|\$certDir|$certDir|g") daemonDir='/etc/docker' # 如果docker配置目录不存在则创建;存在则删除后创建 if [ ! -d "$daemonDir" ]; then echo "" echo "$daemonDir not exist, it will be create" mkdir -p "$daemonDir" && cd "$daemonDir" # 将替换后的内容保存到新的 JSON 文件 echo "$json_content" > "$daemonDir/daemon.json" else echo "" echo "$daemonDir already exist, it will be delete then create" rm -rf "$daemonDir" mkdir -p "$daemonDir" && cd "$daemonDir" # 将替换后的内容保存到新的 JSON 文件 echo "$json_content" > "$daemonDir/daemon.json" fi systemctl daemon-reload && systemctl restart docker
然后我们可以通过 source 命令后接脚本的绝对地址或者相对地址即可执行脚本。
source /xxx/daemon.sh
这个脚本主要是对Docker服务进行通信加密、服务认证、镜像加速配置这三个设置,使用方式和上一个脚本一样。
在执行脚本的过程中,会提示我们输入之前创建的证书和私钥的存放地址,我们必须填写正确的地址,否则会导致Docker服务无法读取证书和私钥。
4、IDEA连接Docker服务
下载证书文件夹到Windows本地,
只需要这三个文件即可:ca.pem、cert.pem、key.pem 将他们下载到本地并装入一个文件夹中
在具体的 IDEA 配置中,可以按照以下步骤进行设置:
- 打开 IDEA,进入 Settings 。
- 导航到 Docker 部分(一般是 Build, Execution, Deployment 下的 Docker)。
- 找到 Connect to Docker daemon with 配置下面的 TCP socket 配置选项
- 在 Engine API URL 中填入Docker服务连接地址,例如:https://192.168.56.10:2375
- 在 Certificates folder 中选择装有三个证书文件的文件夹,用以客户端向服务端的身份认证
- 保存设置并尝试连接到 Docker 服务。
需要注意的是,具体的设置步骤可能因 IDEA 版本而异,请根据你使用的版本进行适当调整。
5、Maven连接Docker服务
有时候我们需要让自己的项目配置Docker服务的连接配置,以方便快速进行项目打包并部署在Docker中,因此,我们需要如下配置:
<!-- 项目maven插件统一管理 --> <pluginManagement> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>${maven-compiler.version}</version> <configuration> <source>${java.version}</source> <target>${java.version}</target> <encoding>${project.build.sourceEncoding}</encoding> </configuration> </plugin> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>${spring-boot.version}</version> </plugin> <!-- docker插件,用于制作镜像 --> <plugin> <groupId>com.spotify</groupId> <artifactId>docker-maven-plugin</artifactId> <version>${docker-maven.version}</version> <!-- docker配置 --> <configuration> <!-- docker远程地址 --> <dockerHost>${docker.host}</dockerHost> <!-- docker打包镜像名称 --> <imageName>${docker.image.prefix}/${project.artifactId}:${project.version}</imageName> <!-- DockerFile的存放位置 --> <dockerDirectory>${project.basedir}</dockerDirectory> <!-- 由于docker服务使用加密通信,开启了认证,因此需要提供通信证书 --> <dockerCertPath>C:\Users\23203\Desktop\linux-ca</dockerCertPath> <!-- 配置制作镜像时需要依赖的资源,此处依赖项目jar包 --> <resources> <resource> <targetPath>/</targetPath> <directory>${project.build.directory}</directory> <include>${project.build.finalName}.jar</include> </resource> </resources> </configuration> </plugin> </plugins> </pluginManagement>
因为配置过长,我只选取关键的部分展示。
总结
以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。