在 Python 请求中捕获客户端/服务器 TLS 版本

Posted

技术标签:

【中文标题】在 Python 请求中捕获客户端/服务器 TLS 版本【英文标题】:Capturing client/server TLS version in Python requests 【发布时间】:2018-03-13 21:47:39 【问题描述】:

是否可以查看使用 Python 请求模块与服务器协商的 TLS 版本? 类似于openssl s_client -connect 会返回的东西

--- 未发送客户端证书 CA 名称 --- SSL 握手已读取 3043 字节并写入 375 字节 --- 新的,TLSv1/SSLv3,密码是 ECDHE-RSA-AES256-SHA 服务器公钥为 2048 位 支持安全重新协商 压缩:无 扩展:无 SSL-会话: 协议:TLSv1.1 密码:ECDHE-RSA-AES256-SHA 键-Arg:无 PSK 身份:无 PSK 身份提示:无 SRP 用户名:无

【问题讨论】:

你遇到了什么错误? 没有错误,我可以连接,但我想看看我的连接是否使用 TLS 1.2 :) 根据文档,除非您指定不同,否则它们似乎使用 urllib3 默认值。但无需深入挖掘,您可以简单地使用wireshark 记录流量并在您的捕获中查看握手协议版本。 docs.python-requests.org/en/master/user/advanced/… @stephen 是的,“无论 urllib3 默认是什么”是我的第一个想法,但 Python 没有多大意义 - 文档说一件事,代码说另一件事。就像我应该有 ssl.OP_NO_SSLv3,但 ssl.py 不包含此代码:D Wireshark 是我最初的想法,但我在商业环境中并且它不起作用:) 【参考方案1】:

复制我在https://***.com/a/55462022/6368697 的其他答案的核心,如果您只想做一次并进行测试,猴子补丁就足够了(否则请阅读我的答案的其余部分,它提供了使用传输适配器的正确实现,并正确显示收到的证书):

import requests
from requests.packages.urllib3.connection import VerifiedHTTPSConnection

SOCK = None

_orig_connect = requests.packages.urllib3.connection.VerifiedHTTPSConnection.connect

def _connect(self):
    global SOCK
    _orig_connect(self)
    SOCK = self.sock

requests.packages.urllib3.connection.VerifiedHTTPSConnection.connect = _connect

requests.get('https://yahoo.com')
tlscon = SOCK.connection
print 'Cipher is %s/%s' % (tlscon.get_cipher_name(), tlscon.get_cipher_version())
print 'Remote certificates: %s' % (tlscon.get_peer_certificate())
print 'Protocol version: %s' % tlscon.get_protocol_version_name()

这会产生:

Cipher is ECDHE-RSA-AES128-GCM-SHA256/TLSv1.2
Remote certificates: <OpenSSL.crypto.X509 object at 0x10c60e310>
Protocol version: TLSv1.2

【讨论】:

以上是关于在 Python 请求中捕获客户端/服务器 TLS 版本的主要内容,如果未能解决你的问题,请参考以下文章

请求被中止:无法为 HttpWebRequest 创建 SSL/TLS 安全通道

使用 Post 请求在 HTTP 客户端中启用 TLS

Python - 请求 HTTP 库 SSL 密钥

如何使用客户端上的“requests”模块和服务器上的“flask-restful”验证 https 请求的自签名证书(TLS1.2)

如何在蓝牙服务器端“读取特征值”捕获客户端请求?

为啥大多数浏览器的预检请求中不包含 TLS 客户端证书?