脚本如何查询SSL证书有效期

wen 实用脚本 35

脚本如何查询SSL证书有效期:自动化工具与实战指南

目录导读

  • 为什么需要脚本查询SSL证书有效期?
  • 核心方法:OpenSSL命令行工具详解
  • 进阶方案:Python脚本批量检查证书
  • 脚本实现:自动检测并发送告警通知
  • 常见问题与解答(FAQ)
  • 总结与最佳实践

为什么需要脚本查询SSL证书有效期?

SSL/TLS证书是保障网站数据传输安全的核心组件,证书过期是导致网站访问中断、浏览器显示“不安全”警告的常见原因,手动检查证书有效期对拥有多个域名或服务器的运维人员而言效率低且容易遗漏,通过脚本自动化查询,可以:

脚本如何查询SSL证书有效期

  • 提前告警:在证书到期前(如30天、7天)自动通知管理员。
  • 批量监控:对数十、数百个域名统一检查。
  • 集成运维流程:将证书检查嵌入CI/CD管道或监控系统(如Prometheus、Zabbix)。

以下详细介绍几种实用脚本方法。


核心方法:OpenSSL命令行工具详解

OpenSSL是检查SSL证书最基础、最通用的工具,在Linux/macOS终端中,一行命令即可获取证书有效日期:

echo | openssl s_client -servername example.com -connect example.com:443 2>/dev/null | openssl x509 -noout -dates

输出示例:

notBefore=Apr  1 00:00:00 2024 GMT
notAfter=Apr  1 23:59:59 2025 GMT

参数说明

  • s_client:建立SSL/TLS连接。
  • -servername:指定SNI(服务器名称指示),用于多域名证书场景。
  • -connect:目标域名和端口(通常443)。
  • 2>/dev/null:忽略警告信息。
  • openssl x509 -noout -dates:仅提取证书有效期。

单行脚本提取剩余天数(Linux Bash):

expire_date=$(echo | openssl s_client -servername example.com -connect example.com:443 2>/dev/null | openssl x509 -noout -enddate | cut -d= -f2)
expire_epoch=$(date -d "$expire_date" +%s)
now_epoch=$(date +%s)
days_left=$(( ($expire_epoch - $now_epoch) / 86400 ))
echo "证书剩余 $days_left 天"

进阶方案:Python脚本批量检查证书

Python的sslsocketdatetime库可替代OpenSSL,更适合跨平台集成,以下脚本支持从文件中读取域名列表,并输出剩余天数:

# check_ssl.py
import ssl
import socket
import datetime
def get_cert_expiry(hostname, port=443):
    try:
        context = ssl.create_default_context()
        with socket.create_connection((hostname, port), timeout=5) as sock:
            with context.wrap_socket(sock, server_hostname=hostname) as ssock:
                cert = ssock.getpeercert()
                expiry_date = cert['notAfter']
                expiry_dt = datetime.datetime.strptime(expiry_date, "%b %d %H:%M:%S %Y %Z")
                days_left = (expiry_dt - datetime.datetime.now()).days
                return days_left
    except Exception as e:
        return f"错误: {e}"
# 使用示例
domains = ["example.com", "google.com", "github.com"]
for domain in domains:
    days = get_cert_expiry(domain)
    print(f"{domain}: 证书剩余 {days} 天")

输出示例

example.com: 证书剩余 89 天
google.com: 证书剩余 45 天
github.com: 证书剩余 230 天

增强功能

  • 添加emailslack告警:当days_left < 30时发送通知。
  • 使用multiprocessingasyncio并行检查大量域名(如1000+域名时使用asyncio + aiohttp)。

脚本实现:自动检测并发送告警通知

整合以上代码,创建一个完整的监控脚本ssl_monitor.sh(Bash版本):

#!/bin/bash
DOMAINS=("example.com" "myshop.net" "api.service.org")
THRESHOLD=30
WEBHOOK_URL="https://hooks.slack.com/services/YOUR/WEBHOOK/URL"
for domain in "${DOMAINS[@]}"; do
    expire_date=$(echo | openssl s_client -servername "$domain" -connect "$domain":443 2>/dev/null | openssl x509 -noout -enddate | cut -d= -f2)
    expire_epoch=$(date -d "$expire_date" +%s)
    now_epoch=$(date +%s)
    days_left=$(( ($expire_epoch - $now_epoch) / 86400 ))
    if [ "$days_left" -le "$THRESHOLD" ] && [ "$days_left" -ge 0 ]; then
        message="⚠️ 证书即将过期!域名: $domain, 剩余 $days_left 天"
        echo "$message"
        # 发送告警(示例:Slack Webhook)
        curl -X POST -H 'Content-type: application/json' --data "{\"text\":\"$message\"}" "$WEBHOOK_URL"
    fi
done

使用说明

  1. 通过crontab定时运行(例如每天8点):0 8 * * * /path/to/ssl_monitor.sh
  2. 若无法联网,脚本提示“连接超时”,建议增加timeout处理(如timeout 10 openssl…)。

常见问题与解答(FAQ)

Q1:脚本检查本地自签名证书是否有效?
A:可以,将-connect改为本地端口(如localhost:443),但需确保服务已监听,自签名证书的notAfter同样可读。

Q2:如何处理云负载均衡器后的证书(如AWS ALB)?
A:直接连接负载均衡器的域名(如alb-dns-name.elb.amazonaws.com),若证书绑定在负载均衡器上,脚本同样正常工作。

Q3:脚本报错“certificate verify failed”怎么办?
A:在OpenSSL命令中添加-verify_return_error或忽略校验(不推荐生产环境),Python中可设置context.check_hostname=False

Q4:能否同时检查证书链是否完整?
A:可以,使用openssl s_client -showcerts查看全部证书链,Python用cert.pem结构可分析签发者与主体关系。

Q5:脚本检查的证书剩余天数和实际到期日有差异?
A:注意时区问题,OpenSSL返回的GMT时间,本地计算时需统一使用UTC,Python的datetime.datetime.now()需设置为timezone.utc


总结与最佳实践

  1. 选择工具:简单场景用Bash+OpenSSL;复杂监控需求(跨平台、多线程、告警集成)用Python。
  2. 频率设置:建议每天检查一次(证书到期前30天改为每6小时一次)。
  3. 安全提醒:脚本应避免在未加密网络传输敏感信息(如Slack Webhook建议通过HTTPS发起)。
  4. 扩展性:可将检查结果写入数据库或监控系统(如InfluxDB + Grafana看板)。

自动化SSL证书有效期检测是保障网站可靠性、避免安全事故的关键步骤,通过上述脚本,您已能快速搭建一套自有监控方案——不仅减少手工操作,更能提前发现潜在风险,为证书更新争取足够时间。

抱歉,评论功能暂时关闭!