避坑指南:自建 Docker 仓库忘了做认证,结果变成了木马窝
最近看到个挺让人后背发凉的案例,有位朋友自建了一个 Docker 私有仓库(Registry),为了省事方便内部拉取,居然全程没开启任何认证机制,直接裸奔在公网(或者是内网但被穿透了)。结果可想而知,不知道被哪个扫描器扫到了,硬生生被人当成了公共仓库,上传了带有木马的镜像。
这事儿虽然听着离谱,但在实际运维小白或者个人测试环境里还真不少见。今天以此为例,咱们来盘一盘这里面到底有多大的坑,以及万一碰上了该怎么救,以后怎么防。
一、 为什么裸奔的 Registry 是黑客的最爱?
很多人觉得,我就随手搭个 Registry 给自己的几台机器用,IP 又不公开,谁会来扫我?大错特错。现在的互联网扫描器是无孔不入的,只要端口开着,不出半天就会被全网测绘收录。
黑客利用未授权的 Docker Registry 通常有两个目的:
公网环境下的服务器时刻面临扫描器的试探,未授权的端口极易被发现。
- 作为恶意软件的“CDN”:把你那高带宽的服务器当成免费的木马分发节点。他们 push 一个充满恶意脚本的镜像进来,然后配置受害者的机器
docker pull 你的IP:端口/恶意镜像。一旦受害者执行了这个容器,机器就被控了。这时候,背锅的是你的 IP 和服务器。 - 投毒你的内部环境:如果黑客能猜到你常用的镜像名称(比如
backend、prod-api),他们可以覆盖掉你原本正常的镜像。当你下次例行部署时,拉取到的就是被植入后门的版本,这招叫“供应链投毒”,防不胜防。
二、 中招后的应急响应:怎么做“尸检”?
如果你发现自己环境里的 Docker Registry 有莫名其妙的镜像,或者拉取量突然暴涨,请立刻按以下步骤操作,别犹豫。
1. 隔离现场,封堵端口
第一时间断网,或者通过防火墙(iptables/ufw/安全组)封掉 Registry 的端口(默认是 5000)。别急着删数据,先切断外部连接,防止黑客继续操作或清除痕迹。
2. 检查镜像清单
Registry 的数据通常存储在 /var/lib/registry/ 目录下。虽然目录结构是一堆哈希值,人类读不懂,但你可以通过 API 查看清单。
在终端执行以下命令(假设 Registry 在本机 5000 端口):
curl -X GET http://localhost:5000/v2/_catalog
这会列出仓库里所有的镜像名。如果你看到了自己没见过的名字(比如 xmr-miner、crypto-base 之类的一看就不对劲的名字),那基本是中招了。
进一步查看某个镜像的 Tag(标签):
curl -X GET http://localhost:5000/v2/镜像名/tags/list
3. 抽检镜像内容(如果还没删)
通过 Nginx 反向代理加 Basic Auth是保护 Docker Registry 最简单有效的方法。
如果你还在内网,可以尝试拉取可疑镜像进行分析。
docker pull localhost:5000/可疑镜像名:latest
拉下来之后,绝对不要直接运行它!使用 docker export 或者 docker cp 把文件系统导出来,看看有没有可疑的二进制文件、篡改过的 authorized_keys 或者挖矿脚本。重点检查 /usr/bin/、/etc/ 和 cron 任务。
三、 解决方案与补救措施
发现问题后,处理逻辑必须清晰:清场 + 加固。
1. 全线清洗
不要相信任何现有的镜像。最安全的做法是直接格式化存储 Registry 数据的磁盘,或者删除整个 /var/lib/registry 目录。然后重新部署 Registry,并从可信源重新 push 你原本需要的镜像。千万不要试图去“清洗”一个可疑的镜像,成本太高且风险无限大。
2. 强制开启认证
这是核心中的核心。自建 Docker Registry 必须开启认证。最简单的方法是使用 Nginx 作为反向代理,配合 htpasswd 进行 Basic Auth 认证。
- 安装工具:
# Debian/Ubuntu apt install apache2-utils # CentOS/RHEL yum install httpd-tools - 生成密码文件:
htpasswd -Bn admin > /etc/nginx/registry.htpasswd # 这里会提示你输入两遍密码 - 配置 Nginx(在
nginx.conf或conf.d下):server { listen 443 ssl; # 建议强制使用 HTTPS server_name your-registry-domain.com;
ssl_certificate /path/to/cert.pem; ssl_certificate_key /path/to/key.pem;
location / { auth_basic "Docker Registry"; auth_basic_user_file /etc/nginx/registry.htpasswd;
proxy_pass http://localhost:5000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
# 下面的配置对 Docker Registry 至关重要
proxy_set_header X-Forwarded-Proto $scheme;
proxy_buffering off;
proxy_request_buffering off;
}
}
```
配置完重启 Nginx,以后登录 Docker 就需要先 docker login 了。
3. 限制访问 IP(ACL)
除了账号密码,防火墙是最好的最后一道防线。如果你的 Registry 只给几台固定的机器用,就在防火墙里设置白名单,只允许那几台 IP 的 5000 端口访问。这样就算密码泄露了,别人也连不上去。
四、 防患于未然:安全配置的“默认姿势”
为了以后不再踩这种坑,建议大家把下面的安全检查项加入标准运维流程:
- 绝不裸奔:公网服务必须开认证,内网服务也建议开认证或配合 VPN 访问。
- 开启 HTTPS:Basic Auth 认证如果不走 HTTPS,密码就是明文传输的。现在 Let's Encrypt 免费证书这么方便,没理由不用。
- 定期审计:写个简单的脚本,定期调用
/v2/_catalogAPI 检查仓库里有没有陌生的镜像。 - 关闭删除能力:新版 Registry 默认开启删除 API,如果不需要频繁删除镜像,建议配置中关闭_delete 功能,防止恶意者清理证据或破坏你的数据。
Docker 虽然好用,但安全意识的缺失往往比 Bug 更可怕。与其费劲去查杀木马,不如一开始就锁好大门。希望这篇惨痛的教训能给大家提个醒,赶紧去检查一下自己的 Registry 还是不是在“裸奔”。

评论已关闭