17.10.1 Prometheus安全模型与威胁面
Prometheus的安全模型以“内网可信、边界防护”为基础设计,核心组件默认无强认证能力,适合部署在受控网络中。安全建设重点在于:网络隔离、访问控制、传输加密、暴露面收敛与查询资源保护。
原理草图(信任边界与威胁面):
主要威胁面与风险点(含可验证示例):
- 未授权访问与数据泄露:Prometheus/Alertmanager/Grafana暴露在公网时可被任意查询。
例:未鉴权时直接访问 /api/v1/labels 可枚举服务标签。
- 指标注入与数据污染:Exporter缺乏鉴权,攻击者可伪造指标。
例:伪造 up=0 导致误报警。
- 配置泄露:prometheus.yml、规则文件含敏感目标与Webhook地址。
- 拒绝服务与资源耗尽:高频、长范围PromQL导致CPU/内存飙升。
- 横向移动:通过Prometheus探测内网目标可达性与服务版本。
安全基线与最小暴露面实践:
- 仅内网监听:Prometheus/Alertmanager监听内网IP,外部入口统一走网关。
- 默认拒绝:安全组/防火墙只放行网关与可信来源。
- TLS加密:对外访问路径强制TLS。
- 查询限制:限制并发、最大查询时间与样本数。
- 配置权限:配置文件最小权限,避免明文凭证。
最小可执行示例:仅内网监听 + 防火墙收敛
# 1) Prometheus仅监听内网IP(假设 10.0.0.10)
cat >/etc/systemd/system/prometheus.service.d/override.conf <<'EOF'
[Service]
ExecStart=
ExecStart=/usr/local/bin/prometheus \
--config.file=/etc/prometheus/prometheus.yml \
--web.listen-address=10.0.0.10:9090 \
--web.enable-lifecycle
EOF
systemctl daemon-reload && systemctl restart prometheus
# 2) 防火墙仅放行网关(10.0.0.5)访问9090
firewall-cmd --permanent --add-rich-rule='rule family=ipv4 source address=10.0.0.5 port port=9090 protocol=tcp accept'
firewall-cmd --permanent --add-port=9090/tcp --zone=drop
firewall-cmd --reload
预期效果:Prometheus仅可被10.0.0.5访问,其他来源连接被拒绝。
示例:查询限制与资源保护(Prometheus启动参数)
# /etc/systemd/system/prometheus.service.d/override.conf
[Service]
ExecStart=
ExecStart=/usr/local/bin/prometheus \
--config.file=/etc/prometheus/prometheus.yml \
--web.listen-address=10.0.0.10:9090 \
--query.max-concurrency=10 \
--query.max-samples=5000000 \
--query.timeout=30s
命令解释:
- --query.max-concurrency:限制并发查询,防止瞬时打爆CPU。
- --query.max-samples:限制单次查询的最大样本数。
- --query.timeout:限制单次查询执行时间。
示例:检测暴露面与快速自检
# 1) 从非授权主机测试是否能访问
curl -s http://10.0.0.10:9090/-/healthy || echo "拒绝访问"
# 2) 检测是否意外暴露到公网
ss -lntp | grep 9090
# 3) 检测label暴露情况(应只在内网可访问)
curl -s http://10.0.0.10:9090/api/v1/labels | head
排错要点:
- 端口仍可公网访问:检查 --web.listen-address 是否为 0.0.0.0,以及安全组/防火墙规则是否生效。
- Prometheus无法拉取目标:检查目标是否只允许网关访问导致抓取失败,需对Prometheus采集IP放行。
- 查询被拒绝或超时:检查 --query.* 参数是否过小,调整并验证。
练习:
1. 将Prometheus从 0.0.0.0:9090 改为内网监听,并使用防火墙仅允许10.0.0.5访问,验证非授权主机无法访问。
2. 构造一个高消耗PromQL(如 sum_over_time(rate(container_cpu_usage_seconds_total[1m])[6h:10s])),观察在设置 --query.timeout=5s 后的行为。
3. 列出 Prometheus 可能暴露的API路径(如 /api/v1/labels、/api/v1/series),并确认仅能从网关访问。