Docker securely opens remote access connection permissions

1. Docker fully opens remote access

The Docker service is fully open to external access and the operations are as follows:

# 开启端口命令  (--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

If the following information appears, it means that the remote access settings of the Docker service have been modified successfully.
Insert image description here
Special points to note: Fully opening Docker's external access rights may be attacked by others. This is very unsafe. As long as others know your server address, they can connect to your Docker service at will without any authentication. Therefore, Fully open is only recommended for use on your own intranet, and is not recommended for full openness directly on the cloud server.

2. Docker opens remote access and enables authentication and communication encryption.

In order to solve the above security risks caused by Docker's fully open remote access, we need to perform communication authentication and encryption on the Docker service. The operation is as follows: First,
create a file directory to store certificates and private keys.

mkdir -p /data/certificate/linux-ca && cd /data/certificate/linux-ca

Then perform the following operations under the linux-ca folder:

  1. Generate a self-signed root certificate and private key:
    Execute the following command to generate a root certificate private key file (for example ca-key.pem):
    openssl genrsa -aes256 -passout pass:123456 -out ca-key.pem 4096
    
    b. Execute the following command to generate a root certificate file (for example ca.pem) and sign it with the private key. When you generate a certificate, you assign it a validity period, usually a few years.
    # 直接指定证书的主题信息
    openssl req -x509 -new -key ca-key.pem -sha256 -days 365 -passin pass:123456 -out ca.pem
    
  2. Generate a self-signed server certificate and private key:
    a. Execute the following command to generate a private key file (for example server-key.pem):
    openssl genrsa -out server-key.pem 4096
    
    b. Execute the following command to generate a certificate signing request file (for example server.csr).
    When generating a CSR file, you need to provide some information, such as organization name, organizational unit, country, etc.
    # 直接指定证书的主题信息
    openssl req -new -key server-key.pem -out server.csr
    
    c. Execute the following command to generate a self-signed server certificate (for example server-cert.pem) and sign it with the CSR file and private key.
    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
    
  3. Generate a self-signed client certificate and private key:
    a. Execute the following command to generate a client private key file (for example key.pem):
    openssl genrsa -out key.pem 4096
    
    b. Execute the following command to generate a client certificate signing request file (for example client.csr). When generating a CSR file, you need to provide some information, such as organization name, organizational unit, country, etc.
    openssl req -new -key key.pem -out client.csr
    
    c. Execute the following command to generate a self-signed client certificate (for example cert.pem) and sign it with the CSR file and private key. When you generate a certificate, you assign it a validity period, usually a few years.
    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
    

Delete the four redundant request files:

rm -f server.csr client.csr extfile-server.cnf extfile-client.cnf

After completing the above steps, you will get the following files:

  • Root certificate file:ca.pem
  • Root certificate private key file:ca-key.pem
  • Server-side certificate file:server-cert.pem
  • Server-side private key file:server-key.pem
  • Client certificate file:cert.pem
  • Client private key file:key.pem

Special attention should be paid to the following four points:
4. The root certificate name must be ca.pem
5. The client certificate must be cert.pem
6. The client private key must be key.pem
7. The server must be added when entering the commonName information IP address, otherwise Docker may fail to start.
8. When the server and client create private keys, you cannot add an additional encryption password, otherwise the server and client will not be able to parse it.

Then configure the Docker daemon configuration file daemon.json. The specific operations are as follows:

# 先查看 /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

In the above operation, we need to fill in the correct certificate and private key storage address. If you follow my steps above, there is no problem and you don’t need to change anything. If the storage address of your certificate and private key is a self-defined address, then you need to modify the address in daemon.json accordingly.
After completing the above content, we cannot obtain information when using https://192.168.56.10:2375/version in the browser, prompting that identity authentication is required.
Insert image description here

3. Quickly complete Docker service activation authentication and communication encryption

In order to solve the problem of the cumbersome process in the second step, I wrote two automated configuration Shell scripts and uploaded them to the public network. They can help us complete all the processes in the second step very quickly. You can choose to use me directly
. The created script operates as follows:

# 证书脚本
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

If you create it yourself and then use it, you can refer to the following steps. The specific operations are as follows:

3.1 First is the Shell script to create the certificate and private key

We only need to create a cert.sh script file with any name, and then fill in the following content:

#!/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 = [email protected]

[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 = [email protected]

[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

This script only requires us to enter three parameters in the console: the storage address of the certificate and private key, the root private key password, and the server IP address . There is nothing else to do.
If you follow the above steps to create the cert.sh script file and fill in the script content, then we can execute the script through the following command

source /xxx/cert.sh

Use the source command followed by the absolute address or relative address of the script to execute the script.

3.2 Create Docker daemon configuration script

We create a daemon.sh script file with any name, and then fill in the following content:

#!/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

Then we can execute the script through the source command followed by the absolute address or relative address of the script.

source /xxx/daemon.sh

This script mainly performs three settings: communication encryption, service authentication, and image acceleration configuration for the Docker service. The usage method is the same as the previous script. During the execution of the script, we will be prompted to enter the storage address of the previously created certificate and private key. We must fill in the correct address, otherwise the Docker service will not be able to read the certificate and private key.

4. IDEA connects to Docker service

Download the certificate folder to Windows locally.
You only need these three files: ca.pem, cert.pem, key.pem. Download them locally and load them into a folder. In the
Insert image description here
specific IDEA configuration, you can follow the following Steps to set up:

  1. Open IDEA and enter Settings.
  2. Navigate to the Docker section (usually Docker under Build, Execution, Deployment).
  3. Find the TCP socket configuration options below Connect to Docker daemon with configuration
  4. Fill in the Docker service connection address in the Engine API URL, for example: https://192.168.56.10:2375
  5. Select the folder containing three certificate files in the Certificates folder to authenticate the client to the server.
  6. Save the settings and try to connect to the Docker service.
    Insert image description here
    It should be noted that the specific setting steps may vary depending on the version of IDEA. Please make appropriate adjustments according to the version you are using.

5. Maven connects Docker service

Sometimes we need to configure our own project to configure the connection configuration of the Docker service to facilitate quick project packaging and deployment in Docker. Therefore, we need the following configuration:

        <!-- 项目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>

Because the configuration is too long, I only selected the key parts to display. If you want to configure the full configuration, you can leave me a message or send me a private message.
If you think my blog is good, don’t forget to like and favorite it. It would be even better if you can also comment and communicate! ! !

Guess you like

Origin blog.csdn.net/python15397/article/details/131649168