适用场景
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 的暴露面控制在可接受范围。