同一台服务器上配置了不同的虚拟主机域名证书也可以获取到,直接上代码了:
def get_certificate(hostname, port):
import idna
from socket import socket
from OpenSSL import SSL
sock = socket()
# sock.settimeout(10) # 不要开启
sock.setblocking(True) # 关键。。
sock.connect((hostname, port), )
ctx = SSL.Context(SSL.SSLv23_METHOD)
ctx.check_hostname = False
ctx.verify_mode = SSL.VERIFY_NONE
sock_ssl = SSL.Connection(ctx, sock)
sock_ssl.set_tlsext_host_name(idna.encode(hostname)) # 关键: 对应不同域名的证书
sock_ssl.set_connect_state()
sock_ssl.do_handshake()
cert = sock_ssl.get_peer_certificate()
sock_ssl.close()
sock.close()
return cert
for u in ['https://www.baidu.com/', 'https://mp.weixin.qq.com/', 'https://www.qq.com/']:
from urllib import parse
rs = parse.urlparse(u)
cert = get_certificate(rs.hostname, int(rs.port or 443))
print(u)
print('\ttime:', cert.get_notBefore(), '~', cert.get_notAfter())
需注意的是如果设置了超时(sock.settimeout(10)
)打开了了非阻塞模式,有可能出现下面的错误(用sock.setblocking(True)
启用阻塞模式):
Traceback (most recent call last):
File "webcheck.py", line 122, in main
cert = get_certificate(rs.hostname, int(rs.port or 443))
File "webcheck.py", line 23, in get_certificate
sock_ssl.do_handshake()
File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/OpenSSL/SSL.py", line 1915, in do_handshake
self._raise_ssl_error(self._ssl, result)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/OpenSSL/SSL.py", line 1622, in _raise_ssl_error
raise WantReadError()
WantReadError
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。