Collect authenticated Qinglong scripts batch
This commit is contained in:
167
脚本库/APP版/抓包/SSL证书检查/2026-05-23_SSL_c1f33bef.py
Normal file
167
脚本库/APP版/抓包/SSL证书检查/2026-05-23_SSL_c1f33bef.py
Normal file
@@ -0,0 +1,167 @@
|
||||
# Source: https://github.com/CN-Grace/QinglongScripts/blob/main/SSL.py
|
||||
# Raw: https://raw.githubusercontent.com/CN-Grace/QinglongScripts/main/SSL.py
|
||||
# Repo: CN-Grace/QinglongScripts
|
||||
# Path: SSL.py
|
||||
# UploadedAt: 2026-05-23T16:04:54Z
|
||||
# SHA256: c1f33bef544c897a6d3ea4c28fde98c6ee9729002ec45451f6197a1348d24589
|
||||
# Category: APP版/抓包
|
||||
# Evidence: cookie/token/authorization/header
|
||||
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
cron: 0 0 * * *
|
||||
new Env("SSL证书检查")
|
||||
SSL 证书检查脚本
|
||||
- 批量检查多个域名的 SSL 证书状态
|
||||
- 获取证书到期时间、剩余天数、颁发者等信息
|
||||
- 分类显示正常、警告、过期和检查失败的证书
|
||||
"""
|
||||
|
||||
import os
|
||||
import ssl
|
||||
import socket
|
||||
from datetime import datetime, timezone
|
||||
from typing import List, Dict
|
||||
|
||||
from utils import log_info, log_success, log_warning, log_error, beijing_now, beijing_time_str
|
||||
from notifier import send as notify_send
|
||||
|
||||
# ==================== 用户配置 ====================
|
||||
DOMAINS_TO_CHECK = [d.strip() for d in os.environ.get("SSL_DOMAINS", "").split(",") if d.strip()]
|
||||
WARNING_THRESHOLD = 30
|
||||
CONNECTION_TIMEOUT = 10
|
||||
|
||||
|
||||
def get_certificate_info(domain: str) -> Dict:
|
||||
"""获取单个域名的 SSL 证书信息"""
|
||||
result = {"domain": domain, "expiry_date": datetime.min, "days_left": -1, "issuer": "", "is_valid": False, "error": None}
|
||||
try:
|
||||
hostname = domain if ":" in domain else f"{domain}:443"
|
||||
host, port = hostname.split(":")
|
||||
port = int(port)
|
||||
context = ssl.create_default_context()
|
||||
with socket.create_connection((host, port), timeout=CONNECTION_TIMEOUT) as sock:
|
||||
with context.wrap_socket(sock, server_hostname=host) as ssock:
|
||||
cert = ssock.getpeercert()
|
||||
|
||||
expiry_str = cert["notAfter"]
|
||||
expiry_date = datetime.strptime(expiry_str, "%b %d %H:%M:%S %Y %Z").replace(tzinfo=timezone.utc)
|
||||
now = datetime.now(timezone.utc)
|
||||
days_left = (expiry_date - now).days
|
||||
issuer_dict = dict(x[0] for x in cert["issuer"])
|
||||
issuer = issuer_dict.get("organizationName", "Unknown")
|
||||
result.update({"expiry_date": expiry_date, "days_left": days_left, "issuer": issuer, "is_valid": days_left > 0})
|
||||
log_info(f"{domain} 证书剩余 {days_left} 天")
|
||||
except Exception as e:
|
||||
result["error"] = str(e)
|
||||
log_error(f"{domain} 检查失败: {e}")
|
||||
return result
|
||||
|
||||
|
||||
def check_all_domains(domains: List[str]) -> List[Dict]:
|
||||
"""检查所有域名的 SSL 证书"""
|
||||
results = []
|
||||
log_info(f"开始检查 {len(domains)} 个域名的 SSL 证书...")
|
||||
for domain in domains:
|
||||
log_info(f"正在检查: {domain}")
|
||||
cert_info = get_certificate_info(domain)
|
||||
results.append(cert_info)
|
||||
if cert_info["is_valid"]:
|
||||
if cert_info["days_left"] <= WARNING_THRESHOLD:
|
||||
log_warning(f" ⚠️ {domain} 将在 {cert_info['days_left']} 天后过期")
|
||||
else:
|
||||
log_success(f" ✅ {domain} 证书正常,剩余 {cert_info['days_left']} 天")
|
||||
elif cert_info["error"]:
|
||||
log_error(f" 🔧 {domain} 检查失败: {cert_info['error']}")
|
||||
else:
|
||||
log_error(f" ❌ {domain} 证书已过期")
|
||||
return results
|
||||
|
||||
|
||||
def categorize_certificates(certificates: List[Dict]) -> Dict[str, List[Dict]]:
|
||||
"""将证书结果分类"""
|
||||
warning_certs, expired_certs, valid_certs, error_certs = [], [], [], []
|
||||
for cert in certificates:
|
||||
if cert["error"] is not None:
|
||||
error_certs.append(cert)
|
||||
elif cert["is_valid"]:
|
||||
if 0 < cert["days_left"] <= WARNING_THRESHOLD:
|
||||
warning_certs.append(cert)
|
||||
elif cert["days_left"] > WARNING_THRESHOLD:
|
||||
valid_certs.append(cert)
|
||||
else:
|
||||
expired_certs.append(cert)
|
||||
return {"warning": warning_certs, "expired": expired_certs, "valid": valid_certs, "error": error_certs}
|
||||
|
||||
|
||||
def format_certificate_report(certificates: List[Dict]) -> str:
|
||||
"""格式化证书检查报告"""
|
||||
cats = categorize_certificates(certificates)
|
||||
lines = [f"🔔 SSL 证书检查报告", "", f"⏰ 检查时间: {beijing_time_str()}", f"📊 总计: {len(certificates)} 个域名", ""]
|
||||
|
||||
if cats["expired"]:
|
||||
lines.append("❌ 已过期的证书:")
|
||||
for cert in cats["expired"]:
|
||||
expiry = cert["expiry_date"].strftime("%Y-%m-%d") if cert["expiry_date"] != datetime.min else "未知"
|
||||
lines.append(f" {cert['domain']} — 已过期 {abs(cert['days_left'])} 天 (到期: {expiry})")
|
||||
lines.append("")
|
||||
|
||||
if cats["warning"]:
|
||||
lines.append("⚠️ 即将过期的证书 (30天内):")
|
||||
for cert in cats["warning"]:
|
||||
expiry = cert["expiry_date"].strftime("%Y-%m-%d")
|
||||
lines.append(f" {cert['domain']} — 剩余 {cert['days_left']} 天 (到期: {expiry} | 颁发: {cert['issuer']})")
|
||||
lines.append("")
|
||||
|
||||
if cats["valid"]:
|
||||
lines.append("✅ 证书状态正常:")
|
||||
for cert in cats["valid"]:
|
||||
lines.append(f" {cert['domain']} — 剩余 {cert['days_left']} 天")
|
||||
lines.append("")
|
||||
|
||||
if cats["error"]:
|
||||
lines.append("🔧 检查失败的域名:")
|
||||
for cert in cats["error"]:
|
||||
lines.append(f" {cert['domain']} — 错误: {cert['error']}")
|
||||
lines.append("")
|
||||
|
||||
lines.append("📈 统计信息:")
|
||||
lines.append(f" ✅ 正常: {len(cats['valid'])}")
|
||||
lines.append(f" ⚠️ 警告: {len(cats['warning'])}")
|
||||
lines.append(f" ❌ 过期: {len(cats['expired'])}")
|
||||
lines.append(f" 🔧 失败: {len(cats['error'])}")
|
||||
lines.append("")
|
||||
lines.append("─" * 18)
|
||||
lines.append(f"🕒 执行时间: {beijing_time_str()}")
|
||||
return "\n".join(lines)
|
||||
|
||||
|
||||
def main():
|
||||
log_info("=" * 50)
|
||||
log_info("SSL 证书检查脚本开始执行")
|
||||
log_info("=" * 50)
|
||||
|
||||
cert_results = check_all_domains(DOMAINS_TO_CHECK)
|
||||
report = format_certificate_report(cert_results)
|
||||
notify_send("SSL 证书检查报告", report)
|
||||
|
||||
cats = categorize_certificates(cert_results)
|
||||
print(f"\n{'=' * 60}")
|
||||
print(f"SSL 证书检查完成! 检查域名总数: {len(cert_results)}")
|
||||
print(f"正常: {len(cats['valid'])} | 警告: {len(cats['warning'])} | 过期: {len(cats['expired'])} | 失败: {len(cats['error'])}")
|
||||
print("=" * 60)
|
||||
|
||||
if cats["expired"] or cats["warning"]:
|
||||
print("\n⚠️ 需要注意的域名:")
|
||||
for cert in cats["expired"]:
|
||||
print(f" ❌ {cert['domain']} — 已过期")
|
||||
for cert in cats["warning"]:
|
||||
print(f" ⚠️ {cert['domain']} — 剩余 {cert['days_left']} 天到期")
|
||||
|
||||
log_info("=" * 50)
|
||||
log_info(f"脚本执行结束")
|
||||
log_info("=" * 50)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user