导入相关模块
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 里面
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 函数)
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 地址和证书过期时间
# 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 函数进行证书有效期检查和提示
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 函数内容如下:
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")
最后我们执行一下代码,看看结果如何
完整代码
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]
小改动一下
import ssl
import socket
import time
from datetime import datetime
def ssl_connect(domain, ip):
if ip == None:
return {'ok': 0, 'domain': domain, 'ip': '', 'end_date': '', 'msg': '获取ip失败!'}
socket.setdefaulttimeout(5)
context = ssl.create_default_context()
skt = context.wrap_socket(socket.socket(), server_hostname=domain)
ok = 0
end_date = ''
cert = ''
try:
skt.connect((ip, 443))
end_date = skt.getpeercert()['notAfter'].strip(' GMT')
ok = 1
except ssl.CertificateError as e:
cert = '证书错误:' + str(e)
except socket.timeout:
cert = '连接被拒绝。'
except ConnectionResetError as e:
cert = '连接重置:' + str(e)
except socket.gaierror as e:
cert = '连接错误:' + str(e)
finally:
skt.close()
skt_info = {'ok':ok,'domain': domain, 'ip': ip, 'end_date': end_date, 'msg':cert}
return skt_info
def check_cert_time(info):
if info['ok'] == 0:
return [0,f"域名:{info['domain']}; ip 地址:--; 证书过期时间:--。\n出现错误,原因:{info['msg']}\n"]
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
formatted_date = date_object.strftime("%Y-%m-%d %H:%M:%S")
reStr = f"域名:{info['domain']}; ip 地址:{info['ip']}; 证书过期时间:{formatted_date}。\n"
if 0 < remain_day < 7:
reStr +="剩余时间小于七天!请及时更换证书!\n"
t = 3
elif remain_day < 0:
reStr +="证书已过期!请及时更换证书!\n"
t = 2
else:
t = 1
reStr +=f"剩余天数为:{remain_day:.2f}天\n"
return [t,reStr]
def resolve_domain(domain):
try:
ip_address = socket.gethostbyname(domain)
return ip_address
except socket.gaierror as e:
return None
if __name__ == "__main__":
#需要检查的域名
queryDomain = [
"www.baidu.com",
]
originalDomainName=[]
for d in queryDomain:
ip_address = resolve_domain(d)
originalDomainName.append(f"{d}:{ip_address}")
domains = {}
for line in originalDomainName:
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]
finalResult = {}
print("")
for i in info:
result = check_cert_time(i)
print(result[1])
来源:
https://developer.aliyun.com/article/1294711