半夜两点,手机上的监控告警像催命一样把我震醒。登录服务器一看,CPU 100% 持续了快十分钟,docker ps 下面多了一个我从来没见过的容器,镜像名字看着马马虎虎,实际跑的是挖矿程序。再往下追原因,结论非常典型:我的 Docker daemon 把 2375 端口暴露在公网,而且没做任何认证。换句话说,任何知道这个 IP 的人,都可以直接调 Docker API 在这台服务器上为所欲为。
这不是我第一次处理 Docker 2375 未授权访问的问题,也肯定不会是最后一次。2375 端口在 Docker 生态里极其常见,但恰恰因为常见,反而成了"默认裸奔"的重灾区。这篇文章就是写给所有用过 Docker、特别是照着老教程把 2375 端口开起来的朋友:先说清楚这个端口为什么危险,再带你按步骤自查,最后给出从止血到 TLS 双向认证加固的完整方案。文章里的验证和修复操作都基于我自己的生产环境踩坑总结,你可以在自己有控制权的服务器上直接操作。
1. 2375端口问题是怎么泛滥的:一句老命令引发的"裸奔"
1.1 Docker daemon 的默认形态:本地 AF_UNIX socket
先说基础。Docker 分成客户端(CLI)和服务端(daemon)两部分,你平时敲 docker ps、docker run,本质上都是客户端向 daemon 发 HTTP 请求。daemon 默认监听在哪儿?不是 TCP 端口,而是一个本地 socket 文件:
bash复制unix:///var/run/docker.sock
这个设计其实挺聪明的。socket 文件的权限受系统用户控制,只有 docker 组或 root 用户能访问,相当于"只有拿着我家钥匙的人才能开门"。你在服务器上直接敲 docker 命令,走的就是这条路,完全不需要端口,也不需要密码。
真正的问题出在"远程管理"这个需求上。当你想从自己的电脑上操作几百公里外的服务器 Docker,本地 socket 就不够用了,必须让 daemon 额外监听一个 TCP 端口。这时候很多老教程会告诉你这样启动:
bash复制dockerd -H 0.0.0.0:2375
不幸的是,这一步就是灾难的开始。
1.2 2375 的来历与"不加认证"的设计缺陷
要理解 2375 为什么危险,得先知道它的身份。Docker 官方其实给远程 API 预留了两个端口:
| 端口 | 用途 | 是否加密 | 是否认证 |
|---|---|---|---|
| 2375 | 明文 HTTP 远程 API | 否 | 否 |
| 2376 | TLS 加密远程 API | 是 | 是(双向证书) |
注意看,2375 这个端口的设计初衷就是"非安全端口"。它不负责鉴权,不负责加密,任何人只要网络能通到 2375,就等于拿到了 Docker 的完全控制权。官方文档里写得很清楚:2375 仅用于调试和可信内网,如果你要远程用,请用 2376 配合 TLS 证书。
那为什么还有很多教程让你开 2375?我翻了翻自己早年收藏的笔记,大概有三个原因:
第一,很多教程写于十年前 Docker 刚火的时候,当时大家安全意识很淡,内网互信、无认证是常态。第二,-H tcp://0.0.0.0:2375 这个参数写起来实在太简单,比配 TLS 少了几十行命令,教程作者图省事就直接贴了。第三,Docker Swarm 早期的跨主机调度、部分 CI/CD 脚本和自动化工具,都需要快速打通多台机器的 daemon,很多人图方便就直接暴露 2375。
说白了,2375 问题的泛滥不是技术门槛高,而是"方便"压过了"安全"。
1.3 2375 和 2376:一字之差,天壤之别
我见过很多朋友把 2375 和 2376 搞混,以为"2376 就是多了个 s"而已,这是非常危险的误解。硬件一点说:
- 2375 是无认证明文端口。数据包在网络上裸奔,访问者就是管理员,没有任何前置门槛。
- 2376 是 TLS 双向认证端口。客户端必须持有 CA 签发的证书才能连上,而且传输过程加密。
一个形象的类比:2375 等于你把服务器钥匙放在门口地毯下面,谁路过谁知道;2376 等于给服务器装了指纹锁,只有录入过指纹的人才能开。你可能会想:"那我只要不告诉别人我的 IP,是不是就安全了?"互联网上的全端口扫描器 24 小时在跑,扫描到 2375 开放只是时间问题,而且很多扫描脚本发现 2375 开放后会自动尝试拉取挖矿镜像。不要把保密当成安全。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 未授权访问2375的真实代价:从容器失控到宿主机失陷
2.1 Daemon 的权限边界决定了攻击者的权限
很多人有个误解,觉得"就算别人通过 2375 进了 Docker,也只是在容器里捣乱,碰不到宿主机"。这个想法相当危险。
Docker daemon 本身是以 root 权限运行的。攻击者拿到 Docker API 之后,理论上可以做到同样的事情,包括但不限于:
- 拉取并运行任意镜像,甚至把宿主机的根目录挂载进容器。
- 查看宿主机的环境变量、挂载点、网络配置等信息。
- 修改 iptables 规则、创建网络、修改现有容器配置。
- 读取宿主机敏感文件,只要把路径挂进容器就行。
我来解释一下"挂载根目录"意味着什么。Docker 的隔离依赖 Linux 内核的命名空间,但它不是一个严格的安全边界。攻击者通过 API 创建一个容器:
bash复制docker run -v /:/host -it alpine sh
这个操作会把宿主机的整个文件系统挂载到容器的 /host 目录下。容器里的进程如果拿到权限,完全可以读取甚至篡改宿主机上的任何文件。你可能会说"在容器里改文件也需要 root 权限啊",但很多容器镜像默认就是以 root 运行,而且 daemon 本身就有能力以宿主机 root 的权限执行操作。
换句话说,2375 未授权访问约等于把宿主机 root 的钥匙交了出去。这不是危言耸听,而是 Docker 架构本身决定的能力边界。
2.2 失陷后的典型痕迹与止损动作
回到我自己那次半夜告警的事故。我当时排查的过
