Prometheus 安全加固实战:未授权访问防护配置指南

适用场景

Prometheus 安全加固适用于所有暴露监控服务的企业环境:默认 Prometheus 监听 0.0.0.0:9090 且无任何认证,公网或内网攻击者可直接查询业务指标、查看目标配置甚至触发远程加载规则文件(–web.enable-remote-write-receiver 开启时风险更大)。本文方案面向:监控服务对外可达的生产环境、需要满足等保对管理接口认证要求的场景,以及希望统一入口管理多个 Prometheus 实例的团队。

前置条件

  • 已部署 Prometheus 2.30+(本文命令基于 2.45+ 验证)
  • Prometheus 服务所在主机具备 openssl 与 htpasswd 工具(apache2-utils 或 httpd-tools 包)
  • 预留域名或直接使用 IP + HTTPS 端口(默认 9090)
  • 如需反向代理方案,预先安装 Nginx 1.18+

原理说明

Prometheus 自身不提供用户认证,官方推荐通过三层手段加固:第一层用 basic_auth 配置让 Prometheus 在 /metrics 与 /-/reload 等接口启用 HTTP Basic 认证;第二层启用 –web.config.file 指定的 TLS 证书,把明文 HTTP 升级为 HTTPS 加密传输;第三层在反向代理层再加一道访问控制并隐藏管理接口。此外,Prometheus 的 –web.enable-lifecycle 参数允许通过 HTTP POST /-/reload 重载配置,若不加保护等于把配置控制权交给攻击者,必须与认证配合使用。

操作步骤

步骤一:生成密码哈希与 TLS 证书

# 1) 生成 Basic Auth 密码哈希(输入两次密码,记录输出)
htpasswd -nBC 12 "" | tr -d ':\n'

# 2) 生成自签名证书(生产环境建议使用正式证书)
mkdir -p /etc/prometheus/certs
openssl req -newkey rsa:2048 -nodes \
  -keyout /etc/prometheus/certs/prometheus.key \
  -out /etc/prometheus/certs/prometheus.csr \
  -subj "/CN=prometheus.example.com"
openssl x509 -req -in /etc/prometheus/certs/prometheus.csr \
  -signkey /etc/prometheus/certs/prometheus.key \
  -out /etc/prometheus/certs/prometheus.crt -days 365

步骤二:创建 web 配置文件

将上一步生成的哈希写入 /etc/prometheus/web.yml:

# /etc/prometheus/web.yml
basic_auth_users:
  admin: $2y$12$K0iH...(粘贴步骤一的 bcrypt 哈希)
tls_server_config:
  cert_file: /etc/prometheus/certs/prometheus.crt
  key_file: /etc/prometheus/certs/prometheus.key
  client_auth_type: "NoClientCert"

步骤三:启动参数启用认证与 TLS

# 修改 systemd 单元 /etc/systemd/system/prometheus.service 的 ExecStart
ExecStart=/usr/local/bin/prometheus \
  --config.file=/etc/prometheus/prometheus.yml \
  --web.config.file=/etc/prometheus/web.yml \
  --web.listen-address=0.0.0.0:9090

systemctl daemon-reload && systemctl restart prometheus

步骤四:反向代理方案(可选,多实例统一入口)

# /etc/nginx/conf.d/prometheus.conf
server {
    listen 443 ssl;
    server_name prometheus.example.com;
    ssl_certificate     /etc/prometheus/certs/prometheus.crt;
    ssl_certificate_key /etc/prometheus/certs/prometheus.key;

    location / {
        auth_basic "Prometheus";
        auth_basic_user_file /etc/nginx/.htpasswd;
        # 只允许内网网段访问
        allow 10.0.0.0/8;
        deny all;
        proxy_pass http://127.0.0.1:9090;
        proxy_set_header Authorization $http_authorization;
    }
}
nginx -t && systemctl reload nginx

配置验证

# 1) 无凭据访问应返回 401
curl -i http://127.0.0.1:9090/metrics | head -1
# 期望输出:HTTP/1.1 401 Unauthorized

# 2) 携带凭据访问正常返回
curl -u admin:密码 https://prometheus.example.com/metrics | head -5

# 3) 验证 TLS 证书生效
openssl s_client -connect 127.0.0.1:9090 -servername prometheus.example.com 2>/dev/null | grep -i subject

常见问题

FAQ 1:配置了 basic_auth 后,抓取目标(node_exporter)还能用吗?

Prometheus 的 basic_auth 只保护 Web UI 与管理接口,不影响 Prometheus 主动拉取 exporter 指标。若 exporter 自身也启用了认证,需在 prometheus.yml 的 scrape_config 中同步配置:

scrape_configs:
- job_name: node
  static_configs: [{ targets: ["10.0.0.5:9100"] }]
  basic_auth:
    username: exporter_user
    password: exporter_pass

FAQ 2:–web.enable-remote-write-receiver 和 –web.enable-lifecycle 要不要开?

两个参数都会扩大攻击面,默认应保持关闭。–web.enable-lifecycle 仅在确实需要 HTTP 热重载时开启,并确保 basic_auth 已生效;–web.enable-remote-write-receiver 仅在需要接受 remote write 推送(如 Prometheus 联邦或 agent 模式)时开启,且建议通过防火墙仅放行可信来源。若开启后 401 验证失败,检查 web.yml 中 bcrypt 哈希是否以 $2y$ 开头(htpasswd -B 输出为 $2y$)。

总结

Prometheus 未授权访问是监控体系中最常见的真实风险,本文通过 Basic Auth + TLS + 可选反向代理三层加固,将默认裸奔的 9090 端口收敛为认证访问的 HTTPS 服务。落地时注意三点:密码哈希必须用 -B 指定 bcrypt、验证时先确认 401 再确认 200、远程写入与管理接口按需最小化开启,即可把 Prometheus 的暴露面控制在可接受范围。