
1. 自签 *.docker.io 域名证书
1.1 创建 CA 证书
| 1
 | openssl genrsa -out ca.key 4096
 | 
| 1
2
3
4
 | openssl req -x509 -new -nodes -sha512 -days 3650 
    -subj "/C=CN/ST=Beijing/L=Beijing/O=example/OU=Personal/CN=chenshaowen.com" 
    -key ca.key 
    -out ca.crt
 | 
1.2 创建 *.docker.io 域名证书
| 1
 | openssl genrsa -out docker.io.key 4096
 | 
| 1
2
3
4
 | openssl req -sha512 -new 
    -subj "/C=CN/ST=Beijing/L=Beijing/O=example/OU=Personal/CN=*.docker.io" 
    -key docker.io.key 
    -out docker.io.csr
 | 
|  1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
 | cat > v3.ext <<-EOF
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names
[alt_names]
DNS.1=docker.io
DNS.2=*.docker.io
EOF
 | 
| 1
2
3
4
5
 | openssl x509 -req -sha512 -days 3650 
    -extfile v3.ext 
    -CA ca.crt -CAkey ca.key -CAcreateserial 
    -in docker.io.csr 
    -out docker.io.crt
 | 
1.3 查看生成的全部文件
| 1
2
3
 | ls
ca.crt         ca.key         ca.srl         docker.io.cert docker.io.crt  docker.io.csr  docker.io.key  v3.ext
 | 
2. 部署 Registry 并配置 HTTPS 证书
2.1 部署 Nginx 代理转发 HTTPS 流量
这里配置一个 Nginx 卸载 HTTPS 证书,用于转发 *.docker.io 域名的请求到 Registry。参考:https://github.com/shaowenchen/docker-compose/tree/main/nginx需要使用到上面生成的证书文件: docker.io.crt,docker.io.key。
2.2 部署 Docker.io 的代理 Registry
| 1
2
 | mkdir mirror
cd mirror
 | 
|  1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
 | version: 0.1
log:
  fields:
    service: registry
storage:
  cache:
    blobdescriptor: inmemory
  filesystem:
    rootdirectory: /var/lib/registry
http:
  addr: :5000
  headers:
    X-Content-Type-Options: [nosniff]
health:
  storagedriver:
    enabled: true
    interval: 10s
    threshold: 3
proxy:
  remoteurl: https://registry-1.docker.io
 | 
| 1
2
3
4
 | docker run -d -p 5000:5000 --restart=always --name mirror 
             -v `pwd`/config.yml:/etc/docker/registry/config.yml 
             -v `pwd`/data:/var/lib/registry 
             registry:2
 | 
2.3 部署私有仓库的 Registry
| 1
2
 | mkdir harbor-mirror
cd harbor-mirror
 | 
|  1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
 | version: 0.1
log:
  fields:
    service: registry
storage:
  cache:
    blobdescriptor: inmemory
  filesystem:
    rootdirectory: /var/lib/registry
http:
  addr: :5000
  headers:
    X-Content-Type-Options: [nosniff]
health:
  storagedriver:
    enabled: true
    interval: 10s
    threshold: 3
proxy:
  remoteurl: https://private.chenshaowen.com
  username: [username]
  password: [password]
 | 
这里的 [username]、[password] 需要替换为私有仓库的凭证。
| 1
2
3
4
 | docker run -d -p 5002:5000 --restart=always --name harbor-mirror 
             -v `pwd`/config.yml:/etc/docker/registry/config.yml 
             -v `pwd`/data:/var/lib/registry 
             registry:2
 | 
3. 给访问镜像仓库的主机添加证书
这里直接将 ca.crt 添加到受到信任证书链,以此 CA 证书签发的域名证书都将被信任。当然,你也可以一个一个地将自签发的证书添加到信任列表。这里将 ca.crt 重命名,以方便识别和区分:
| 1
 | cp ca.crt chenshaowen.com.ca.crt
 | 
3.1 Ubuntu 系统
| 1
2
 | cp chenshaowen.com.ca.crt /usr/local/share/ca-certificates
update-ca-certificates
 | 
| 1
2
 | rm -f /usr/local/share/ca-certificates/chenshaowen.com.ca.crt
update-ca-certificates
 | 
3.2 CentOS 系统
| 1
 | cp chenshaowen.com.ca.crt /etc/pki/ca-trust/source/anchors/
 | 
| 1
 | update-ca-trust extract
 | 
| 1
2
3
 | rm /etc/pki/ca-trust/source/anchors/chenshaowen.com.ca.crt
update-ca-trust extract
 | 
3.3 需要重启 Docker,才会重新加载根证书
| 1
 | systemctl restart docker 
 | 
4. 测试验证
这里将设 Nginx 代理的主机 IP 为 1.1.1.1,那么在访问镜像的主机上都需要加上解析或者配置 /etc/hosts:
| 1
2
 | 1.1.1.1 docker.io
1.1.1.1 registry-1.docker.io
 | 
并且测试主机应该信任 ca.crt 或者 docker.io.crt 证书。
4.1 代理 docker.io 流量
此时,将 Nginx 的流量代理到 5000 端口,也就是直接访问 dockerhub 上的镜像。
| 1
 | docker pull jenkins/jenkins
 | 
能够拉取成功
| 1
2
3
 | du -sh  data/
169M	data/
 | 
4.2 代理私有镜像仓库流量
修改 Nginx 配置,将后端流量切换到私有镜像仓库的 5002 端口,此时后端对接的是私有 Harbor 镜像仓库。
如果直接访问私有镜像仓库,那么地址应该是 private.chenshaowen.com/okscloud/test:develop ,但是这里我们可以直接去掉域名前缀拉取镜像:
| 1
 | docker pull okscloud/test:develop
 | 
可以拉取成功,此时的 docker.io 指向的是 Registry ,最终被代理到 private.chenshaowen.com。
| 1
2
3
 | du -sh /diskb/harbor-mirror
676M	/diskb/harbor-mirror
 | 
5. 总结
本文主要是验证了一个想法,在内网通过修改 docker.io 的解析指向 Registry 代理,劫持 dockerhub 的镜像流量。这种劫持的意义在于:
- 审计内网对 dockerhub 的镜像依赖
- 更好的镜像加速,利用 Dragonfly 等
- 摆脱国内 docker.io 访问限速、不稳定的困扰