一次 Elasticsearch 被清库的复盘
这件事发生得很突然,也很典型。
我有一套 Elasticsearch,用来存设备日志和监控数据,部署很简单:Docker 单节点,数据目录挂到宿主机。本来只是测试环境,就没太在意安全,9200 端口直接对外开放,也没有开认证。
运行一直很正常,直到某天发现数据不对劲。
现象
最开始不是“全没了”,而是更隐蔽的变化:
- 有些索引的数据明显变少
- 有些索引直接查不到
- ES 服务还在正常运行,甚至还在持续写入
这种状态很容易让人误判成查询问题。于是先做了最基础的确认:
curl http://localhost:9200/_cat/indices?v
可以看到索引还在,但文档数量明显不对,而且有些索引像是刚创建的,数据量很小。
这时候可以确定:
不是查询条件问题
第一反应:是不是持久化丢了
Docker 跑 ES,最常见的坑就是没做持久化。先看配置:
- /usr/local/data/elasticsearch/data:/usr/share/elasticsearch/data
确认数据目录已经挂载到宿主机。
然后直接去宿主机看数据文件:
find /usr/local/data/elasticsearch/data/nodes/0/indices | head
能看到类似这些文件:
_index/_0.cfs
segments_3
translog-*.tlog
state-*.st
这里简单解释一下这些文件是什么:
- Lucene segment 文件(.cfs / segments_*) ES 底层用 Lucene 存数据,这些文件就是“真正的数据”
- translog(事务日志) 用来保证数据写入不丢失,类似数据库的 redo log
- state 文件 记录索引和分片的元信息
这些文件都在,说明一件事:
数据目录是正常的,不是容器重建导致的数据丢失
怀疑 ILM(生命周期管理)
因为配置过 ILM,于是查了一下策略:
curl http://127.0.0.1:9200/_ilm/policy?pretty
关键策略大致是:
- device_log_policy:3650 天后删除
- system_log_policy:180 天后删除
而当前索引是:
device_log_xxx_2026-4
也就是当月数据。
很明显,这些索引不可能满足删除条件。
于是可以排除:
不是 ILM 自动删除
真正的突破:日志
接下来去看 ES 日志,直接搜关键字:
grep "deleting index" elasticsearch.log
很快看到大量记录:
MetadataDeleteIndexService ... deleting index
而且删的全是业务索引,比如:
- access_logger_2026-4
- device_log_xxx_2026-4
- system_logger_2026-4
更关键的是时间:
- 下午删一批
- 晚上再删
- 第二天继续
这个节奏已经很明显:
索引是被“主动删除”的
更诡异的一点:删完又出现
继续看日志,还能看到另一类记录:
creating index, cause [auto(bulk api)]
这说明:
- 索引被删后
- 应用还在往这个索引写数据
- ES 自动重新创建索引
整个过程是:
删除索引 → 应用写入 → 自动创建 → 再被删除
这也是为什么一开始看到的是“数据变少”,而不是直接全没。
最终确认:read_me 勒索信息
在索引列表里发现一个异常索引:
curl http://localhost:9200/_cat/indices?v
里面多了一个:
read_me
打开之后是一段勒索内容,大致意思是:
数据已经被删除,想恢复需要支付 BTC
到这里,原因就完全明确了:
Elasticsearch 被扫端口后执行了清库攻击
*** 这里需要注意一下,你的数据已经确认被删除了,接受这个事实,不要打钱,对方不可能还你数据。勒索内容里面的链接也不要点! ***
发生了什么
这类攻击流程非常简单,而且是自动化的:
扫描全网 9200 端口
判断是否无认证
执行删除:
DELETE /*写入勒索信息
等待用户上钩
重点是:
对方并没有真的备份你的数据
只是删除后“骗你打钱”。
为什么会中招
回头看环境,其实问题很直接:
- 9200 端口对公网开放
- 没有认证
- 没有 IP 限制
换句话说:
等于把数据库的读写删除权限直接暴露在公网
而这些扫描都是机器人在跑,并不是针对某个人。
处理方式
处理其实很简单,先把入口关掉。
第一步是通过安全组限制访问,只允许自己的 IP:
只允许指定 IP 访问 9200
第二步是开启认证:
xpack.security.enabled: true
至少做到:
不是谁都能连进来执行 DELETE
后续打算
这次之后,会把这一层补完整:
- ES 不再直接暴露公网,前面加网关
- 做 IP 白名单
- 增加快照备份
- 保留访问日志
这些平时看起来“用不到”,但一旦出事就是刚需。
总结
这件事本身不复杂,但很有代表性。
它不是配置写错,也不是组件问题,而是一个很基础的安全问题:
基础设施暴露在公网且没有认证
可以简单总结一句话:
Elasticsearch 只要裸露在公网,就迟早会被清库。
踩过一次,这个问题基本就不会再忽视了。