一、MongoDB网络安全基础
1.1 默认安全风险分析
MongoDB的默认配置存在严重的安全隐患,这些风险是造成过去大量MongoDB数据泄露事件的根本原因:
- 无认证启用:默认情况下,MongoDB不启用认证
- 绑定所有接口 :默认绑定到
0.0.0.0(所有网络接口) - 无防火墙保护:不配置默认防火墙规则
- 默认端口公开:27017端口对所有IP开放
统计数据 :根据CIS(Center for Internet Security)报告,2023年仍有超过15,000个MongoDB实例暴露在互联网上,其中**92%**的泄露事件是由于错误的网络配置,而非软件漏洞。
1.2 网络安全的核心原则
1.2.1 最小暴露原则
- 只暴露必要的服务和端口
- 限制可访问的网络范围
- 遵循"需要知道"原则
1.2.2 分层防御策略
- 外层:网络防火墙(系统级/云平台)
- 中层:MongoDB绑定IP配置
- 内层:MongoDB认证与授权
- 核心:数据加密
1.2.3 持续验证
- 定期扫描外部暴露面
- 验证防火墙规则有效性
- 监控异常连接模式
二、IP白名单配置详解
2.1 MongoDB绑定IP配置
MongoDB通过net.bindIp参数控制监听的网络接口。
2.1.1 配置方法
yaml
# mongod.conf
net:
port: 27017
bindIp: 127.0.0.1,10.20.30.0/24
bindIpAll: false
2.1.2 配置说明
| 参数 | 说明 | 推荐值 |
|---|---|---|
bindIp |
指定监听的IP地址 | 仅内部网络IP |
bindIpAll |
是否绑定所有接口 | false |
port |
监听端口 | 27017(默认) |
2.1.3 不同部署模式的配置
单机部署:
yaml
net:
bindIp: 127.0.0.1,192.168.1.100
副本集部署:
yaml
net:
bindIp: 127.0.0.1,10.0.0.10,10.0.0.11,10.0.0.12
分片集群:
yaml
# Config Server
net:
bindIp: 127.0.0.1,172.16.0.10
# Mongos
net:
bindIp: 127.0.0.1,172.16.0.100
# Shard Servers
net:
bindIp: 127.0.0.1,172.16.0.20
2.2 网络访问控制列表(NACL)
MongoDB提供基于IP的访问控制列表,比单纯的绑定IP更灵活。
2.2.1 配置步骤
- 创建访问控制列表:
javascript
// 创建IP白名单
db.createUser({
user: "security_admin",
pwd: "StrongPassword123!",
roles: [
{ role: "clusterAdmin", db: "admin" }
],
authenticationRestrictions: [
{
clientSource: [
"10.20.30.0/24",
"192.168.1.100"
],
serverAddress: [
"mongodb01.example.com:27017",
"10.20.30.10:27017"
]
}
]
})
- 配置全局IP限制:
yaml
# mongod.conf
security:
authorization: enabled
accessControl:
enabled: true
ipWhitelist: [
"10.20.30.0/24",
"192.168.1.100"
]
2.2.2 高级访问控制
javascript
// 为特定角色配置IP限制
db.createRole({
role: "app_user",
privileges: [
{ resource: { db: "appdb", collection: "" }, actions: ["find", "insert"] }
],
roles: [],
authenticationRestrictions: [
{
clientSource: ["10.20.30.50"],
serverAddress: ["app-server:27017"]
}
]
})
2.3 多网络接口配置
对于有多个网络接口的服务器,需要精细化控制:
2.3.1 专用网络配置
yaml
# mongod.conf
net:
port: 27017
bindIp: 127.0.0.1,10.0.0.10
ipv6: true
unixDomainSocket:
enabled: true
pathPrefix: /var/run/mongodb
2.3.2 生产环境示例
+-----------------+ +-----------------+
| 应用服务器 | | 管理工作站 |
| 10.20.30.50 | | 10.20.30.100 |
+--------+--------+ +--------+--------+
| |
| |
v v
+--------+---------------------+--------+
| MongoDB 服务器 |
| 127.0.0.1, 10.20.30.10 (仅内部) |
+-----------------------------------+
三、防火墙规则配置策略
3.1 系统级防火墙配置
3.1.1 UFW (Ubuntu)
bash
# 1. 允许本地访问
sudo ufw allow from 127.0.0.1 to any port 27017
# 2. 允许应用服务器访问
sudo ufw allow from 10.20.30.50 to any port 27017
# 3. 允许管理工作站访问
sudo ufw allow from 10.20.30.100 to any port 27017
# 4. 拒绝所有其他访问
sudo ufw deny 27017/tcp
# 5. 启用防火墙
sudo ufw enable
3.1.2 iptables (CentOS/RHEL)
bash
# 1. 清除现有规则
sudo iptables -F
# 2. 允许本地访问
sudo iptables -A INPUT -s 127.0.0.1 -p tcp --dport 27017 -j ACCEPT
# 3. 允许应用服务器访问
sudo iptables -A INPUT -s 10.20.30.50 -p tcp --dport 27017 -j ACCEPT
# 4. 允许管理工作站访问
sudo iptables -A INPUT -s 10.20.30.100 -p tcp --dport 27017 -j ACCEPT
# 5. 拒绝其他访问
sudo iptables -A INPUT -p tcp --dport 27017 -j DROP
# 6. 保存规则
sudo service iptables save
3.1.3 防火墙规则验证
bash
# 检查UFW规则
sudo ufw status verbose
# 检查iptables规则
sudo iptables -L -n -v
3.2 端口最小化原则
MongoDB使用多个端口,需为每个端口配置相应的防火墙规则:
| 端口 | 用途 | 安全建议 |
|---|---|---|
| 27017 | mongod/mongos | 严格限制访问 |
| 27018 | Shard Server | 仅允许Mongos访问 |
| 27019 | Config Server | 仅允许Mongos和管理访问 |
| 27020-27022 | 复制集节点 | 仅允许复制集成员访问 |
示例配置:
bash
# Config Server防火墙规则
sudo ufw allow from 10.20.30.0/24 to any port 27019
sudo ufw deny 27019/tcp
# Shard Server防火墙规则
sudo ufw allow from 10.20.40.0/24 to any port 27018
sudo ufw deny 27018/tcp
3.3 防火墙规则自动化管理
3.3.1 防火墙配置脚本
bash
#!/bin/bash
# mongodb-firewall-setup.sh
# 定义安全IP列表
APP_SERVERS="10.20.30.50 10.20.30.51"
ADMIN_WORKSTATIONS="10.20.30.100 10.20.30.101"
INTERNAL_NETWORK="10.20.30.0/24"
# 清除现有规则
sudo ufw reset
# 允许本地访问
sudo ufw allow from 127.0.0.1 to any port 27017
# 允许应用服务器访问
for ip in $APP_SERVERS; do
sudo ufw allow from $ip to any port 27017
done
# 允许管理工作站访问
for ip in $ADMIN_WORKSTATIONS; do
sudo ufw allow from $ip to any port 27017
done
# 限制Config Server访问
sudo ufw allow from $INTERNAL_NETWORK to any port 27019
sudo ufw deny 27019/tcp
# 设置默认策略
sudo ufw default deny incoming
sudo ufw default allow outgoing
# 启用防火墙
sudo ufw enable
# 保存配置
sudo ufw status verbose > /etc/ufw/mongodb-firewall-rules.txt
3.3.2 动态IP更新脚本
bash
#!/bin/bash
# update-ip-whitelist.sh
# 从CMDB获取最新应用服务器IP
APP_SERVERS=$(curl -s https://cmdb.example.com/api/servers?role=app | jq -r '.[].ip')
# 更新防火墙规则
sudo ufw delete allow 27017/tcp # 删除旧规则
for ip in $APP_SERVERS; do
sudo ufw allow from $ip to any port 27017
done
# 保存更新
sudo ufw status verbose > /var/log/mongodb/firewall-rules-$(date +%Y%m%d).log
四、云环境特殊考虑
4.1 AWS安全组配置
4.1.1 基本安全组配置
json
{
"SecurityGroups": [
{
"GroupName": "mongodb-app-access",
"Description": "Allow app servers to access MongoDB",
"IpPermissions": [
{
"IpProtocol": "tcp",
"FromPort": 27017,
"ToPort": 27017,
"UserIdGroupPairs": [],
"IpRanges": [
{
"CidrIp": "10.20.30.50/32",
"Description": "App Server 1"
},
{
"CidrIp": "10.20.30.51/32",
"Description": "App Server 2"
}
]
}
]
}
]
}
4.1.2 多区域部署策略
+-------------------+
| VPC (us-east-1) |
| |
| +---------------+ |
| | MongoDB Nodes | |
| +---------------+ |
+-------------------+
|
| VPC Peering
|
+-------------------+
| VPC (us-west-2) |
| |
| +---------------+ |
| | Application | |
| +---------------+ |
+-------------------+
安全组配置:
- 仅允许通过VPC Peering连接
- 限制源IP为对端VPC的CIDR
- 仅开放必要端口
4.2 GCP防火墙规则
4.2.1 网络标签配置
bash
# 创建防火墙规则
gcloud compute firewall-rules create mongodb-access \
--network=default \
--action=ALLOW \
--direction=INGRESS \
--rules=tcp:27017 \
--source-ranges=10.20.30.50/32,10.20.30.100/32 \
--target-tags=mongodb-server
4.2.2 分层防火墙策略
| 层 | 规则 | 目标标签 |
|---|---|---|
| 应用层 | 允许应用服务器访问 | app-server → mongodb-server |
| 管理层 | 允许管理工作站访问 | admin-workstation → mongodb-server |
| 复制层 | 允许复制集成员访问 | mongodb-node → mongodb-node |
4.3 Azure网络安全组
4.3.1 NSG配置
powershell
# 创建NSG
$rule1 = New-AzNetworkSecurityRuleConfig -Name "Allow-App-Servers" `
-Description "Allow App Servers to MongoDB" `
-Access Allow `
-Protocol Tcp `
-Direction Inbound `
-Priority 100 `
-SourceAddressPrefix "10.20.30.50" `
-SourcePortRange "*" `
-DestinationAddressPrefix "*" `
-DestinationPortRange "27017"
$rule2 = New-AzNetworkSecurityRuleConfig -Name "Allow-Admin" `
-Description "Allow Admin Workstations" `
-Access Allow `
-Protocol Tcp `
-Direction Inbound `
-Priority 110 `
-SourceAddressPrefix "10.20.30.100" `
-SourcePortRange "*" `
-DestinationAddressPrefix "*" `
-DestinationPortRange "27017"
$nsg = New-AzNetworkSecurityGroup -ResourceGroupName "MongoDB-RG" `
-Location "eastus" `
-Name "MongoDB-NSG" `
-SecurityRules $rule1, $rule2
4.3.2 服务端点配置
powershell
# 配置服务端点
$vnet = Get-AzVirtualNetwork -Name "MongoDB-VNet" -ResourceGroupName "MongoDB-RG"
$subnet = Get-AzVirtualNetworkSubnetConfig -Name "MongoDB-Subnet" -VirtualNetwork $vnet
# 添加服务端点
$subnet = Add-AzVirtualNetworkSubnetConfig -Name "MongoDB-Subnet" `
-VirtualNetwork $vnet `
-AddressPrefix "10.0.0.0/24" `
-ServiceEndpoint "Microsoft.Storage" `
-NetworkSecurityGroup $nsg
# 更新虚拟网络
$vnet | Set-AzVirtualNetwork
五、高级网络隔离技术
5.1 VPC/私有网络配置
5.1.1 私有网络架构
+---------------------+ +---------------------+
| 应用VPC | | 数据VPC |
| | | |
| +-----------------+ | | +-----------------+ |
| | Application | | | | MongoDB Nodes | |
| | (Public Subnet) | | | | (Private Subnet)| |
| +-----------------+ | | +-----------------+ |
| | Load Balancer | | | | | |
| +-----------------+ | | | | |
+----------+----------+ +----------+----------+
| |
| VPC Peering |
| |
+----------+----------+ +----------+----------+
| 管理VPC (可选) | | 备份VPC (可选) |
| | | |
| +-----------------+ | | +-----------------+ |
| | Management | | | | Backup | |
| | Workstations | | | | System | |
| +-----------------+ | | +-----------------+ |
+---------------------+ +---------------------+
5.1.2 专用网络配置
yaml
# mongod.conf
net:
port: 27017
bindIp: 10.0.0.10
ssl:
mode: requireTLS
PEMKeyFile: /etc/mongodb/mongodb.pem
CAFile: /etc/mongodb/ca.crt
allowInvalidCertificates: false
5.2 网络分段策略
5.2.1 多层隔离架构
+---------------------+
| Internet |
+----------+----------+
|
v
+---------------------+ <-- DMZ (仅负载均衡)
| Load Balancer |
+----------+----------+
|
v
+---------------------+ <-- 应用层 (Web/应用服务器)
| Application Layer |
+----------+----------+
|
v
+---------------------+ <-- 数据层 (MongoDB服务器)
| Data Layer |
| (Private Network) |
+---------------------+
5.2.2 分段防火墙规则
bash
# 应用层到数据层规则
sudo ufw allow from 10.20.40.0/24 to any port 27017
# 管理层到数据层规则
sudo ufw allow from 10.20.50.0/24 to any port 27017
# 禁止其他所有访问
sudo ufw deny 27017/tcp
5.3 服务网格集成
5.3.1 Istio服务网格配置
yaml
# mongodb-gateway.yaml
apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
name: mongodb-gateway
spec:
servers:
- port:
number: 27017
name: mongo
protocol: MONGO
hosts:
- "mongodb.example.com"
selector:
istio: ingressgateway
yaml
# mongodb-virtual-service.yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: mongodb
spec:
hosts:
- "mongodb.example.com"
gateways:
- mongodb-gateway
tcp:
- match:
- port: 27017
route:
- destination:
host: mongodb-service
port:
number: 27017
5.3.2 网络策略
yaml
# mongodb-network-policy.yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: mongodb-access
spec:
podSelector:
matchLabels:
app: mongodb
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
project: app
podSelector:
matchLabels:
role: app-server
ports:
- protocol: TCP
port: 27017
六、安全最佳实践与常见错误
6.1 最小权限原则实施
6.1.1 服务账户网络限制
javascript
// 为服务账户配置严格的网络限制
db.createUser({
user: "app_service",
pwd: "ServicePassword123!",
roles: [
{ role: "readWrite", db: "appdb" }
],
authenticationRestrictions: [
{
clientSource: ["10.20.30.50/32"],
serverAddress: ["mongodb-app:27017"]
}
]
})
6.1.2 管理员账户限制
javascript
// 为管理员账户配置严格的网络限制
db.createUser({
user: "admin",
pwd: "AdminPassword123!",
roles: [
{ role: "root", db: "admin" }
],
authenticationRestrictions: [
{
clientSource: ["10.20.30.100/32"],
serverAddress: ["mongodb-admin:27017"]
}
]
})
6.2 常见配置错误与修复
| 错误 | 风险 | 修复方法 |
|---|---|---|
bindIp: 0.0.0.0 |
完全暴露 | 仅绑定到必要IP |
| 未配置防火墙 | 无保护层 | 配置系统防火墙 |
| 云安全组开放0.0.0.0/0 | 完全暴露 | 限制为特定IP |
| 未分离管理与应用访问 | 扩大攻击面 | 不同IP段访问 |
| 未使用TLS | 数据传输不安全 | 配置SSL/TLS |
6.2.1 危险配置示例
yaml
# DANGEROUS CONFIGURATION
net:
bindIp: 0.0.0.0
port: 27017
security:
authorization: disabled
6.2.2 安全配置示例
yaml
# SAFE CONFIGURATION
net:
bindIp: 127.0.0.1,10.20.30.10
port: 27017
ssl:
mode: requireTLS
PEMKeyFile: /etc/mongodb/server.pem
CAFile: /etc/mongodb/ca.crt
security:
authorization: enabled
keyFile: /etc/mongodb/keyfile
6.3 安全测试方法
6.3.1 外部扫描测试
bash
# 使用nmap扫描暴露面
nmap -sV -p 27017 <your-public-ip>
# 使用Shodan搜索
shodan host <your-public-ip>
6.3.2 内部连接测试
javascript
// 测试本地连接
mongo --eval "db.version()"
// 测试应用服务器连接
ssh app-server-1
mongo --host mongodb.example.com
// 测试未经授权的连接
ssh unauthorized-server
mongo --host mongodb.example.com
七、监控与审计网络访问
7.1 连接监控工具
7.1.1 MongoDB内置监控
javascript
// 实时连接监控
db.currentOp({ "active": true })
// 历史连接统计
db.getSiblingDB("local").system.profile.find().sort({ ts: -1 }).limit(10)
7.1.2 Prometheus监控配置
yaml
# mongodb_exporter 配置
rules:
- name: Network
rules:
- alert: UnauthorizedAccessAttempt
expr: mongodb_connections{state=" Unauthorized"} > 0
for: 1m
labels:
severity: critical
annotations:
summary: "Unauthorized MongoDB access attempt"
description: "Unauthorized access attempt detected from {{ $labels.remote_addr }}"
- alert: HighConnectionCount
expr: mongodb_current_connections > 100
for: 5m
labels:
severity: warning
annotations:
summary: "High MongoDB connection count"
description: "Current connections: {{ $value }} (threshold: 100)"
7.2 异常访问检测
7.2.1 异常访问模式检测
javascript
// 检测异常连接模式
function detectAnomalousConnections() {
const threshold = 5; // 5分钟内相同IP超过5次
const window = 5 * 60 * 1000; // 5分钟
const recentConnections = db.getSiblingDB("local").system.profile.find({
ts: { $gt: new Date(Date.now() - window) }
}).toArray();
const ipCounts = {};
recentConnections.forEach(conn => {
const ip = conn.remote.addr;
ipCounts[ip] = (ipCounts[ip] || 0) + 1;
});
const anomalies = Object.keys(ipCounts).filter(ip => ipCounts[ip] > threshold);
if (anomalies.length > 0) {
alertAnomalousConnections(anomalies, ipCounts);
}
return anomalies;
}
7.2.2 地理位置异常检测
javascript
// 检测非常规地理位置访问
function detectGeolocationAnomalies() {
const allowedRegions = ["US", "EU"];
const threshold = 3; // 1小时内超过3次非常规区域访问
const recentConnections = db.getSiblingDB("local").system.profile.find({
ts: { $gt: new Date(Date.now() - 60 * 60 * 1000) } // 1小时
}).toArray();
const regionCounts = {};
recentConnections.forEach(conn => {
const geoData = lookupGeo(conn.remote.addr);
const region = geoData ? geoData.country : "UNKNOWN";
if (!allowedRegions.includes(region)) {
regionCounts[region] = (regionCounts[region] || 0) + 1;
}
});
const anomalies = Object.keys(regionCounts).filter(region =>
regionCounts[region] > threshold
);
if (anomalies.length > 0) {
alertGeolocationAnomalies(anomalies, regionCounts);
}
return anomalies;
}
7.3 审计日志配置
7.3.1 网络访问审计配置
yaml
# mongod.conf
auditLog:
destination: file
format: JSON
path: /var/log/mongodb/network-audit.log
filter: |
{
"atype": {
"$in": ["login", "logout", "getCmdLineOpts", "connectionStatus"]
}
}
7.3.2 审计日志分析
javascript
// 分析网络访问审计日志
function analyzeNetworkAccess() {
const auditLog = db.getSiblingDB("admin").system.profile;
// 1. 检测异常登录时间
const offHours = auditLog.find({
"atype": "login",
"ts": {
"$expr": {
"$or": [
{ "$lt": [{ "$hour": "$ts" }, 7] },
{ "$gt": [{ "$hour": "$ts" }, 20] }
]
}
}
}).toArray();
// 2. 检测异常IP访问
const suspiciousIps = auditLog.aggregate([
{ $match: { "atype": "login" } },
{ $group: { _id: "$remote.addr", count: { $sum: 1 } } },
{ $match: { count: { $gt: 10 } } }
]).toArray();
// 3. 检测失败登录
const failedLogins = auditLog.find({
"result": { "$ne": 0 },
"ts": { "$gt": new Date(Date.now() - 24 * 60 * 60 * 1000) } // 24小时
}).toArray();
return {
offHoursLogins: offHours,
suspiciousIps: suspiciousIps,
failedLogins: failedLogins
};
}
八、结论与建议
8.1 实施路线图
-
评估阶段(1-3天):
- 扫描当前网络暴露面
- 识别所有访问MongoDB的IP
- 评估现有防火墙规则
-
规划阶段(3-5天):
- 确定安全IP白名单
- 设计网络分段策略
- 规划防火墙规则配置
-
实施阶段(2-4周):
- 配置MongoDB绑定IP
- 设置系统级防火墙
- 部署云平台安全组
- 验证配置有效性
-
持续优化(持续):
- 定期更新IP白名单
- 监控异常网络活动
- 定期进行安全测试
8.2 关键成功因素
| 因素 | 说明 | 实施建议 |
|---|---|---|
| 最小暴露 | 仅暴露必要接口 | 禁用bindIpAll |
| 多层防御 | 多重保护机制 | 网络层+应用层 |
| 持续验证 | 定期测试安全性 | 每月渗透测试 |
| 自动化 | 减少人为错误 | 脚本化配置管理 |
| 文档记录 | 满足合规要求 | 详细记录配置 |
关键提示 :安全不是目的地,而是旅程。网络配置需要随着业务发展和威胁环境变化而持续调整。定期审查网络配置,确保其与当前业务需求和安全态势保持一致。
8.3 安全成熟度评估
| 级别 | 特征 | 行动建议 |
|---|---|---|
| 初始 | 无网络限制 | 实施基础防火墙规则 |
| 可重复 | 有基本规则,但不一致 | 标准化配置模板 |
| 已定义 | 有文档化流程 | 实施自动化管理 |
| 已管理 | 定期审查,量化指标 | 建立安全基线 |
| 优化 | 预测性安全,自适应 | 实现AI辅助安全 |
附录:常用网络配置命令速查
bash
# 查看当前监听端口
sudo netstat -tuln | grep 27017
# 检查UFW状态
sudo ufw status verbose
# 检查iptables规则
sudo iptables -L -n -v
# 测试外部连接
nmap -p 27017 <your-public-ip>
# 检查MongoDB绑定IP
mongo --eval "db.adminCommand('getCmdLineOpts').parsed.net"
# 查看当前连接
mongo --eval "db.currentOp({ 'active': true })"
# 验证认证配置
mongo --eval "db.serverStatus().security"