MongoDB副本集安全性配置与增强
2023-10-153.1k 阅读
MongoDB 副本集安全性基础配置
启用身份验证
在 MongoDB 副本集中,启用身份验证是保障安全性的基础步骤。这能确保只有经过授权的用户才能访问数据库。
- 创建管理员用户:
- 首先连接到 MongoDB 副本集的主节点。可以使用 mongo 命令行工具:
mongo --host primary_host:port
- 切换到
admin
数据库,因为管理员用户通常创建在这个数据库中:
use admin
- 创建管理员用户,例如:
db.createUser({
user: "adminUser",
pwd: "adminPassword",
roles: [ { role: "root", db: "admin" } ]
})
这里 root
角色赋予了用户在整个 MongoDB 实例上的最高权限。
- 启用身份验证:
- 修改 MongoDB 配置文件(通常在
/etc/mongod.conf
或其他指定路径),添加或修改以下配置:
- 修改 MongoDB 配置文件(通常在
security:
authorization: enabled
- 保存配置文件后,重启 MongoDB 服务,使配置生效。在大多数 Linux 系统上,可以使用以下命令:
sudo systemctl restart mongod
之后,当连接到 MongoDB 时,就需要提供用户名和密码。例如:
mongo --host primary_host:port -u "adminUser" -p "adminPassword" --authenticationDatabase "admin"
配置密钥文件
密钥文件用于副本集成员之间的身份验证,确保只有授权的节点可以加入副本集。
- 生成密钥文件:
- 使用 openssl 工具生成一个随机的密钥文件,例如:
openssl rand -base64 756 > /path/to/mongodb.key
- 设置密钥文件的权限,只有 MongoDB 进程能读取它:
chmod 400 /path/to/mongodb.key
- 配置副本集使用密钥文件:
- 修改每个副本集成员的 MongoDB 配置文件,添加以下内容:
security:
keyFile: /path/to/mongodb.key
- 重启每个副本集成员的 MongoDB 服务,使配置生效。这样,副本集成员之间就通过密钥文件进行身份验证,增强了副本集内部通信的安全性。
网络安全配置
绑定 IP 地址
- 限制监听地址:
- MongoDB 默认监听所有网络接口(0.0.0.0),这在生产环境中存在安全风险。建议将其绑定到特定的 IP 地址,比如服务器的内部 IP 地址或仅允许访问的外部 IP 地址。
- 修改 MongoDB 配置文件,找到
net
部分,修改bindIp
选项。例如,只绑定到内部 IP192.168.1.100
:
net:
bindIp: 192.168.1.100
- 保存配置文件并重启 MongoDB 服务,这样 MongoDB 就只会监听指定的 IP 地址,减少了暴露在不必要网络接口上的风险。
- 使用防火墙:
- 结合服务器的防火墙(如 iptables 或 firewalld)进一步限制对 MongoDB 端口(默认 27017)的访问。
- 以 iptables 为例,允许特定 IP 地址(如
192.168.1.200
)访问 MongoDB 端口:
iptables -A INPUT -p tcp -s 192.168.1.200 --dport 27017 -j ACCEPT
iptables -A INPUT -p tcp --dport 27017 -j DROP
第一条规则允许指定 IP 访问,第二条规则阻止其他所有 IP 访问 MongoDB 端口。对于 firewalld,可以使用类似的命令:
firewall -cmd --zone=public --add -rich -rule='rule family="ipv4" source address="192.168.1.200" port protocol="tcp" port="27017" accept'
firewall -cmd --zone=public --add -rich -rule='rule family="ipv4" port protocol="tcp" port="27017" drop'
启用 TLS/SSL 加密
- 生成证书:
- 可以使用 OpenSSL 生成自签名证书,这适用于测试和开发环境。对于生产环境,建议使用受信任的证书颁发机构(CA)颁发的证书。
- 生成私钥:
openssl genrsa -out mongodb.key 2048
- 生成证书签名请求(CSR):
openssl req -new -key mongodb.key -out mongodb.csr -subj "/C=US/ST=California/L=San Francisco/O=Your Company Name/CN=your_domain.com"
- 自签名证书:
openssl x509 -req -in mongodb.csr -days 365 -signkey mongodb.key -out mongodb.crt
- 配置 MongoDB 使用 TLS/SSL:
- 修改 MongoDB 配置文件,添加以下内容:
net:
ssl:
mode: requireSSL
PEMKeyFile: /path/to/mongodb.pem
CAFile: /path/to/ca.crt
这里 mongodb.pem
文件包含私钥和证书(可以将 mongodb.key
和 mongodb.crt
合并到一个文件中),ca.crt
是证书颁发机构的证书(如果使用自签名证书,就是 mongodb.crt
)。
- 重启 MongoDB 服务,使配置生效。连接到 MongoDB 时,也需要指定 SSL 选项。例如:
mongo --host primary_host:port -u "adminUser" -p "adminPassword" --authenticationDatabase "admin" --ssl --sslCAFile /path/to/ca.crt
权限管理与安全策略
细粒度权限控制
- 创建普通用户并分配权限:
- 除了管理员用户,应该为不同的业务需求创建具有细粒度权限的普通用户。例如,为一个应用程序创建用户,该用户只能读写特定数据库中的集合。
- 切换到目标数据库,例如
myappdb
:
use myappdb
- 创建用户并分配权限,比如只允许读取
users
集合和写入logs
集合:
db.createUser({
user: "myappUser",
pwd: "myappPassword",
roles: [
{ role: "read", db: "myappdb", collection: "users" },
{ role: "write", db: "myappdb", collection: "logs" }
]
})
- 使用角色组合:
- MongoDB 提供了一些内置角色,也可以创建自定义角色并将其组合使用。例如,创建一个自定义角色
myapp_custom_role
并分配给用户: - 首先在
admin
数据库中创建自定义角色:
- MongoDB 提供了一些内置角色,也可以创建自定义角色并将其组合使用。例如,创建一个自定义角色
use admin
db.createRole({
role: "myapp_custom_role",
privileges: [
{ resource: { db: "myappdb", collection: "products" }, actions: ["find", "update"] },
{ resource: { db: "myappdb", collection: "orders" }, actions: ["insert", "delete"] }
],
roles: []
})
- 然后在
myappdb
数据库中创建用户并分配这个自定义角色:
use myappdb
db.createUser({
user: "myappUser2",
pwd: "myappPassword2",
roles: [ { role: "myapp_custom_role", db: "myappdb" } ]
})
审计配置
- 启用审计日志:
- 审计日志可以记录 MongoDB 服务器上的各种操作,有助于安全分析和合规性检查。
- 修改 MongoDB 配置文件,添加以下内容:
auditLog:
destination: file
path: /var/log/mongodb/audit.log
format: JSON
filter: {
atype: { $in: ["command", "connection", "authentication"] }
}
这里将审计日志输出到文件 /var/log/mongodb/audit.log
,采用 JSON 格式,并只记录命令、连接和身份验证相关的操作。
- 重启 MongoDB 服务,开始记录审计日志。可以使用工具如
jq
来分析 JSON 格式的审计日志。例如,查看所有身份验证相关的记录:
cat /var/log/mongodb/audit.log | jq '.[] | select(.atype == "authentication")'
防范常见安全威胁
防止注入攻击
- 使用参数化查询:
- 在应用程序中与 MongoDB 交互时,应避免直接拼接查询字符串,而是使用参数化查询。以 Python 的
pymongo
库为例:
- 在应用程序中与 MongoDB 交互时,应避免直接拼接查询字符串,而是使用参数化查询。以 Python 的
from pymongo import MongoClient
client = MongoClient("mongodb://adminUser:adminPassword@primary_host:port/admin")
db = client["myappdb"]
users_collection = db["users"]
username = "testUser"
password = "testPassword"
# 错误方式,易受注入攻击
# query = "{'username': '" + username + "', 'password': '" + password + "'}"
# result = users_collection.find_one(eval(query))
# 正确方式,参数化查询
query = {'username': username, 'password': password}
result = users_collection.find_one(query)
- 验证和清理输入:
- 在将用户输入传递给 MongoDB 查询之前,对其进行验证和清理。例如,使用正则表达式验证用户名是否符合规范:
import re
username = "testUser"
if not re.match("^[a-zA-Z0-9_]{3,20}$", username):
raise ValueError("Invalid username")
防范暴力破解攻击
- 设置合理的密码策略:
- 要求用户设置强密码,包含大小写字母、数字和特殊字符,并且有一定的长度限制。例如,在创建用户时提示用户设置强密码:
db.createUser({
user: "newUser",
pwd: prompt("Enter a strong password"),
roles: [ { role: "readWrite", db: "myappdb" } ]
})
- 限制登录尝试次数:
- 虽然 MongoDB 本身没有内置的登录尝试次数限制功能,但可以在应用层实现。例如,使用一个计数器记录用户登录尝试次数,超过一定次数后锁定用户一段时间:
login_attempts = {}
def login(username, password):
if username not in login_attempts:
login_attempts[username] = 1
else:
login_attempts[username] += 1
if login_attempts[username] > 5:
print("Account locked for 10 minutes due to too many failed attempts.")
return
# 实际的登录验证逻辑
client = MongoClient("mongodb://adminUser:adminPassword@primary_host:port/admin")
db = client["myappdb"]
users_collection = db["users"]
user = users_collection.find_one({'username': username, 'password': password})
if user:
print("Login successful.")
else:
print("Login failed.")
监控与安全更新
监控副本集状态
- 使用 MongoDB 内置监控工具:
- MongoDB 提供了
rs.status()
命令来查看副本集的状态。连接到副本集的主节点后,运行该命令:
- MongoDB 提供了
rs.status()
该命令会返回副本集的详细状态信息,包括成员状态、选举状态、同步状态等。例如,检查某个成员的状态:
var status = rs.status();
for (var i = 0; i < status.members.length; i++) {
printjson(status.members[i]);
}
- 使用外部监控工具:
- 可以使用第三方工具如 Prometheus 和 Grafana 来监控 MongoDB 副本集。首先,安装并配置 MongoDB Exporter,它可以将 MongoDB 的指标暴露给 Prometheus。
- 下载 MongoDB Exporter 二进制文件,例如:
wget https://github.com/percona/mongodb_exporter/releases/download/v0.20.3/mongodb_exporter-0.20.3.linux-amd64.tar.gz
tar -xvf mongodb_exporter-0.20.3.linux-amd64.tar.gz
cd mongodb_exporter-0.20.3.linux-amd64
- 配置 MongoDB Exporter 连接到副本集,例如:
./mongodb_exporter --mongodb.uri="mongodb://adminUser:adminPassword@primary_host:port/admin"
- 然后在 Prometheus 配置文件中添加 MongoDB Exporter 的地址,在 Grafana 中导入 MongoDB 相关的仪表盘模板,就可以直观地监控副本集的各种指标,如 CPU 使用率、内存使用情况、复制延迟等。
安全更新与漏洞管理
- 定期更新 MongoDB:
- 关注 MongoDB 官方发布的安全更新和新版本。可以在 MongoDB 官方网站的下载页面查看最新版本。
- 在更新之前,先在测试环境中进行全面测试,确保更新不会影响业务功能。例如,在测试环境中停止 MongoDB 服务,下载并解压新版本:
wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-ubuntu2004-5.0.10.tgz
tar -xvf mongodb-linux-x86_64-ubuntu2004-5.0.10.tgz
- 备份数据,然后将新版本的二进制文件替换旧版本,并重启 MongoDB 服务。在生产环境更新时,要遵循一定的部署策略,如滚动升级,以确保服务的连续性。
- 漏洞扫描与修复:
- 使用漏洞扫描工具如 Nessus 或 OpenVAS 对运行 MongoDB 的服务器进行定期扫描。这些工具可以检测出 MongoDB 相关的已知漏洞。
- 当发现漏洞时,根据漏洞的严重程度和影响范围,及时采取修复措施。如果是 MongoDB 本身的漏洞,及时更新到包含修复的版本;如果是配置相关的漏洞,如弱密码或不安全的网络配置,按照前面介绍的安全配置方法进行修复。
通过以上全面的安全性配置与增强措施,可以有效提升 MongoDB 副本集的安全性,保护数据的机密性、完整性和可用性。在实际应用中,要根据业务需求和安全要求,灵活运用这些方法,并持续关注安全动态,及时调整安全策略。