概述
本文档提供针对公网域名、内网域名、内网IP的HTTPS URL证书有效期监控方案,支持在证书有效期低于30天时触发告警。涵盖以下三种监控系统:
- Prometheus + Blackbox Exporter + Alertmanager
- Zabbix
- 夜莺监控 (Nightingale)
一、Prometheus 方案
1.1 架构说明
- Blackbox Exporter: 负责探测HTTPS端点,获取SSL证书信息
- Prometheus: 采集Blackbox Exporter的指标
- Alertmanager: 处理告警规则,发送通知
1.2 安装 Blackbox Exporter
# 下载 Blackbox Exporter
wget https://github.com/prometheus/blackbox_exporter/releases/download/v0.25.0/blackbox_exporter-0.25.0.linux-amd64.tar.gz
tar xvfz blackbox_exporter-*.tar.gz
cd blackbox_exporter-*
# 创建配置文件 blackbox.yml
cat > blackbox.yml << 'EOF'
modules:
http_ssl:
prober: http
http:
method: GET
preferred_ip_protocol: "ip4"
tls: true
tls_config:
insecure_skip_verify: false
EOF
1.3 Prometheus 配置
编辑 prometheus.yml,添加Blackbox Exporter的scrape配置:
# prometheus.yml
global:
scrape_interval: 60s
scrape_configs:
- job_name: 'blackbox-ssl'
metrics_path: /probe
params:
module: [http_ssl]
static_configs:
- targets:
# 公网域名
- https://www.google.com
- https://github.com
# 内网域名
- https://internal.example.com
- https://jenkins.internal.com
# 内网IP
- https://192.168.1.100:8443
- https://10.0.0.50
relabel_configs:
- source_labels: [__address__]
target_label: __param_target
- source_labels: [__param_target]
target_label: instance
- target_label: __address__
replacement: 127.0.0.1:9115 # Blackbox Exporter地址
1.4 SSL 证书有效期告警规则
创建告警规则文件 ssl_cert_alerts.yml:
# ssl_cert_alerts.yml
groups:
- name: ssl_cert_alerts
rules:
# 证书有效期小于30天告警
- alert: SSLCertExpirySoon
expr: |
probe_ssl_earliest_cert_expiry - time() < 30 * 24 * 3600
for: 5m
labels:
severity: warning
annotations:
summary: "SSL证书即将过期 (instance {{ $labels.instance }})"
description: |
SSL证书将在 {{ printf "%.1f" (div (sub $value (time)) 86400)) }} 天后过期。
当前时间: {{ $labels.instance }}
到期时间: {{ $labels.cert_expiry | default "unknown" }}
# 证书有效期小于7天严重告警
- alert: SSLCertExpiryCritical
expr: |
probe_ssl_earliest_cert_expiry - time() < 7 * 24 * 3600
for: 5m
labels:
severity: critical
annotations:
summary: "SSL证书即将严重过期 (instance {{ $labels.instance }})"
description: |
SSL证书将在 {{ printf "%.1f" (div (sub $value (time)) 86400)) }} 天后过期!
请立即更新证书!
在 prometheus.yml 中引用告警规则:
yaml
复制
rule_files:
- "ssl_cert_alerts.yml"
1.5 Alertmanager 告警配置
yaml
复制
# alertmanager.yml
global:
smtp_smarthost: 'smtp.example.com:587'
smtp_from: 'alert@example.com'
route:
group_by: ['alertname', 'severity']
group_wait: 10s
group_interval: 10s
repeat_interval: 12h
receiver: 'email-notifications'
receivers:
- name: 'email-notifications'
email_configs:
- to: 'admin@example.com'
subject: '【告警】{{ .GroupLabels.alertname }}'
body: |
{{ range .Alerts }}
告警: {{ .Annotations.summary }}
详情: {{ .Annotations.description }}
时间: {{ .StartsAt }}
{{ end }}
1.6 验证指标
访问 Blackbox Exporter 进行手动测试:
bash
复制
curl "http://localhost:9115/probe?target=https://www.google.com&module=http_ssl"
查看 Prometheus 指标:
probe_ssl_earliest_cert_expiry
二、Zabbix 方案
2.1 方案一:使用 Web 场景监控
创建 Web 场景
- 进入 Zabbix 前端,选择 Configuration → Hosts
- 创建或选择一个主机,点击 Web
- 点击 Create web scenario
配置示例:
| 参数 | 值 |
|---|---|
| Name | SSL Certificate Check |
| Application | SSL Monitoring |
| Update interval | 1h |
添加步骤:
| Name | URL | Timeout |
|---|---|---|
| Check SSL | https://your-domain.com | 30s |
创建监控项和触发器
使用 Zabbix 内置的 {SSL.CERT.EXPIRY} 宏或通过自定义脚本:
2.2 方案二:自定义脚本 + Zabbix Agent(推荐)
创建脚本 /etc/zabbix/scripts/check_ssl_cert.sh:
bash
复制
#!/bin/bash
# check_ssl_cert.sh - 检查SSL证书有效期
# 用法: ./check_ssl_cert.sh <host> <port>
HOST="$1"
PORT="${2:-443}"
if [ -z "$HOST" ]; then
echo "Usage: $0 <host> [port]"
exit 1
fi
# 获取证书过期时间
CERT_EXPIRY=$(echo | openssl s_client -servername "$HOST" -connect "$HOST:$PORT" 2>/dev/null | \
openssl x509 -noout -enddate 2>/dev/null | \
sed 's/notAfter=//')
if [ -z "$CERT_EXPIRY" ]; then
echo "Failed to get certificate info"
exit 1
fi
# 转换为时间戳
EXPIRY_TIMESTAMP=$(date -d "$CERT_EXPIRY" +%s 2>/dev/null || date -j -f "%b %d %T %Z %Y" "$CERT_EXPIRY" +%s 2>/dev/null)
CURRENT_TIMESTAMP=$(date +%s)
if [ -z "$EXPIRY_TIMESTAMP" ]; then
echo "Failed to parse expiry date"
exit 1
fi
# 计算剩余天数
DAYS_LEFT=$(( ($EXPIRY_TIMESTAMP - $CURRENT_TIMESTAMP) / 86400 ))
echo "$DAYS_LEFT"
# 退出码:0=正常, 1=警告(<30天), 2=严重(<7天)
if [ "$DAYS_LEFT" -lt 7 ]; then
exit 2
elif [ "$DAYS_LEFT" -lt 30 ]; then
exit 1
else
exit 0
fi
设置权限:
bash
复制
chmod +x /etc/zabbix/scripts/check_ssl_cert.sh
配置 Zabbix Agent
编辑 /etc/zabbix/zabbix_agentd.conf 或创建独立的配置文件:
# /etc/zabbix/zabbix_agentd.d/ssl_cert.conf
UserParameter=ssl.cert.daysleft[*],/etc/zabbix/scripts/check_ssl_cert.sh "$1" "$2"
UserParameter=ssl.cert.expiry[*],echo | openssl s_client -servername "$1" -connect "$1:$2" 2>/dev/null | openssl x509 -noout -enddate 2>/dev/null | sed 's/notAfter=//'
重启 Zabbix Agent:
systemctl restart zabbix-agent
在 Zabbix 前端配置监控
- 创建监控项 (Items):
| 名称 | 键值 | 类型 | 更新间隔 |
|---|---|---|---|
| SSL证书剩余天数 - google.com | ssl.cert.daysleft[www.google.com,443] |
Zabbix agent | 1h |
| SSL证书剩余天数 - 内网IP | ssl.cert.daysleft[192.168.1.100,8443] |
Zabbix agent | 1h |
- 创建触发器 (Triggers):
| 名称 | 表达式 | 严重性 |
|---|---|---|
| SSL证书即将过期 (google.com) | {Host:ssl.cert.daysleft[www.google.com,443].last()}<30 |
警告 |
| SSL证书严重过期 (google.com) | {Host:ssl.cert.daysleft[www.google.com,443].last()}<7 |
严重 |
触发器表达式示例:
{SSL Monitor:ssl.cert.daysleft[www.google.com,443].last()}<30
配置告警媒介
进入 Administration → Media types,配置邮件/短信/Webhook等告警方式。
2.3 使用 Zabbix 官方模板
Zabbix 提供了 SSL 证书监控模板,可以直接导入使用:
- 下载模板:https://www.zabbix.com/integrations/ssl_certificate
- 导入模板:Configuration → Templates → Import
- 将模板链接到主机
三、夜莺监控 (Nightingale) 方案
3.1 架构说明
夜莺支持多种数据源,可以利用:
- Prometheus 数据源:复用上面的 Prometheus 方案
- Categraf:夜莺自带的采集器,支持 SSL 证书采集
- 自定义脚本 :通过
script采集插件
3.2 方案一:使用 Categraf 采集 SSL 证书
Categraf 自带 ssl_cert 采集插件。
配置 Categraf
编辑 conf/input.ssl_cert/ssl_cert.toml:
[[instances]]
# 公网域名
targets = [
"https://www.google.com",
"https://github.com",
]
# 内网域名
internal_targets = [
"https://internal.example.com",
"https://jenkins.internal.com",
]
# 内网IP
ip_targets = [
"https://192.168.1.100:8443",
"https://10.0.0.50:443",
]
# 超时时间
timeout = "10s"
# 忽略证书验证(用于自签名证书)
# insecure_skip_verify = false
# 标签
labels = { job = "ssl_cert_monitoring" }
启动 Categraf:
./categraf --configs /path/to/conf
采集到的指标
Categraf 会采集以下指标:
ssl_cert_days_left- 证书剩余天数ssl_cert_expiry_timestamp- 证书过期时间戳
3.3 方案二:复用 Prometheus Blackbox Exporter
夜莺可以直接接入 Prometheus 作为数据源:
- 在夜莺的 基础设施 → 数据源 中添加 Prometheus 数据源
- 使用前面 Prometheus 方案中配置的 Blackbox Exporter
3.4 配置夜莺告警规则
进入夜莺 告警管理 → 告警规则,创建告警规则:
告警规则配置
规则名称:SSL证书有效期告警
级别:警告
规则:
promql
复制
ssl_cert_days_left < 30
备注(告警模板):
告警: SSL证书即将过期
证书地址: {{ $labels.instance }}
剩余天数: {{ $value }} 天
告警时间: {{ timestamp }}
请及时更新证书!
严重告警规则
规则名称:SSL证书严重过期告警
级别:严重
规则:
ssl_cert_days_left < 7
3.5 配置告警通知渠道
进入 告警管理 → 通知设置:
支持的通知方式:
- 邮件
- 钉钉
- 企业微信
- 飞书
- Webhook
- Slack
- Telegram
示例(钉钉配置):
{
"msgtype": "markdown",
"markdown": {
"title": "SSL证书告警",
"text": "### SSL证书即将过期\n\n**地址**: {{ $labels.instance }}\n**剩余天数**: {{ $value }} 天\n**告警级别**: {{ $labels.severity }}"
}
}
3.6 夜莺告警规则完整示例
yaml
复制
四、方案对比
| 特性 | Prometheus | Zabbix | 夜莺监控 |
|---|---|---|---|
| 部署复杂度 | 中等 | 低 | 低 |
| 内网IP支持 | ✅ | ✅ | ✅ |
| 公网域名支持 | ✅ | ✅ | ✅ |
| 告警灵活性 | 高 | 高 | 高 |
| 可视化 | Grafana | 内置 | 内置 |
| 通知渠道 | 丰富 | 丰富 | 丰富 |
| 推荐场景 | 云原生/K8s | 传统运维 | 云原生/传统混合 |
五、注意事项
- 内网证书 :自签名证书可能需要设置
insecure_skip_verify: true - 证书链:确保监控工具能获取完整的证书链信息
- 权限:执行脚本的用户需要有 openssl 命令访问权限
- 频率:建议监控间隔设置为1小时或更长,避免频繁探测
- 告警抑制:防止证书过期后持续告警,可设置告警恢复或抑制规则
六、快速验证脚本
提供一个通用的证书检查脚本,可用于任何监控系统:
#!/bin/bash
# check_ssl_expiry.sh - 通用SSL证书检查
# 支持域名和IP
check_ssl() {
local target="$1"
local port="${2:-443}"
# 提取主机名(如果是URL)
local host=$(echo "$target" | sed 's|https\?://||' | sed 's|/.*||')
# 获取证书信息
local cert_info=$(echo | timeout 10 openssl s_client -connect "$host:$port" -servername "$host" 2>/dev/null)
if [ -z "$cert_info" ]; then
echo "ERROR: Cannot connect to $host:$port"
return 1
fi
local expiry_date=$(echo "$cert_info" | openssl x509 -noout -enddate 2>/dev/null | cut -d= -f2)
local expiry_ts=$(date -d "$expiry_date" +%s 2>/dev/null)
local now_ts=$(date +%s)
local days_left=$(( ($expiry_ts - $now_ts) / 86400 ))
echo "Host: $host:$port"
echo "Expiry: $expiry_date"
echo "Days left: $days_left"
if [ "$days_left" -lt 7 ]; then
echo "CRITICAL: Certificate expires in $days_left days!"
return 2
elif [ "$days_left" -lt 30 ]; then
echo "WARNING: Certificate expires in $days_left days"
return 1
else
echo "OK: Certificate is valid for $days_left more days"
return 0
fi
}
# 批量检查
targets=(
"https://www.google.com"
"https://github.com"
"192.168.1.100:8443"
)
for target in "${targets[@]}"; do
echo "========================"
check_ssl "$target"
echo ""
done
文档生成时间: 2026-05-01