SSL 证书过期巡检脚本 (Python 版)

哈喽大家好,我是咸鱼

之前写了个 shell 版本的 SSL 证书过期巡检脚本 (文章:《SSL 证书过期巡检脚本》),后台反响还是很不错的

那么今天咸鱼给大家介绍一下 python 版本的 SSL 证书过期巡检脚本 (完整代码在文末)

思路

导入相关模块

python 复制代码
import ssl
import socket
import time
from datetime import datetime

首先我们创建一个 domain.txt 用来存放要检查的域名和对应的 IP 地址

复制代码
www.baidu.com:180.101.50.242,180.101.50.188
www.bing.com:202.89.233.101,202.89.233.100

我们读取该文件,把里面的域名和对应的每个 ip 取出来,并存放到字典 domains 里面

python 复制代码
domains = {}
with open('domain.txt', 'r', encoding='utf-8') as file:
	for line in file:
		domain, ip_pool = line.strip().split(':')
		domains[domain] = ip_pool.split(',')

取出来之后我们循环遍历字典,去获取每个域名对应的证书信息(ssl_connect 函数)

python 复制代码
def ssl_connect(domain, ip):
    # 设置socket的超时时间为5秒
    socket.setdefaulttimeout(5)
    # 创建默认的SSL上下文
    context = ssl.create_default_context()
    # 创建一个SSL套接字
    skt = context.wrap_socket(socket.socket(), server_hostname=domain)
    try:
        # 建立SSL连接
        skt.connect((ip, 443))

        # 获取证书过期时间
        end_date = skt.getpeercert()['notAfter'].strip(' GMT')

        # 创建一个字典,存储本次连接中的域名、IP 地址和证书过期时间信息
        skt_info = {'domain': domain, 'ip': ip, 'end_date': end_date}
    except ssl.CertificateError as e:
        cert = e
    except socket.timeout:
        cert = 'Connect refused'
    except ConnectionResetError as e:
        cert = 'Connect reset' + str(e)
    except socket.gaierror as e:
        cert = 'Connnect gaierror'
    finally:
        # 关闭SSL套接字
        skt.close()
    return skt_info

ssl_connect 函数返回一个字典 skt_info,包含当前连接的域名、ip 地址和证书过期时间

python 复制代码
# skt_info 内容
{'domain': 'www.baidu.com', 'ip': '180.101.50.242', 'end_date': 'Aug  6 01:51:05 2024'}
{'domain': 'www.baidu.com', 'ip': '180.101.50.188', 'end_date': 'Aug  6 01:51:05 2024'}
{'domain': 'www.bing.com', 'ip': '202.89.233.101', 'end_date': 'Aug 16 03:47:45 2023'}
{'domain': 'www.bing.com', 'ip': '202.89.233.100', 'end_date': 'Aug 16 03:47:45 2023'}

然后我们调用 check_cert_time 函数进行证书有效期检查和提示

python 复制代码
info = [ssl_connect(domain, ip) for domain, ip_pool in domains.items() for ip in ip_pool]
[check_cert_time(i) for i in info]

check_cert_time 函数内容如下:

python 复制代码
def check_cert_time(info):
    # 获取当前时间戳
    current_timestamp = int(time.time())

    # 将证书过期时间转换成时间戳
    date_object = datetime.strptime(info['end_date'], "%b %d %H:%M:%S %Y")
    end_timestamp = int(date_object.timestamp())

    # 计算剩余天数
    remain_day = (end_timestamp - current_timestamp) / 86400

    # 打印域名、IP 地址和证书过期时间信息
    print(f"域名:{info['domain']},ip 地址:{info['ip']},证书过期时间:{info['end_date']}")

    # 根据剩余天数进行不同的提示
    # 如果证书过期时间减去当前时间的天数小于七天的话,则提示需要准备更换证书了
    if 0 < remain_day < 7:
        print('剩余时间小于七天!请及时更换证书!')
    elif remain_day < 0:
        print('证书已过期!请及时更换证书!')
    else:
        print(f"剩余天数为:{remain_day:.2f}天\n")

