安全审计这件事,最折磨人的不是标准有多严,而是检查本身是"一次性"的。SSH 上去逐台看 SELinux 状态、防火墙规则、过期账户、密码策略——几十台机器做完,人已经麻了。更致命的是:今天查完合规,明天有人改了一行配置,你根本不知道。
security-collector-exporter 的思路很简单:把这些散落在各处的安全配置项变成 Prometheus 指标,审计从"人肉巡检"变成"持续可观测"。
审计项怎么变成指标
Linux 安全审计覆盖的东西很杂,但大致可以归为几类:
| 类别 | 典型检查项 | 指标化思路 |
|---|---|---|
| 访问控制 | SELinux 模式、AppArmor 状态 | 用 1/0 表示 enforcing/permissive/disabled |
| 网络边界 | iptables/nftables 是否加载、默认策略 | 规则数量 + 默认策略枚举 |
| 身份认证 | SSH PermitRootLogin、PasswordAuthentication | 布尔指标,1 = 不合规 |
| 账户管理 | 过期账户数、空密码账户数 | 直接暴露计数 |
| 密码策略 | 最小长度、最大天数 | 数值指标 |
关键设计决策:不合规的项用 1 表示,合规用 0。这样在 Prometheus 里一条 sum(security_ssh_permit_root_login == 1) 就能立刻知道有多少台机器开了 root 登录,告警规则也直观。
部署与采集配置
Exporter 本身是个轻量 Go 二进制,跑在被监控节点上,定期读取本地配置文件和系统状态,暴露 /metrics 端点。下面是一个最小化部署方案。
先在目标机器上启动 exporter(以 systemd 方式为例):
# 下载二进制(假设版本 v0.3.0)
curl -L -o /usr/local/bin/security-collector-exporter \
https://github.com/ownObservability/security-collector-exporter/releases/download/v0.3.0/security-collector-exporter-linux-amd64
chmod +x /usr/local/bin/security-collector-exporter
# 写 systemd unit
cat > /etc/systemd/system/security-collector-exporter.service << 'EOF'
[Unit]
Description=Security Collector Exporter for Prometheus
After=network.target
[Service]
ExecStart=/usr/local/bin/security-collector-exporter \
--web.listen-address=0.0.0.0:9987 \
--config.path=/etc/security-collector/config.yaml
Restart=on-failure
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable --now security-collector-exporter
Exporter 的采集配置文件 /etc/security-collector/config.yaml,可以指定要检查哪些模块:
modules:
ssh:
enabled: true
config_path: /etc/ssh/sshd_config
selinux:
enabled: true
firewall:
enabled: true
backend: nftables # 或 iptables
accounts:
enabled: true
check_expired: true
check_empty_password: true
password_policy:
enabled: true
login_defs_path: /etc/login.defs
然后在 Prometheus 的 prometheus.yml 里加上采集目标:
scrape_configs:
- job_name: 'security-collector'
scrape_interval: 60s # 安全配置不需要秒级采集
static_configs:
- targets:
- '10.0.1.11:9987'
- '10.0.1.12:9987'
- '10.0.1.13:9987'
labels:
cluster: 'prod'
如果节点多,配合 node_exporter 的服务发现方式(Consul、Kubernetes SD 等)统一管理就行,端口和 job 名区分开即可。
指标出来后怎么用
Exporter 暴露的指标大致长这样(curl localhost:9987/metrics 截取):
security_selinux_mode{mode="enforcing"} 1
security_selinux_mode{mode="permissive"} 0
security_selinux_mode{mode="disabled"} 0
security_ssh_permit_root_login 1
security_ssh_password_auth 0
security_account_expired_total 3
security_account_empty_password_total 0
security_password_min_length 8
security_password_max_days 90
几个立竿见影的用法:
1. 不合规计数面板
# 有多少台机器 SSH 允许 root 登录
sum(security_ssh_permit_root_login == 1)
# 有多少台机器 SELinux 不是 enforcing
sum(security_selinux_mode{mode="enforcing"} == 0)
2. 告警规则——配置漂移立刻发现
groups:
- name: security_compliance
rules:
- alert: SSHPermitRootLoginEnabled
expr: security_ssh_permit_root_login == 1
for: 5m
labels:
severity: warning
team: infra
annotations:
summary: "SSH 允许 root 登录"
description: "{{ $labels.instance }} 的 sshd_config 开启了 PermitRootLogin"
- alert: SELinuxNotEnforcing
expr: security_selinux_mode{mode="enforcing"} == 0
for: 10m
labels:
severity: critical
annotations:
summary: "SELinux 未处于 enforcing 模式"
description: "{{ $labels.instance }} 当前 SELinux 状态不是 enforcing"
- alert: ExpiredAccountsExist
expr: security_account_expired_total > 0
for: 1h
labels:
severity: warning
annotations:
summary: "存在过期账户"
description: "{{ $labels.instance }} 有 {{ $value }} 个过期账户"
3. 审计报告一键生成
不再需要逐台 SSH,一条 PromQL 就能出全集群报告:
# 每台机器的合规得分(合规项数 / 总检查项数)
# 假设 exporter 还暴露了 security_compliance_total 和 security_compliance_passed
security_compliance_passed / security_compliance_total
在 Grafana 里做成表格面板,按 instance 排序,低于 0.8 的标红——审计报告的雏形就有了。
上手前的几个考虑
- 采集频率别太高。安全配置变更频率远低于业务指标,60s 甚至 5min 都够用,没必要给 Prometheus 和目标机器加压。
- 指标设计要稳定。一旦 label 结构定下来就尽量别改,Prometheus 的历史数据对 label 变化是不友好的。新增检查项加新指标,不要在旧指标上塞新 label。
- 和 node_exporter 共存没问题。端口分开(node_exporter 默认 9100,这个用 9987),job 名分开,互不干扰。
- 敏感信息别进指标。不要把密码哈希、账户名等丢进 metric label,Prometheus 数据谁都能查。只暴露"是否合规"和"数量",具体账户名留在告警 annotation 或单独的审计日志里。
- 配置漂移才是核心价值。一次性审计用 Ansible 也能做,这个 exporter 的真正意义是:改了配置 5 分钟内告警就到,不用等下一次人工巡检。
从一台机器开始试——部署 exporter、加 scrape 配置、写两条告警规则,跑一天看数据。合规这件事,持续看见比偶尔检查有用得多。