适用场景
MongoDB 安全加固适用于以下场景:数据库实例直接暴露在公网导致未授权访问;业务增长后忘记为实例开启认证,任何人均可通过 mongo shell 直连并读取、篡改数据;等保 2.0 或金融行业合规要求对数据库访问链路做加密与审计。本文从 MongoDB 未授权访问原理出发,给出开启认证、配置访问控制、启用 TLS 加密与安全基线加固的完整方案。
前置条件
- 一台已安装 MongoDB 的服务器(本文以 MongoDB 6.0/7.0 社区版为例)
- 拥有 MongoDB 配置文件
/etc/mongod.conf的读写权限 - 能通过 SSH 登录服务器,并已配置防火墙(如 iptables 或云安全组)
原理说明
MongoDB 未授权访问的本质是认证开关未开启:默认配置下服务端不校验客户端身份,任何能连通 27017 端口的 IP 都可以以管理员权限直连数据库,配合 db.adminCommand({listDatabases:1}) 即可枚举全部库表,进而拖库或加密勒索。MongoDB 的认证体系基于 SCRAM-SHA-256 机制,启用后客户端需提供用户名与密码,由服务端完成口令校验。同时,MongoDB 通过 角色(Role) 控制权限粒度,最小权限原则要求业务账号只拥有其所需库的读写权限。若数据库需跨公网传输数据,还必须在传输层启用 TLS 加密,防止口令与数据被中间人截获。
操作步骤
1. 创建管理员账号
# 先以无认证模式临时启动,或直接用本地 shell 连接
mongosh --port 27017
# 切换 admin 库创建超级管理员
use admin
db.createUser({
user: "admin",
pwd: passwordPrompt(), # 交互输入强密码
roles: [{ role: "root", db: "admin" }]
})
关键参数:roles: "root" 赋予所有库的管理权限,仅用于初始化,业务运行期建议改用 readWrite 等受限角色。
2. 开启认证并绑定内网地址
# 编辑 /etc/mongod.conf
security:
authorization: enabled # 开启认证
net:
port: 27017
bindIp: 127.0.0.1,192.168.1.10 # 仅绑定本机与内网 IP,禁止 0.0.0.0
# 重启生效
sudo systemctl restart mongod
关键参数:bindIp 绝不能配置 0.0.0.0,否则等于把数据库裸奔在公网;authorization: enabled 是阻断未授权访问的核心开关。
3. 验证未授权访问已被阻断
# 未提供凭据直连,应报认证错误
mongosh --host 192.168.1.10 --port 27017
# 输出: MongoServerError: Unauthorized
# 使用账号密码登录成功
mongosh --host 192.168.1.10 --port 27017 -u admin -p --authenticationDatabase admin
4. 启用 TLS 加密传输
# 生成自签名证书(生产环境建议使用 CA 签发)
openssl req -newkey rsa:2048 -nodes -keyout mongodb.key -x509 -days 365 -out mongodb.crt
cat mongodb.key mongodb.crt > mongodb.pem
# 修改 mongod.conf
net:
tls:
mode: requireTLS
certificateKeyFile: /etc/mongodb.pem
sudo systemctl restart mongod
# 客户端加密连接
mongosh "mongodb://192.168.1.10:27017/admin?tls=true" -u admin -p
5. 安全基线加固
# 关闭 HTTP 接口(老版本 Web 管理端口,默认已移除)
# 通过 iptables 仅放行内网访问 27017
sudo iptables -A INPUT -p tcp --dport 27017 -s 192.168.1.0/24 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 27017 -j DROP
# 定期备份并在备份时加密
dump --out /backup/mongo_$(date +%F) --authenticationDatabase admin -u admin -p
配置验证
# 1. 检查认证是否生效:无凭据连接应被拒绝
mongosh --host 127.0.0.1 --port 27017 --eval "db.runCommand({connectionStatus:1})"
# 2. 检查监听地址,不应出现 0.0.0.0
sudo ss -tlnp | grep 27017
# 3. 验证最小权限:用只读账号执行写操作应被拒绝
mongosh -u readonly -p --authenticationDatabase appdb --eval "db.users.insert({x:1})"
# 输出: MongoServerError: not authorized on appdb to execute command
常见问题
Q1:开启认证后应用连接报 Unauthorized,如何处理?
先确认应用连接串是否正确携带 authSource(认证库)参数,例如 mongodb://user:pass@host:27017/appdb?authSource=admin。其次检查账号所属库与角色,若账号在 admin 库创建,authSource 必须为 admin。最后确认连接用户名密码无多余空格。
Q2:开启 TLS 后老客户端连不上怎么办?
TLS 模式 requireTLS 强制所有连接加密,老版本驱动需升级支持 TLS 的版本,或在驱动连接串追加 ?tls=true&tlsAllowInvalidCertificates=true(仅测试环境,生产建议使用受信任 CA 证书)。若业务无法立即改造,可先用 preferTLS 过渡,但需尽快切换到强制加密。
总结
MongoDB 未授权访问是最常见的数据库失陷入口之一,开启 authorization: enabled、将 bindIp 限制在内网、启用 TLS 加密三件事能挡住绝大多数攻击路径。再配合最小权限账号、iptables 端口管控与加密备份,即可形成数据库层的纵深防御。建议每季度复查一次角色权限与连接审计日志。