最后我们执行一下代码,看看结果如何

完整代码

python 复制代码
import ssl
import socket
import time
from datetime import datetime


def ssl_connect(domain, ip):
    # 设置socket的超时时间为5秒
    socket.setdefaulttimeout(5)
    # 创建默认的SSL上下文
    context = ssl.create_default_context()
    # 创建一个SSL套接字
    skt = context.wrap_socket(socket.socket(), server_hostname=domain)
    try:
        # 建立SSL连接
        skt.connect((ip, 443))

        # 获取证书过期时间
        end_date = skt.getpeercert()['notAfter'].strip(' GMT')

        # 创建一个字典,存储本次连接中的域名、IP 地址和证书过期时间信息
        skt_info = {'domain': domain, 'ip': ip, 'end_date': end_date}
    except ssl.CertificateError as e:
        cert = e
    except socket.timeout:
        cert = 'Connect refused'
    except ConnectionResetError as e:
        cert = 'Connect reset' + str(e)
    except socket.gaierror as e:
        cert = 'Connnect gaierror'
    finally:
        # 关闭SSL套接字
        skt.close()
    return skt_info


def check_cert_time(info):
    # 获取当前时间戳
    current_timestamp = int(time.time())

    # 将证书过期时间转换成时间戳
    date_object = datetime.strptime(info['end_date'], "%b %d %H:%M:%S %Y")
    end_timestamp = int(date_object.timestamp())

    # 计算剩余天数
    remain_day = (end_timestamp - current_timestamp) / 86400

    # 打印域名、IP 地址和证书过期时间信息
    print(f"域名:{info['domain']},ip 地址:{info['ip']},证书过期时间:{info['end_date']}")

    # 根据剩余天数进行不同的提示
    # 如果证书过期时间减去当前时间的天数小于七天的话,则提示需要准备更换证书了
    if 0 < remain_day < 7:
        print('剩余时间小于七天!请及时更换证书!')
    elif remain_day < 0:
        print('证书已过期!请及时更换证书!')
    else:
        print(f"剩余天数为:{remain_day:.2f}天\n")



if __name__ == "__main__":
    domains = {}

    with open('domain.txt', 'r', encoding='utf-8') as file:
        for line in file:
            domain, ip_pool = line.strip().split(':')
            domains[domain] = ip_pool.split(',')

    info = [ssl_connect(domain, ip) for domain, ip_pool in domains.items() for ip in ip_pool]

    [check_cert_time(i) for i in info]
相关推荐
香蕉大香蕉(06敬畏市场)3 分钟前
MySQL 单点详解(01)
java·数据库·mysql·面试·博客·实习
小小张说故事16 分钟前
Python 的 str 为什么设计成不可变?拆开字符串驻留、字符串池,以及 += 拼接到底慢在哪
后端·python
LaughingZhu18 分钟前
Product Hunt 热榜 2026-10-30:Empacer、Scape、Floot in ChatGPT
java·前端·数据库·人工智能·chatgpt·notion
ljt272496066119 分钟前
Python笔记(十一)--Numpy(一)
笔记·python·numpy
时早玖沐24 分钟前
KOOK「找不到语音频道」:同一个错误假设,我犯了三次
python·开源·ai编程
_冷眸_26 分钟前
Python 调用大模型 API:最小请求、Base URL 和 401/404 排查
开发语言·人工智能·python
standxy37 分钟前
即时库存同步实战:从旺店通拉取库存详情落库 MySQL 的完整策略
数据库·集成·电商
麦壳饼37 分钟前
SonnetDB:工业 IoT 中的 PID 历史分析与 PLC 协作
数据库·sonnetdb
吹什么轩42 分钟前
MySQL 事务管理:从 ACID 到 MVCC,一篇讲透
数据库·mysql
Dumbness1 小时前
UIA 读微信群消息没有 id,怎么判断哪条是新的:后缀对齐在翻历史和撤回时整屏重报
python·算法