Python:获取域名ssl证书信息和到期时间!

1、通过openssl证书获取

openssl x509 -in <cert>.pem -noout -dates   

2、通过openssl域名获取

echo | openssl s_client -servername <doman> -connect <doman>:443 2>/dev/null | openssl x509 -noout -dates   

3、通过脚本获取curl

# coding: utf-8    # 查询域名证书到期情况      import re   import subprocess   from datetime import datetime   def get_re_match_result(pattern, string):       match = re.search(pattern, string)       return match.group(1)      def parse_time(date_str):       return datetime.strptime(date_str, "%b %d %H:%M:%S %Y GMT")      def format_time(date_time):       return datetime.strftime(date_time, "%Y-%m-%d %H:%M:%S")      def get_cert_info(domain):       """获取证书信息"""       cmd = f"curl -Ivs https://{domain} --connect-timeout 10"          exitcode, output = subprocess.getstatusoutput(cmd)          # 正则匹配       start_date = get_re_match_result('start date: (.*)', output)       expire_date = get_re_match_result('expire date: (.*)', output)          # 解析匹配结果       start_date = parse_time(start_date)       expire_date = parse_time(expire_date)          return {           'start_date': start_date,           'expire_date': expire_date       }         def get_cert_expire_date(domain):       """获取证书剩余时间"""       info = get_cert_info(domain)       print(info)          expire_date = info['expire_date']          # 剩余天数       return (expire_date - datetime.now()).days         if __name__ == "__main__":       domain = 'www.baidu.com'       expire_date = get_cert_expire_date(domain)       print(expire_date)   

4、通过socket 获取域名ssl 证书信息

核心代码

# -*- coding: utf-8 -*-      import socket   import ssl         def get_domain_cert(domain):       """       获取证书信息       :param domain: str       :return: dict       """       socket.setdefaulttimeout(5)          cxt = ssl.create_default_context()       skt = cxt.wrap_socket(socket.socket(), server_hostname=domain)          skt.connect((domain, 443))       cert = skt.getpeercert()          skt.close()          return cert         if __name__ == "__main__":       print(get_domain_cert("www.baidu.com"))   

还有一种方式也记录一下

    import socket   import ssl          def get_domain_cert(host, port=443, timeout=3):       """       获取证书信息       存在问题:没有指定主机ip,不一定能获取到正确的证书信息       :param host: str       :param port: int       :param timeout: int       :return: dict       """       context = ssl.create_default_context()          with socket.create_connection(address=(host, port), timeout=timeout) as sock:           with context.wrap_socket(sock, server_hostname=host) as wrap_socket:               return wrap_socket.getpeercert()    

输出

{   'subject': ((('countryName', 'CN'),), (('stateOrProvinceName', 'beijing'),), (('localityName', 'beijing'),), (('organizationalUnitName', 'service operation department'),), (('organizationName', 'Beijing Baidu Netcom Science Technology Co., Ltd'),), (('commonName', 'baidu.com'),)),    'issuer': ((('countryName', 'BE'),), (('organizationName', 'GlobalSign nv-sa'),), (('commonName', 'GlobalSign RSA OV SSL CA 2018'),)),    'version': 3,    'serialNumber': '4417CE86EF82EC6921CC6F68',    'notBefore': 'Jul  5 05:16:02 2022 GMT',    'notAfter': 'Aug  6 05:16:01 2023 GMT',    'subjectAltName': (('DNS', 'baidu.com'), ),    'OCSP': ('http://ocsp.globalsign.com/gsrsaovsslca2018',),    'caIssuers': ('http://secure.globalsign.com/cacert/gsrsaovsslca2018.crt',),    'crlDistributionPoints': ('http://crl.globalsign.com/gsrsaovsslca2018.crl',)   }   

结构化输出内容后的完整代码

