每隔几个月,技术媒体上就会出现一条熟悉的新闻:某公司的云存储桶暴露在公网,数以百万计的用户记录,任何人拿到一个 URL 就能直接下载。复盘报告的结论几乎总是相同的——攻击者没有突破任何防线,入口从一开始就是开着的。对象存储领域的泄露事件,多数不是漏洞利用的结果,而是有人忘了关上一扇门。桶的权限是错的,凭证是默认的,控制台直接挂在公网上,传输是明文的。
RustFS 是用 Rust 写的 S3 兼容分布式对象存储,Apache 2.0 协议开源,1.0.0 已于 9 月 16 日 GA,10 月 3 日刚出过补丁版 1.0.1,一条 docker run 就能拉起来。安装简单是优点,也是风险:实例跑起来和有资格上线之间,隔着一段不少人不肯走的路。官方文档其实把该做的安全动作都写了,只是散落在安装指南、检查清单和集成页里,没人替你把它们串起来。这份清单就是做这件事的,五个动作,每一条都给出官方文档出处,逐条做完再接网络。
把 rustfsadmin 换掉,再谈别的
RustFS 出厂自带一组默认凭证,和大多数软件一样,全世界的实例长着同一张脸。互联网上的扫描器对 S3 兼容端点的探测从不停歇,新实例挂上公网,早晚会被扫到。默认凭证的问题就在这里:全世界都知道这把钥匙长什么样。这也是为什么官方把它放在安装文档的第一屏。安装指南开篇单独设了一节"立即更改默认凭证",要求在将 RustFS 接入网络前,为 RUSTFS_ACCESS_KEY 和 RUSTFS_SECRET_KEY 设置唯一值,原话的意思很直白:rustfsadmin 这个全球通用的默认值,一个字符都别留。Docker 部署页重复了同样的警告,并给了补救路径:容器启动时未设置自定义凭证的,停掉它,用两个 -e 选项重新创建,rustfs-data 卷会保持不变,数据不丢。已经用默认凭证跑了一阵子的实例,光改环境变量还不够:默认凭证在这段时间里等于公开,重建容器之后把这段窗口期的访问日志翻一遍,有异常就当已泄露处理。
所以正经的启动命令应该长这样,两个凭证变量在容器创建时就传进去,控制台端口只绑本机回环,原因下一节讲:
dockerrun-d\--namerustfs\--restartunless-stopped\-p9000:9000\-p127.0.0.1:9001:9001\-vrustfs-data:/data\-eRUSTFS_ACCESS_KEY="<your-access-key>"\-eRUSTFS_SECRET_KEY="<your-secret-key>"\-eRUSTFS_ADDRESS=":9000"\-eRUSTFS_CONSOLE_ADDRESS=":9001"\-eRUSTFS_CONSOLE_ENABLE=true\-eRUSTFS_OBS_LOGGER_LEVEL=error\-eRUSTFS_OBS_LOG_DIRECTORY="/var/log/rustfs/"\rustfs/rustfs:latest\/data密钥本身的生成方式也有讲究。安全检查清单的凭证保护一节要求初始化后立即设置唯一的访问密钥和强随机密钥,例如使用 openssl rand -base64 24 生成,示例里的占位符值绝不带进生产环境。官方 Docker 页的原话更直接:绝不要将占位符值用于生产环境。二进制和 systemd 部署的路径不同,把两个值写进 /etc/default/rustfs,然后重启 rustfs 服务,动作是等价的。
这一关过了,静态密钥之外还有个进阶方向。IAM 页对根凭证的口径很明确,原话是:请仅使用根凭证引导部署,然后创建 IAM 用户和服务账户来处理日常工作。服务账户可以设过期时间,STS 签发的临时凭证有效期在 15 分钟到 12 小时之间(IAM 管理、OIDC 外部身份提供商两个章节都在安全与合规专区里)。钥匙从"永久有效"变成"按时作废",泄露之后的影响窗口就完全不同了。
9000 和 9001,别同时对着公网
RustFS 默认开两个端口:9000 跑 S3 API,9001 跑控制台。控制台是整个存储系统的管理面,谁拿到它谁就能建桶、删桶、换策略,它暴露在公网上的后果比数据面被扫到还重。安全检查清单的 API 安全一节为此写了三条:使用防火墙或安全组限制对 S3 API(端口 9000)和控制台(端口 9001)的访问;使用反向代理(例如 Nginx),不要直接公开存储节点;禁用未使用的端口,不要向公共互联网公开管理界面。
具体开哪些口,网络检查清单的防火墙一节给了一个最小集合:
- TCP 9000 (S3 API; also used for internal node-to-node communication) - TCP 9001 (RustFS Console) - TCP 443 (only if you terminate HTTPS on a reverse proxy / load balancer)注意 9000 的双角色:多节点部署时它还承担节点间通信,所以必须在集群内部全通,但对公网可以一个端口都不给。443 只在你把 HTTPS 终结在反向代理或负载均衡上时才需要,证书和流量压力都挪到了前置层,存储节点本身继续待在内网。网络检查清单在 IP 分配一节还要求将管理网络与数据网络分离,为存储节点分配连续的 IP 地址段并预留扩容空间,对应到部署上,就是控制台只绑内网地址,运维要碰它先过跳板机。这一步在云上是安全组几条规则的事,在 IDC 里是交换机 ACL 几行配置的事,成本都不高,跳过它的代价却可能是整站数据被人打包带走。检查方法也简单:从一台公网机器上 telnet 这两个端口,两个都连不上才算及格,业务和运维的入口都收在 443 反代和跳板机后面。
TLS 只是两个环境变量的事
存储里的数据不该明文过网,内部网络也不例外,一旦有机器被拿下,同网段的流量就是现成的窃听现场。安全检查清单对传输加密的要求很明确:启用 TLS/SSL,强制 TLS 1.2 以上,建议外部和内部访问使用不同的证书,证书用受信任 CA 签发,私钥靠严格的文件权限保护,多域名场景下用强加密算法(例如 2048 位 RSA 或 256 位 ECC)。
落到操作上,TLS 配置页写得相当短。证书必须命名为 rustfs_cert.pem 和 rustfs_key.pem,放进任意一个目录,然后在 /etc/default/rustfs 里指向它:
RUSTFS_TLS_PATH="/opt/tls"systemctl restart rustfs重启之后 TLS 同时作用于两个监听器,S3 API 和控制台都走 https,不需要分开配两遍。容器部署则是挂载证书目录并传入同一个变量:
docker run -d \ --name rustfs \ -e RUSTFS_TLS_PATH="/opt/tls/" \ -v /opt/tls:/opt/tls \ -p 9000:9000 \ -p 127.0.0.1:9001:9001 \ -v /data:/data \ rustfs/rustfs:latest这里有个文档专门提醒的坑:容器默认以 rustfs 用户运行,证书文件如果不归这个用户所有,RustFS 会因为读不了私钥而配不上 TLS。报错信息往往和证书权限看起来毫无关系,排查时先看文件属主,再看 TLS 配置本身。私钥的保管同样属于检查清单里证书管理一条的范畴,文件权限收紧到属主可读是底线。证书到期时间也建议纳入监控,TLS 配好之后被一张过期证书打回明文,是运维事故统计里出现频率很高的一种难堪。
审计日志要放到系统外面
出了安全事件,你需要回答三个问题:谁在什么时候动了哪个桶。答案只在日志里,而日志只有在攻击者碰不到的地方才算数。安全检查清单的日志和审计一节要求启用审计日志,并将其导出到外部系统,给出的可选目标是 HTTP Webhook、Kafka、ELK、Splunk;同时为登录失败、异常访问模式、批量删除这类行为设置告警。日志只留在本机不算数,机器一旦被入侵,被顺手清掉的往往就是日志本身,这正是导出到外部系统的意义。
RustFS 官方的 Docker Compose 文件自带 grafana、prometheus、otel-collector 和 jaeger 这组可观测性服务,克隆仓库后一条命令整套拉起:
docker compose --profile observability up -d只想要 RustFS 本体的话,把服务名单独指过去:
docker compose -f docker-compose.yml up -d rustfs不过要说清楚:这套 compose 栈管的是指标和追踪,跟审计日志要的"外部"不是一回事。审计日志对应的是检查清单里 Webhook、Kafka、ELK、Splunk 那条导出路径,目标系统必须独立于存储主机,拉起一套本机 Grafana,不等于完成了审计导出。
日志收集方式官方也给了参考:用 systemd、Docker 或 K8s 这些标准工具收集,再通过 ELK 或 Grafana Loki 分析。选型可以后置,规则要先建:异常访问模式这类信号只有提前定义了才会被看见,事后翻日志永远慢一步。告警阈值的设计也有讲究:批量删除是最值得盯的信号之一,一次正常的运维清理和一次灾难性的误操作,在日志里的形状可能一模一样,差别只在有没有告警把它拦下来给人过目。留存时长则有一条硬性的法定底线:《网络安全法》要求网络日志留存不少于六个月,等保和行业审计的要求只会更严,按最严的那条执行。
纠删码不是备份
Docker 页的"生产环境之前"一节把上线前的固定动作列了一遍:完成预安装检查清单,使用多节点部署架构,启用 TLS 加密通信,配置日志轮转策略,并设置定期备份策略。备份被官方写进了上线前动作清单,原因在安装页的部署模式对比表里写得很清楚:单节点单磁盘模式没有任何容错能力,需要依赖备份;单节点多磁盘只能容忍节点内的磁盘故障;跨服务器的磁盘级和节点级容错,要靠多节点多磁盘加纠删码。也就是说,容错能力再强的架构也不替代备份,纠删码防的是磁盘坏,防不了误删、恶意删和数据损坏。
备份解决机器坏,版本控制解决人手滑。安全检查清单的 WORM 合规一节要求启用版本控制和对象锁定,以满足法规要求。开着版本控制的桶,覆盖和误删都还有回退余地;对象锁定再把对象钉死在保留期内,勒索软件把文件加密重写那条最常见的技术路线也就走不通了。这两项是 S3 兼容生态的标准能力,金融、医疗这类数据合规定得严的行业尤其用得上。备份本身的存放位置同样是个决策:备份和源数据放在同一套存储里,一场针对存储系统的故障或攻击会把两者一起带走,异地或异系统的第二副本才是真正能兜底的最后一张牌。
这五项检查全部是部署侧的配置动作,但官方清单并不止这五项:基于策略的访问控制和最小权限、不在代码里硬编码凭证、应用补丁并保持操作系统和依赖(比如 OpenSSL)为最新,都在同一页上,这五个是底线不是上限。