mongos是唯一有效的审计入口点,因其处理所有认证、授权和命令解析,分片节点仅接收剥离用户上下文的内部请求,无法反映原始特权操作。

不能直接审计单个分片的特权访问行为——mongos 路由层会拦截并重写所有客户端请求,原始连接不直连分片节点,所以分片节点自身的日志或审计日志无法反映“谁、通过什么应用、对哪个集合执行了什么特权操作”。
为什么 mongos 是唯一有效的审计入口点
分片集群中,客户端只与 mongos 交互;mongos 解析查询、路由到对应分片、合并结果。所有认证、授权、命令解析都发生在 mongos 进程内。分片节点(mongod)收到的请求已剥离用户上下文,仅含内部路由凭证。
-
mongod分片日志里看不到原始用户名、客户端 IP、应用名,只有类似conn123: command admin.$cmd command: { replSetGetStatus: 1 }这类内部调用 -
mongos启用审计后,能记录完整操作链:发起者(client字段)、数据库/集合、命令名、参数(可选)、结果状态 - 即使你为每个分片单独开启
auditLog,也无法关联到真实业务请求,因为分片收不到$or、explain、dropDatabase等特权命令的原始形态
在 mongos 上启用审计并过滤分片相关操作
审计必须配置在 mongos 实例上,且需显式包含分片管理类命令。默认审计规则不捕获分片行为,必须手动添加。
- 启动
mongos时加上:--auditDestination file --auditFormat JSON --auditPath /var/log/mongodb/mongos-audit.log - 关键审计规则需包含:
sh.addShard、sh.removeShard、sh.enableSharding、sh.shardCollection、sh.moveChunk、sh.splitAt - 注意:
sh.status()是只读命令,不在默认审计范围内,如需记录,得用auditFilter自定义规则匹配command: "serverStatus"或"getCmdLineOpts"(取决于实际触发方式) - 审计日志体积增长快,建议配合 logrotate,并避免开启
logAllOperations—— 它会记录每条查询,与“特权访问”目标偏离
如何从审计日志定位某次分片变更的源头
审计日志中的 client 字段是唯一可信来源,但容易被伪造或缺失,需前置加固。
- 确保所有
mongos配置了net.bindIpAll: false+ 显式net.bindIp,禁止通配绑定,否则client.addr可能是127.0.0.1(来自本地脚本) - 强制客户端使用带
appName的连接字符串,例如:mongodb://user:pass@mongos1:27017/?appName=payment-batch-job;该值会出现在审计日志的client.appName字段 - 特权操作如
sh.shardCollection("mydb.users", {"tenant_id": 1})在日志中体现为command: "shardCollection",其params字段含数据库名和分片键,但不含执行者角色——角色需查admin.system.roles结合client.principal推断 - 若发现异常
sh.moveChunk,立刻检查对应时间窗口的config.chunks变更和config.migrations记录,确认是否由平衡器自动触发(who: "Balancer")还是人工干预
真正难的是把一次 sh.splitAt 操作和三个月前创建的那个运维账号关联起来——mongos 不存操作人邮箱或工号,所有追溯依赖你是否在创建账号时用了有意义的 userName(比如 ops-db-prod-2025-q3),以及是否禁用了 root 类通用账号。没做这两点,审计日志就只是时间戳堆叠。


















