我们对于域名的管理,主要需要监控的状态包括域名过期时间、域名的证书过期时间,就简单介绍一下。
通常会在阿里云,或者腾讯云这类主流平台购买域名和证书,通常都会有相关的API接口可供查询,这里就不介绍相关SDK的使用了。
我们使用更加通用的方式来监控域名,获取其相关信息。
查询域名过期时间
就非常简单的示例,先安装依赖包
pip install whois
示例代码
import whois
domain = whois.query("xwl.io")
print(domain.__dict__)
print(domain.expiration_date)
我们可以打印出所有支持的字段信息,以下是相关输出,根据需求获取即可。
>>> print(domain.__dict__)
{
'name': 'xwl.io',
'registrar': 'CloudFlare, Inc.',
'registrant_country': 'CN',
'creation_date': datetime.datetime(2021, 1, 30, 15, 54, 49),
'expiration_date': datetime.datetime(2023, 1, 30, 15, 54, 49),
'last_updated': datetime.datetime(2021, 5, 3, 21, 17, 4),
'status': 'clientTransferProhibited https://icann.org/epp#clientTransferProhibited',
'statuses': ['serverTransferProhibited https://icann.org/epp#serverTransferProhibited',
'clientTransferProhibited https://icann.org/epp#clientTransferProhibited'], 'dnssec': False,
'name_servers': {'ashley.ns.cloudflare.com\r', 'earl.ns.cloudflare.com\r'}, 'registrant': 'DATA REDACTED'
}
查询域名证书过期时间
安装依赖包
pip install pyopenssl python-dateutil
以下是获取域名证书过期时间的示例脚本
import ssl
import time
import OpenSSL
from dateutil import parser
hostname = 'blog.xwl.io'
port = 443
cert = ssl.get_server_certificate((hostname, port)).encode()
cert_obj = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, cert)
cert_expire_time = parser.parse(cert.get_notAfter().decode("UTF-8")).strftime('%Y-%m-%d %H:%M:%S')
print(cert.has_expired())
print(cert_expire_time)
输出信息如下:
False
2022-05-07 23:59:59
由于我的网站挂在CloudFlare下,这个过程中也可能会出现一个错误
ssl.SSLError: [SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert handshake failure (_ssl.c:1122)
这是因为请求的时候没有传递主机名导致的,需要修改ssl
模块如下
def get_server_certificate(addr, ssl_version=PROTOCOL_TLS, ca_certs=None):
"""Retrieve the certificate from the server at the specified address,
and return it as a PEM-encoded string.
If 'ca_certs' is specified, validate the server cert against it.
If 'ssl_version' is specified, use it in the connection attempt."""
host, port = addr
if ca_certs is not None:
cert_reqs = CERT_REQUIRED
else:
cert_reqs = CERT_NONE
context = _create_stdlib_context(ssl_version,
cert_reqs=cert_reqs,
cafile=ca_certs)
with create_connection(addr) as sock:
with context.wrap_socket(sock, server_hostname=host) as sslsock:
dercert = sslsock.getpeercert(True)
return DER_cert_to_PEM_cert(dercert)
主要就是为这一行with context.wrap_socket(sock, server_hostname=host) as sslsock:
,加上server_hostname
字段。