├── README.md └── get_dns_info.py /README.md: -------------------------------------------------------------------------------- 1 | ## 证书失效会发生啥? 2 | * 浏览器报不可信,页面被拦截 3 | * 生产事故,运维绩效扣光 - - 4 | 5 | ## 大厂也会犯的低级失误? 6 | * 苹果15年1月ChinaCache节点证书到期,未更新证书,导致国内用户appstore访问失败: [戳我](http://tech.163.com/15/0126/12/AGSSODRN00094OE0.html?agt=2337%27) 7 | * 乌龙!火狐浏览器忘记续费证书导致所有扩展被禁用: [戳我](https://kuaibao.qq.com/s/20190504A0C43M00?refer=spider) 8 | 9 | 10 | ## get_dns_info.py是什么? 11 | * 域名多、证书多,人工收集困难,漏续费后果严重。此脚本一键收集并生成html格式报表 12 | > 通过域名提供商(DNSpod)API获取所有域名 13 | >> 解析记录 14 | >>> 筛选A记录与CNAME,去重 15 | >>>> Curl获取证书详情、提供商、过期时间等信息 16 | >>>>> 生成HTML报告 17 | 18 | 19 | ## 环境 20 | * python3 21 | * requests 库 22 | 23 | 24 | ## 使用方法 25 | * DNSpod创建Token,替换脚本ID、token 26 | ![截图](https://github.com/fcatat/common/raw/master/create_token.jpg) 27 | 28 | ```python 29 | # https://www.dnspod.cn/console/user/security创建API Token 30 | ID = 111111 # 替换 31 | Token = 'e96527a8944f0123ww9edscsf4d7' # 替换 32 | ``` 33 | 34 | ```python 35 | # 仅汇总了域名总数与使用ssl证书量,可按需添加 36 | domain_sum = len(get_domains()) 37 | use_ssl_record_sum = len(all_record) 38 | ``` 39 | 40 | * python get_dns_info.py 运行后生成report-new.html 41 | 42 | 43 | ![截图](https://github.com/fcatat/common/raw/master/report_jpg.jpg) 44 | 45 | 46 | ## 关于作者 47 | 48 | ```python 49 | fcatat = { 50 | 地点 : "上海", 51 | 职业 : "运维" 52 | } 53 | ``` 54 | -------------------------------------------------------------------------------- /get_dns_info.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | ------------------------------------------------- 4 | File Name: get_dns_info 5 | Description : 6 | Author : ops@lechebang.com 7 | date: 2019/6/25 8 | ------------------------------------------------- 9 | Change Activity: 10 | 2019/6/25: 11 | ------------------------------------------------- 12 | """ 13 | import requests 14 | import subprocess 15 | import re 16 | 17 | 18 | # https://www.dnspod.cn/console/user/security创建API Token 19 | ID = 111111 # 替换 20 | Token = 'e96527a8944f0123ww9edscsf4d7' # 替换 21 | full_token = '%s,%s' % (ID, Token) 22 | content = { 23 | "login_token": full_token, 24 | "format": "json", 25 | "lang": "cn", 26 | "error_on_empty": "no", 27 | } 28 | 29 | 30 | # 获取所有域名 31 | def get_domains(): 32 | res = requests.post(url="https://dnsapi.cn/Domain.List", data=content) 33 | domains = res.json()['domains'] 34 | return domains 35 | 36 | 37 | # 获取所有记录 38 | def get_records(domainid): 39 | content['domain_id'] = domainid 40 | res = requests.post(url="https://dnsapi.cn/Record.List", data=content) 41 | records = res.json()['records'] 42 | return records 43 | 44 | 45 | # 获取证书信息 46 | def get_ssl(full_url): 47 | try: 48 | # curl超时时间5秒 49 | command = 'curl --connect-timeout 5 -lvs https://{}/'.format(full_url) 50 | cert_info = subprocess.getstatusoutput(command)[1] 51 | 52 | print('domain:', full_url) 53 | res = re.search( 54 | 'subject:(.*?)\n.*?start date:(.*?)\n.*?expire date:(.*?)\n.*?common name:(.*?)\n.*?issuer:(.*?)\n', 55 | cert_info) 56 | print('subject:', res.group(1)), 57 | print('start date:', res.group(2)), 58 | print('expire date:', res.group(3)), 59 | print('common name:', res.group(4)), 60 | print('issuer:', res.group(5)), 61 | print('*'*80) 62 | except: 63 | print('超时或没有证书') 64 | 65 | 66 | def new_get_ssl(full_url): 67 | try: 68 | # 配置超时时间5秒 69 | command = 'curl --connect-timeout 5 -lvs https://{}/'.format(full_url) 70 | cert_info = subprocess.getstatusoutput(command)[1] 71 | # name = re.findall('(?<=common.name:).*', cert_info)[0] 72 | name = full_url 73 | issuer = re.findall('(?<=issuer:).*', cert_info)[0] 74 | expire_date = re.findall('(?<=expire.date:).*', cert_info)[0] 75 | return [name, issuer, expire_date] 76 | except: 77 | pass 78 | 79 | 80 | # 取所有域名改写为html ,使用集合去重 81 | domain_str = '' 82 | all_record = set() 83 | for i in get_domains(): 84 | domain_str_tbody = '' + '\n' + \ 85 | '' + i['name'] + '' + '\n' + \ 86 | '' + i['grade_title'] + '' + '\n' + \ 87 | '' + i['records'] + '' + '\n' + \ 88 | '' + i['updated_on'] + '' + '\n' + \ 89 | '' + '\n' 90 | domain_str += domain_str_tbody 91 | for j in get_records(i['id']): 92 | if j['type'] == 'A' or j['type'] == 'CNAME': 93 | all_record.add(j['name']+'.'+i['name']) 94 | 95 | 96 | # 拼装record tbody 97 | record_str = '' 98 | for k in all_record: 99 | record_info = new_get_ssl(k) 100 | if record_info: 101 | record_str_tbody = '' + '\n' + \ 102 | '' + record_info[0] + '' + '\n' + \ 103 | '' + record_info[1] + '' + '\n' + \ 104 | '' + record_info[2] + '' + '\n' + \ 105 | '' + '\n' 106 | record_str += record_str_tbody 107 | 108 | # 汇总所有数据 109 | domain_sum = len(get_domains()) 110 | use_ssl_record_sum = len(all_record) 111 | 112 | 113 | 114 | # html原文 115 | html = ''' 116 | 117 | 118 | 119 | 120 | Report 121 | 122 | 123 | 124 | 125 |
126 | 127 | 128 |
129 |

130 | All_Cert_Info 131 | 132 |

133 |
134 |
135 | 136 | 137 |
138 |
139 | 140 |
141 |
142 |

143 | 144 | 域名总数:%s 145 | 146 |

147 |
148 |
149 |

150 | 151 | 使用证书总数:%s 152 | 153 |

154 |
155 |
156 |
157 |
158 | 159 | 160 |
161 |
162 |
163 |
域名详情
164 |
165 |
166 | 167 |
168 | 169 |
170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | %s 180 | 181 |
只检测A记录与CNAME证书
域名套餐条目数创建时间
182 |
183 |
184 |
185 |
186 |
187 |
证书详情
188 |
189 |
190 | 191 |
192 | 193 |
194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | %s 203 | 204 |
只检测A记录与CNAME证书
域名发行商过期时间
205 |
206 |
207 |
208 | 209 | 210 | 211 | ''' % (domain_sum, use_ssl_record_sum, domain_str, record_str) 212 | f = open('report-new.html', 'w') 213 | f.write(html) 214 | f.close() 215 | 216 | 217 | 218 | --------------------------------------------------------------------------------