SSL 证书一旦过期,浏览器会直接显示“不安全”或“连接已阻断”,导致网站无法正常访问,用户流失严重。手动检查证书有效期非常容易遗忘,因此需要一套自动化的监控提醒机制。本教程将教你使用三种主流方法配置证书到期提醒,涵盖服务器端脚本、第三方监控平台以及企业微信/钉钉/邮件推送,确保证书到期前30天、7天、1天都能收到告警。
---
## 前置准备
- 一台Linux服务器(CentOS 7/8、Ubuntu 20.04/22.04均可)或Windows Server(本教程以Linux为例)
- 服务器上已安装OpenSSL(一般系统自带,可通过`openssl version`验证)
- 一个用于接收告警的邮箱(支持SMTP发送)或企业微信机器人Webhook地址
- 如果使用第三方监控平台,需要注册UptimeRobot或Pingdom账号(免费版即可)
- 基本的命令行操作能力(会使用vim/nano编辑文件、crontab设置定时任务)
---
## 分步操作步骤
### 方法一:使用Shell脚本 + 邮件告警(最通用,适合所有Linux服务器)
**1. 创建证书检查脚本**
登录服务器,切换到`/usr/local/bin`目录(或其他自定义脚本目录),创建一个名为`ssl_check.sh`的文件:
```bash
cd /usr/local/bin
sudo vim ssl_check.sh
```
**2. 写入核心检查逻辑**
在脚本中粘贴以下内容(注意替换域名和邮箱):
```bash
#!/bin/bash
# 配置部分 - 根据实际情况修改
DOMAINS=("example.com" "www.example.com" "api.example.com") # 要监控的域名列表
THRESHOLD_DAYS=30 # 提前多少天开始告警
SMTP_SERVER="smtp.qq.com"
SMTP_PORT=587
SMTP_USER="your_email@qq.com"
SMTP_PASS="你的SMTP授权码" # 不是QQ密码,是开启SMTP后生成的授权码
ALERT_EMAIL="admin@yourcompany.com" # 接收告警的邮箱
# 函数:发送邮件
send_mail() {
local subject="$1"
local body="$2"
echo -e "Subject: $subject\n\n$body" | msmtp --account=default -t "$ALERT_EMAIL"
}
# 遍历每个域名
for domain in "${DOMAINS[@]}"; do
# 获取证书过期时间(秒级时间戳)
expiry_date=$(echo | openssl s_client -servername "$domain" -connect "$domain":443 2>/dev/null | openssl x509 -noout -enddate 2>/dev/null | cut -d= -f2)
if [ -z "$expiry_date" ]; then
echo "[$(date)] $domain: 无法获取证书信息,可能域名未指向本机或端口不通" >> /var/log/ssl_check.log
continue
fi
# 将过期时间转为时间戳
expiry_timestamp=$(date -d "$expiry_date" +%s 2>/dev/null)
if [ -z "$expiry_timestamp" ]; then
echo "[$(date)] $domain: 日期解析失败,原始日期:$expiry_date" >> /var/log/ssl_check.log
continue
fi
# 当前时间戳
current_timestamp=$(date +%s)
# 计算剩余天数
remaining_days=$(( (expiry_timestamp - current_timestamp) / 86400 ))
# 判断是否需要告警
if [ $remaining_days -le 0 ]; then
send_mail "⚠️ 紧急:$domain SSL证书已过期" "域名 $domain 的SSL证书已于 $expiry_date 过期,请立即更新!"
elif [ $remaining_days -le $THRESHOLD_DAYS ]; then
send_mail "⚠️ 提醒:$domain SSL证书将在 $remaining_days 天后过期" "域名 $domain 的SSL证书将于 $expiry_date 过期,剩余 $remaining_days 天,请安排更新。"
echo "[$(date)] $domain: 剩余 $remaining_days 天,已发送提醒邮件" >> /var/log/ssl_check.log
else
echo "[$(date)] $domain: 剩余 $remaining_days 天,正常" >> /var/log/ssl_check.log
fi
done
```
**3. 安装邮件发送工具msmtp**
大多数Linux发行版不自带msmtp,需要手动安装:
```bash
# CentOS/RHEL
sudo yum install epel-release -y
sudo yum install msmtp msmtp-mta -y
# Ubuntu/Debian
sudo apt update
sudo apt install msmtp msmtp-mta -y
```
**4. 配置msmtp**
创建配置文件`~/.msmtprc`:
```bash
vim ~/.msmtprc
```
写入以下内容(以QQ邮箱为例,其他邮箱修改SMTP地址和端口):
```
defaults
auth on
tls on
tls_trust_file /etc/ssl/certs/ca-certificates.crt
account default
host smtp.qq.com
port 587
from your_email@qq.com
user your_email@qq.com
password your_smtp_authorization_code
```
保存后设置权限(密码明文存储,必须限制访问):
```bash
chmod 600 ~/.msmtprc
```
**5. 测试脚本**
先手动运行脚本测试:
```bash
chmod +x /usr/local/bin/ssl_check.sh
bash /usr/local/bin/ssl_check.sh
```
如果配置正确,你会收到测试邮件(如果当前证书剩余天数小于30天)。同时检查日志文件:
```bash
cat /var/log/ssl_check.log
```
如果出现“连接超时”或“证书获取失败”,请确认域名能正常通过443端口访问。
**6. 设置定时任务(每天检查一次)**
编辑crontab:
```bash
crontab -e
```
添加以下行(每天上午9点执行):
```
0 9 * * * /bin/bash /usr/local/bin/ssl_check.sh
```
保存后,用`crontab -l`验证是否生效。如果想测试定时任务是否正常运行,可以临时设置一个近期的执行时间(例如下一分钟),然后观察日志。
---
### 方法二:使用UptimeRobot免费监控(无需服务器,只需域名)
**1. 注册并登录UptimeRobot**
访问[uptimerobot.com](https://uptimerobot.com),使用邮箱注册免费账号。免费版支持50个监控器,每个监控器可设置5个告警联系人。
**2. 添加SSL证书监控**
登录后点击右上角“Add New Monitor”,选择监控类型为“Port”,因为我们要监控443端口。填写以下信息:
- **Friendly Name**:输入一个易识别的名称,例如“公司官网SSL”
- **URL**:输入你的域名,例如`example.com`(不要加https://)
- **Port**:选择`443 - HTTPS`
- **Monitoring Interval**:选择`5 minutes`(免费版最小间隔5分钟)
**3. 配置告警联系人**
点击“Add Alert Contact”,选择通知方式:
- **Email**:输入接收告警的邮箱,UptimeRobot会发送验证邮件,点击确认。
- **SMS**:需要付费,不推荐。
- **Webhook**:可以对接企业微信、钉钉机器人(需要自定义配置)。
建议至少添加一个邮箱联系人,并勾选“Send alerts when SSL certificate expires”。
**4. 设置SSL到期提醒阈值**
在监控器编辑页面,找到“SSL Certificate Expiry”部分:
- 勾选“Monitor SSL Certificate Expiry”
- 设置提醒天数:建议填写`30`(提前30天开始告警)
- 选择告警联系人:勾选刚才添加的联系人
**5. 验证监控是否生效**
保存后,等待5-10分钟,UptimeRobot会开始检测。你可以点击监控器名称,查看“SSL Certificate”选项卡,里面会显示证书签发机构、有效期、剩余天数。如果证书快到期,系统会自动发送邮件。
---
### 方法三:使用企业微信机器人 + Python脚本(适合团队协作)
**1. 创建企业微信群机器人**
打开企业微信,进入一个群聊,点击右上角“...”->“群机器人”->“添加”->“新机器人”,给机器人起名(例如“证书监控”),获取Webhook地址(格式类似`https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxxxx`)。
**2. 编写Python监控脚本**
在服务器上创建`ssl_wechat.py`:
```bash
vim /usr/local/bin/ssl_wechat.py
```
粘贴以下代码(需要Python3环境,一般系统自带):
```python
#!/usr/bin/env python3
import subprocess
import json
import urllib.request
import datetime
import sys
# 配置部分
DOMAINS = ["example.com", "www.example.com"] # 监控域名列表
WEBHOOK_URL = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=你的key" # 替换为实际key
THRESHOLD_DAYS = 30 # 提前告警天数
def get_cert_expiry(domain):
"""通过openssl获取证书过期时间"""
cmd = f"echo | openssl s_client -servername {domain} -connect {domain}:443 2>/dev/null | openssl x509 -noout -enddate"
result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
if result.returncode != 0:
return None
# 输出格式:notAfter=Jan 15 23:59:59 2025 GMT
expiry_str = result.stdout.strip().replace("notAfter=", "")
try:
expiry_date = datetime.datetime.strptime(expiry_str, "%b %d %H:%M:%S %Y %Z")
return expiry_date
except:
return None
def send_wechat_message(content):
"""发送消息到企业微信群"""
data = {
"msgtype": "markdown",
"markdown": {
"content": content
}
}
req = urllib.request.Request(
url=WEBHOOK_URL,
data=json.dumps(data).encode("utf-8"),
headers={"Content-Type": "application/json"}
)
try:
response = urllib.request.urlopen(req)
return response.status == 200
except Exception as e:
print(f"发送消息失败: {e}")
return False
def main():
alerts = []
for domain in DOMAINS:
expiry = get_cert_expiry(domain)
if expiry is None:
alerts.append(f"❌ **{domain}**:无法获取证书信息,请检查网络或域名")
continue
now = datetime.datetime.now()
remaining = (expiry - now).days
if remaining <= 0:
alerts.append(f"🚨 **{domain}**:证书已过期!过期时间:{expiry.strftime('%Y-%m-%d')}")
elif remaining <= THRESHOLD_DAYS:
alerts.append(f"⚠️ **{domain}**:证书将在 {remaining} 天后过期({expiry.strftime('%Y-%m-%d')})")
else:
print(f"{domain}: 正常,剩余{remaining}天")
if alerts:
content = "## SSL证书到期提醒\n" + "\n".join(alerts)
send_wechat_message(content)
if __name__ == "__main__":
main()
```
**3. 安装依赖并测试**
Python3标准库已包含所需模块,无需额外安装。直接运行:
```bash
python3 /usr/local/bin/ssl_wechat.py
```
如果配置正确,企业微信群会收到一条Markdown格式的告警消息。如果提示`urllib`模块找不到,请确认Python版本(Python 3.x自带urllib)。
**4. 设置定时任务**
同样使用crontab,每天执行一次:
```bash
crontab -e
```
添加:
```
0 10 * * * /usr/bin/python3 /usr/local/bin/ssl_wechat.py
```
注意:crontab中环境变量有限,建议使用Python的绝对路径(可通过`which python3`查看)。
---
## 常见问题
**Q1:脚本运行提示“openssl: command not found”**
A:服务器未安装OpenSSL。执行`sudo yum install openssl -y`(CentOS)或`sudo apt install openssl -y`(Ubuntu)。
**Q2:邮件发送失败,提示“authentication failed”**
A:检查SMTP授权码是否正确。QQ邮箱需要在设置->账户->POP3/IMAP/SMTP服务中生成授权码,不要使用QQ密码。其他邮箱(如163、Gmail)同样需要开启SMTP并获取专用密码。
**Q3:UptimeRobot检测显示“SSL Certificate Invalid”但实际证书正常**
A:可能原因:1)域名使用了CDN,CDN节点证书与源站不一致;2)证书链不完整。建议在UptimeRobot监控器设置中,勾选“Ignore SSL certificate errors”暂时跳过,同时检查CDN配置。
**Q4:企业微信机器人消息发送成功但群内未显示**
A:检查Webhook URL是否完整复制,注意key参数不能有空格。另外,企业微信机器人对Markdown格式有严格限制,不要使用复杂的表格或图片。
**Q5:监控脚本每天执行一次,但证书在周末过期怎么办?**
A:建议设置多个检查频率。例如crontab中增加每天下午6点再执行一次:`0 9,18 * * * /path/to/script`。或者使用UptimeRobot的5分钟检测间隔,更及时。
**Q6:证书剩余天数显示负数,脚本未发送告警**
A:检查脚本中的日期比较逻辑。如果剩余天数计算为负数,应触发“已过期”告警。确保`if [ $remaining_days -le 0 ]`条件正确,且脚本中`$remaining_days`变量未被错误截断。
**Q7:多个域名证书到期时间不同,如何统一管理?**
A:在脚本的`DOMAINS`数组中列出所有域名,脚本会逐个检查。也可以将域名列表放在外部文件(如`/etc/ssl_monitor_domains.txt`),脚本读取该文件,便于维护。
---
## 收尾总结
通过本教程,你掌握了三种SSL证书到期提醒的配置方法:Shell脚本+邮件适合单机管理,UptimeRobot适合无服务器环境且操作简单,企业微信机器人适合团队协作。建议将三种方法结合使用:本地脚本作为基础保障,UptimeRobot作为外部兜底监控,企业微信通知推送到工作群。配置完成后,记得定期检查脚本日志和监控平台状态,确保提醒机制本身不出故障。证书管理无小事,提前30天设置告警,给自己留足更新缓冲时间,彻底避免站点告警。