本文说明 Docker Image Proxy 的源站保护、Docker Hub 上游认证、CDN/WAF 放行、回源鉴权、限流、密钥管理和排障安全边界。
生产环境至少达到以下目标:
- 源站端口不对公网裸奔。
- 只有 CDN、堡垒机、监控或明确测试 IP 能访问源站入口。
- Docker Hub 回源使用专用低权限账号和 Access Token。
- WAF 不破坏 Docker Registry
/v2/协议。 - 不提交真实 IP、SSH 信息、token、
.env、证书私钥。
.env 必填:
REGISTRY_PROXY_USERNAME=replace-with-dockerhub-username
REGISTRY_PROXY_PASSWORD=replace-with-dockerhub-access-token要求:
- 使用专用 Docker Hub 账号。
- 使用 Access Token,不使用个人主账号密码。
- 不要让该账号拥有不必要的私有镜像访问权限。
.env权限保持600。
风险说明:
如果该账号可以访问私有镜像,并且 mirror 对外没有访问控制,mirror 使用者可能通过该 mirror 拉取该账号有权限访问的私有资源。
源站入方向只允许:
TCP 5000 或 TCP 443:
allow CDN 回源 IP 段
allow 运维堡垒机 IP
allow 监控 IP
deny 0.0.0.0/0
安全组优先级高于系统防火墙。不要只依赖容器内 Nginx 拦截。
只允许指定测试服务器公网 IP:
TCP 5000:
allow <国内测试服务器公网 IP>/32
deny 0.0.0.0/0
验证结束后立即恢复:
cd /data/docker-image-proxy
sed -i 's/^PROXY_BIND_ADDR=.*/PROXY_BIND_ADDR=127.0.0.1/' .env
docker compose up -d推荐和安全组二选一或叠加:
| 方式 | 适用场景 |
|---|---|
| CDN 回源 IP 白名单 | CDN 回源 IP 段稳定且可维护 |
| 自定义回源 Header | 源站网关可校验 Header |
| Authenticated Origin Pulls | Cloudflare 场景,源站可校验证书 |
CDN 回源添加:
X-Origin-Auth: replace-with-random-origin-secret
源站 Nginx 校验:
if ($http_x_origin_auth != "replace-with-random-origin-secret") {
return 403;
}仓库内置 Nginx 已提供可切换的 CDN 回源鉴权子配置:
nginx/conf.d/default.conf # 普通入口
nginx/conf.d/cdn-origin-auth.conf # 校验 X-Origin-Auth
启用步骤:
cd /data/docker-image-proxy
cp .env .env.bak.$(date +%F-%H%M%S)
vi nginx/conf.d/cdn-origin-auth.conf
sed -i 's#^NGINX_SERVER_CONF=.*#NGINX_SERVER_CONF=./nginx/conf.d/cdn-origin-auth.conf#' .env
docker compose up -d编辑 nginx/conf.d/cdn-origin-auth.conf 时,把 replace-with-random-origin-secret 替换为自己的真实随机长密钥,并在 CDN 回源 Header 中使用同一个值。
注意:
replace-with-random-origin-secret必须替换为随机长密钥。- 不要把真实回源密钥提交到仓库。
- 如果用
certbotHTTP-01 验证证书,需要放行/.well-known/acme-challenge/,或改用 DNS 验证。 cdn-origin-auth.conf只保护/v2/路径;/healthz和容器内部127.0.0.1健康检查不需要 Header。- 生产仍建议叠加安全组或防火墙,只允许 CDN 回源 IP 访问源站端口。
对 /v2/ 路径:
允许方法:GET、HEAD、OPTIONS
允许请求头:Accept、Authorization、Range、If-Range、User-Agent
允许响应头:Docker-Distribution-API-Version、Content-Length、Accept-Ranges、ETag
允许大文件下载和 Range
跳过:
JS Challenge
Managed Challenge
验证码
浏览器完整性检查
Bot Fight / 机器人挑战
需要 Cookie 的规则
保留:
DDoS 防护
IP 黑名单
基础恶意流量规则
轻量速率限制
如果 Docker pull 返回 HTML、403、验证码页面,优先检查 WAF/Bot 规则。
原则:
- 对
/v2/*/manifests/*可以轻量限流。 - 对
/v2/*/blobs/*不要强限流,否则大镜像层容易下载失败。 - Kubernetes 批量拉镜像时会并发访问,同一出口 IP 可能代表整批节点。
当前内置 Nginx 已对 manifests 做轻量限流:
limit_req_zone $binary_remote_addr zone=manifest_rate:10m rate=20r/s;
limit_conn_zone $binary_remote_addr zone=addr_conn:10m;如果部署在 CDN 后,优先在 CDN 边缘做速率控制,并确保不会误伤镜像层下载。
公开文档只能使用模拟值:
203.0.113.10
mirror.example.com
mirror-origin.example.com
10022
/path/to/id_ed25519
replace-with-dockerhub-username
replace-with-dockerhub-access-token
replace-with-random-origin-secret
禁止提交:
- 真实服务器 IP。
- 真实 SSH 端口。
- SSH 私钥路径和私钥内容。
.env。- Docker Hub 用户名、密码、Access Token。
REGISTRY_HTTP_SECRET。- CDN 回源密钥。
- 证书私钥。
- 云厂商 AccessKey/SecretKey。
提交前建议搜索:
rg -n "REGISTRY_HTTP_SECRET=|REGISTRY_PROXY_PASSWORD=|AKIA|ghp_|github_pat_|BEGIN .*PRIVATE KEY" .源站日志:
cd /data/docker-image-proxy
tail -f logs/nginx/access.log
docker compose logs -f nginx registry重点关注:
大量 401/403/429
异常高频 manifests 请求
单 IP 大量并发 blobs
来自非 CDN IP 的源站访问
WAF 返回 HTML 或挑战页面
CDN 日志重点关注:
命中率
回源流量
4xx/5xx
被 WAF 拦截的 /v2/ 请求
单 IP 或单地域异常拉取
如果怀疑 mirror 被滥用:
- 在 CDN 层临时限制来源 IP 或关闭加速域名。
- 在源站安全组撤销公网临时开放。
- 恢复
PROXY_BIND_ADDR=127.0.0.1。 - 轮换 Docker Hub Access Token。
- 检查 CDN 和源站访问日志。
- 重新按 验证手册 验证后再恢复服务。
如果 Docker Hub 429:
- 确认
.env填写了 Docker Hub 账号/token。 - 确认 token 未过期或被撤销。
- 检查是否有未授权客户端大量拉取。
- 必要时加 CDN 限流、客户端白名单或拆分源站。