# -*- coding: utf-8 -*-      import socket   import ssl      from dateutil import parser      # requests.packages.urllib3.disable_warnings()      try:       _create_unverified_https_context = ssl._create_unverified_context   except AttributeError:       # Legacy Python that doesn't verify HTTPS certificates by default       pass   else:       # Handle target environment that doesn't support HTTPS verification       ssl._create_default_https_context = _create_unverified_https_context      DATETIME_FORMAT = '%Y-%m-%d %H:%M:%S'      socket.setdefaulttimeout(5)         def get_domain_ip(domain):       """       获取ip地址       :param domain: str       :return: str       """       try:           addrinfo = socket.getaddrinfo(domain, None)           return addrinfo[0][-1][0]       except Exception as e:           pass          return None         def get_domain_cert(domain):       """       获取证书信息       :param domain: str       :return: dict       """       cxt = ssl.create_default_context()       skt = cxt.wrap_socket(socket.socket(), server_hostname=domain)          skt.connect((domain, 443))       cert = skt.getpeercert()       skt.close()          return cert         def get_cert_info(domain):       """       获取证书信息       :param domain: str       :return: dict       """       cert = get_domain_cert(domain)          issuer = _tuple_to_dict(cert['issuer'])       subject = _tuple_to_dict(cert['subject'])          return {           'domain': domain,           'ip': get_domain_ip(domain),           'subject': _name_convert(subject),           'issuer': _name_convert(issuer),           # 'version': cert['version'],           # 'serial_number': cert['serialNumber'],           'start_date': _parse_time(cert['notBefore']),           'expire_date': _parse_time(cert['notAfter']),       }         def _tuple_to_dict(cert_tuple):       """       cert证书 tuple转dict       :param cert_tuple: tuple       :return:       """       data = {}       for item in cert_tuple:           data[item[0][0]] = item[0][1]          return data         def _name_convert(data):       """       名字转换       :param data: dict       :return: dict       """       name_map = {           'C': 'countryName',           'CN': 'commonName',           'O': 'organizationName',           'OU': 'organizationalUnitName',           'L': 'localityName',           'ST': 'stateOrProvinceName'       }          dct = {}       for key, value in name_map.items():           dct[key] = data.get(value, '')          return dct         def _parse_time(time_str):       """       解析并格式化时间       :param time_str: str       :return: str       """       return parser.parse(time_str).astimezone().strftime(DATETIME_FORMAT)         if __name__ == "__main__":       print(get_cert_info("www.baidu.com"))      

输出

{     "domain": "www.baidu.com",     "ip": "39.156.66.14",     "subject": {       "C": "CN",       "CN": "baidu.com",       "O": "Beijing Baidu Netcom Science Technology Co., Ltd",       "OU": "service operation department",       "L": "beijing",       "ST": "beijing"     },     "issuer": {       "C": "BE",       "CN": "GlobalSign RSA OV SSL CA 2018",       "O": "GlobalSign nv-sa",       "OU": "",       "L": "",       "ST": ""     },     "start_date": "2022-07-05 13:16:02",     "expire_date": "2023-08-06 13:16:01"   }

5、通过pyOpenSSL获取证书信息

该方式,不校验证书合法性,只获取证书信息

文档:https://pyopenssl.org/en/0.15.1/index.html#

依赖

pip install pyOpenSSL   

示例

# -*- coding: utf-8 -*-      import ssl   import OpenSSL         def get_ssl_expire_date(host, port=443):       cert = ssl.get_server_certificate((host, port))       x509 = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, cert)       return x509.get_notAfter().decode()         if __name__ == '__main__':       print(get_ssl_expire_date('www.baidu.com'))       # 20230806051601Z      

6、Domain Admin可视化管理域名证书到期

项目地址:https://github.com/mouday/domain-admin

运行环境:Python 3.7.0

$ pip install domain_admin      # 升级到最新版本,可选   $ pip3 install -U domain-admin -i https://pypi.org/simple      # 启动运行   $ gunicorn 'domain_admin.main:app'   

访问地址:http://127.0.0.1:8000

默认的管理员账号:admin 密码:123456

---------------------------END---------------------------

题外话

当下这个大数据时代不掌握一门编程语言怎么跟的上脚本呢?当下最火的编程语言Python前景一片光明!如果你也想跟上时代提升自己那么请看一下.

在这里插入图片描述

感兴趣的小伙伴,赠送全套Python学习资料,包含面试题、简历资料等具体看下方。

一、Python所有方向的学习路线

Python所有方向的技术点做的整理,形成各个领域的知识点汇总,它的用处就在于,你可以按照下面的知识点去找对应的学习资源,保证自己学得较为全面。

img
img

二、Python必备开发工具

工具都帮大家整理好了,安装就可直接上手!img

三、最新Python学习笔记

当我学到一定基础,有自己的理解能力的时候,会去阅读一些前辈整理的书籍或者手写的笔记资料,这些笔记详细记载了他们对一些技术点的理解,这些理解是比较独到,可以学到不一样的思路。

img

四、Python视频合集

观看全面零基础学习视频,看视频学习是最快捷也是最有效果的方式,跟着视频中老师的思路,从基础到深入,还是很容易入门的。

img

五、实战案例

纸上得来终觉浅,要学会跟着视频一起敲,要动手实操,才能将自己的所学运用到实际当中去,这时候可以搞点实战案例来学习。

img

六、面试宝典

在这里插入图片描述

在这里插入图片描述

简历模板在这里插入图片描述
若有侵权,请联系删除
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值