Python 3 SSL无法获取证书问题求助
解决SSL证书收集时的连接拒绝问题及通过Requests获取证书的方法
为什么会出现ConnectionRefusedError?
你怀疑User-Agent的问题其实不对——SSL握手阶段还没到发送HTTP请求的步骤,这时候根本不会传递User-Agent这类HTTP头信息。连接被拒绝通常是这几个原因:
- 目标服务器的443端口实际未开放HTTPS服务
- 服务器/CDN拦截了纯SSL握手请求(部分CDN要求后续必须发送HTTP请求,而
ssl.get_server_certificate只完成SSL握手就结束) - 旧版
ssl.get_server_certificate未正确配置SNI(服务器名称指示),导致服务器无法识别请求的域名,进而拒绝连接
用Requests获取服务器证书
Requests确实可以获取证书,而且它会自动处理SNI、连接池等细节,能避免很多手动SSL连接的问题。示例代码:
import requests import ssl def get_cert_with_requests(dom): try: with requests.get(f"https://{dom}", verify=True) as resp: # 获取字典格式的证书详细信息 cert_details = resp.raw.connection.sock.getpeercert() # 转换为PEM格式的证书字符串(和ssl.get_server_certificate返回格式一致) pem_cert = ssl.DER_cert_to_PEM_cert(resp.raw.connection.sock.getpeercert(True)) return {"cert_details": cert_details, "pem_cert": pem_cert} except Exception as e: return {"error": str(e)}
修复原SSL代码的问题
如果坚持用标准库ssl模块,不要用ssl.get_server_certificate这个简化函数,手动创建socket并配置SNI,能解决大部分连接拒绝的问题:
import ssl import socket def certgrab(dom): address = (dom, 443) context = ssl.create_default_context() try: with socket.create_connection(address) as sock: # 手动指定server_hostname开启SNI支持 with context.wrap_socket(sock, server_hostname=dom) as ssock: pem_cert = ssl.DER_cert_to_PEM_cert(ssock.getpeercert(True)) print(pem_cert) return pem_cert except Exception as clanger: return {'clanger': clanger}
内容的提问来源于stack exchange,提问作者voltesque
相关产品推荐
相关产品推荐

