一、前言
最近一段时间学习了Docker相关的知识(内容参考:Jmeter+influxdb+Grafana+Docker 初步实践),但是没过多久云服务器就被攻击了。原因就是docker的2375端口被攻击,导致服务器宕机不能使用了。
二、Docker配置TLS
1、创建证书生成脚本 createcert.sh,放置/opt/sh目录
mkdir -p /opt/sh /opt/cert/docker
touch /opt/sh/createcert.sh
vim /opt/sh/createcert.sh
在createcret.sh添加内容
#!/bin/bash
set -e
if [ -z $1 ];then
echo "请输入Docker服务器外网IP"
exit 0
fi
HOST=$1
# 创建/opt/cert/docker多级目录
mkdir -p /opt/cert/docker
# 进入/opt/cert/docker文件
cd /opt/cert/docker
# 使用OpenSSL生成 CA 私钥,这里会输入一个密码,请记住后面会一直用到
openssl genrsa -aes256 -out ca-key.pem 4096
# 再次输入刚刚的密码、国家、省、市、组织、单位、名称、邮箱。(密码要求和之前的一致,其他的可以随便填)
openssl req -new -x509 -days 365 -key ca-key.pem -sha256 -out ca.pem
# 使用OpenSSL生成公钥文件
openssl genrsa -out server-key.pem 4096
# 这个/CN=后面的$HOST可以不用动,因为脚本上的$1就是替换这个字段的(到时候填写docker所在主机的域名或者IP地址)。
openssl req -subj "/CN=$HOST" -sha256 -new -key server-key.pem -out server.csr
# 使用 CA 签署公钥,配置白名单,推荐配置0.0.0.0,允许所有IP连接但只有证书才可以连接成功(这里请记住,如果有域名才使用DNS,否则请使用IP,我没有域名只填写IP,且第一个为服务器外网的IP)
# echo subjectAltName = DNS:$HOST,IP:0.0.0.0 > extfile.cnf
echo subjectAltName = IP:$HOST,IP:0.0.0.0 > extfile.cnf
# 将 Docker 守护程序密钥的扩展使用属性设置为仅用于服务器身份验证:
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
# 创建客户端的密钥
openssl genrsa -out key.pem 4096
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 -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out cert.pem -extfile extfile.cnf
# 删除两个证书签名请求和扩展配置文件
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
2、执行 createcert.sh 脚本,生成证书放置 /opt/cert/docker(脚本里面有写好,不用单独跳转) 目录中
# $host为服务器外网的IP地址
sh /opt/sh/createcert.sh $HOST
3、按照提示输入相关信息,密码一致,其他信息可留空,等脚本指定完成之后,可在 /opt/cert/docker 目录查看到生成的证书。
4、 进入/opt/cert/docker,将
# 备注:删除多余文件后,该目录下剩余:
# ca.pem CA机构证书
# ca.srl
# ca-key.pem 根证书RSA私钥
# cert.pem 客户端证书
# key.pem 客户私钥
# server-cert.pem 服务端证书
# server-key.pem 服务端私钥
# 进入/opt/cert/docker
cd /opt/cert/docker
# 让 Docker daemon只接受来自提供 CA 信任的证书的客户端的连接
# 把dockerd要用到的文件找个地方单独存放:
cp {ca,server-*}.pem /etc/docker/
5、修改Docker的端口和重新启动方法第一弹:
①修改daemon.json的配置
vim /etc/docker/daemon.json
修改一下几个配置(注意:基于 TLS 的 Docker 应该在 TCP 端口 2376 上运行,idea支持的模式是TCP Socket)
{
"hosts": [
"fd://",
"unix:///var/run/docker.sock",
"tcp://0.0.0.0:2376"
],
"tlsverify": true,
"tlscacert": "/etc/docker/ca.pem",
"tlscert": "/etc/docker/server-cert.pem",
"tlskey": "/etc/docker/server-key.pem"
}
②同时需要去除/lib/systemd/system/docker.service文件中ExecStart里全部的-H
选项,因为命令行选项的优先级高于daemon.json配置文件(PS:记得在修改前先备份一个docker.service)。
③重启docker
# 因为修改了daemon.json,需要重启daemon程序
systemctl daemon-reload
# 重启docker daemon服务
systemctl restart docker.service
# 查看服务运行情况,可以使用docker ps
docker ps
# 查看2376端口运行情况
netstat -nltp | grep 2376
6.修改Docker的端口和重新启动方法第二弹:
① 直接修改/usr/lib/systemd/system/docker.service的docker.service,不需要修改daemon.json
# 在根目录下编辑/usr/lib/systemd/system/docker.service
vim /usr/lib/systemd/system/docker.service
修改ExecStart,将原本的ExecStart进行注释,然后加入一下指令
ExecStart=/usr/bin/dockerd -H fd:// -H unix:///var/run/docker.sock --containerd=/run/containerd/containerd.sock \
--tlsverify --tlscacert=/etc/docker/ca.pem \
--tlscert=/etc/docker/server-cert.pem \
--tlskey=/etc/docker/server-key.pem \
-H tcp://0.0.0.0:2376
②重启daemon和docker
# 因为修改了daemon.json,需要重启daemon程序
systemctl daemon-reload
# 重启docker daemon服务
systemctl restart docker.service
# 查看服务运行情况,可以使用docker ps
docker ps
# 查看2376端口运行情况
netstat -nltp | grep 2376
三、idea链接Docker
1、将客户端密钥和签名证书拉取到客户端
1.1 可以通过ssh工具进行拖拽复制(在用户里面下创建C:\Users\123\.ca\docker目录)
1.2 使用scp命令拉取服务器上的客户端秘钥和签名证书:
# win+R 使用终端命令下使用以下命令,$HOST为远程服务器的域名或者IP地址
# 注意:需要注意.ca/docker内不能有.pem文件
C:\Users\xxx> scp root@$HOST:/opt/cert/docker/{ca,cert,key}.pem ./.ca/docker
2、idea链接docker。
File-->settings-->Docker-->点击【+】-->选择TCP socket,
Engine API URL:https://$host:2376
Certificates folder:C:\Users\123\.ca\docker (上面创建的.ca/docker目录地址)
如果下发显示:Connection successful就代表链接成功
四、FAQ
1、官网上使用CA 对公钥进行签名,说的是使用DNS和IP。导致idea链接docker提示:Cannot connect: com.intellij.dockeragent,ApiTaskException:javax.net.ssl.SSLPeerUnverifiedException: Certificate for 116.62.145.20 doesn't match any of thesubject alternative names: [x.x.x.x,0.0.0.0]
解决办法:需要根据实际上的host是DNS域名还是IP来决定。host是域名那就需要加上DNS:$HOST,否则就是IP:$HOST
借鉴大神的文章:
1、docker+idea+TLS:docker开启TLS保护的安全远程连接,idea远程连接docker
2、Docker实战 | 第四篇:Docker启用TLS加密解决暴露2375端口引发的安全漏洞,被黑掉三台云主机的教训总结
3、docker 无法访问 镜像运行成功 docker 2375 无法访问
以上排名不分先后