问题 在Python 2.6中发送TLS 1.2请求


我被困在使用Python 2.6,我需要使用TLS 1.2发送一个帖子请求。 Python 2.6是不是 requests 库支持TLS 1.2?如何通过TLS1.2而不是其他版本确保/验证请求?

样本请求是

r=requests.post(url,data=payload,verify=False)

在论坛的某个地方,我开始知道我们需要编译 pyOpenSSL 支持这个。有更容易的方法吗?


1736
2018-03-19 19:24


起源



答案:


ssl Python 2.6中的模块仅支持TLS 1.0。如果您不希望引入其他依赖项(例如您建议的pyOpenSSL),则需要升级到Python 2.7或3.x以获得对较新版本TLS的支持。

强制使用特定版本的TLS Python 2.7.9或更高版本构建一个 SSLContext 用合适的 PROTOCOL_* 不变。然后,您可以将它与任何允许您提供自己的API一起使用 SSLContext

import ssl
import urllib2

ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
# set other SSLContext options you might need
response = urllib2.urlopen(url, context=ctx)

使用特定协议版本 或更高 (包括未来版本),使用 ssl.PROTOCOL_SSLv23 然后禁用您不想使用的协议版本:

ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)

# allow TLS 1.2 and later
ctx.options |= ssl.OP_NO_SSLv2
ctx.options |= ssl.OP_NO_SSLv3
ctx.options |= ssl.OP_NO_TLSv1
ctx.options |= ssl.OP_NO_TLSv1_1

至于使用自定义 SSLContext 使用请求以强制特定协议版本, 根据文件 似乎没有办法做到这一点请参阅文档中的以下示例


12
2018-03-19 21:50



谢谢@frasertweedale。如何在发送请求时指定TLS的版本? - MultipleCrashes
更新了答案以及更多信息和 ssl 模块代码示例。不幸的是,似乎没有办法使用Requests库执行此操作。 - frasertweedale
如果服务器正在执行TLS 1.2请求怎么可能在python中使用请求库?在我的情况下,当我使用wireshark捕获数据包时,我观察到的是从客户端计算机发出的请求是TLS 1.0,但在服务器上捕获的数据包是TLS 1.2。我无法弄清楚,因为通过发送请求协议而非通过特定端口,服务器和客户端正在协商通过TLS 1.2进行通信。这个链接已经说明了这一点 luxsci.com/blog/ssl-versus-tls-whats-the-difference.html - MultipleCrashes
@testedboy你链接的文章很混乱并使用了奇怪的术语。 SSL和TLS握手类似;两者都是“通过港口”。 “按协议”是指应用层协议升级机制,如STARTTLS。正如您所指出的,SSL / TLS版本在握手期间进行协商;通常使用服务器和客户端都支持的高版本。 - frasertweedale
请求库支持设置特定版本的ssl: docs.python-requests.org/en/latest/user/advanced/... - brianz


答案:


ssl Python 2.6中的模块仅支持TLS 1.0。如果您不希望引入其他依赖项(例如您建议的pyOpenSSL),则需要升级到Python 2.7或3.x以获得对较新版本TLS的支持。

强制使用特定版本的TLS Python 2.7.9或更高版本构建一个 SSLContext 用合适的 PROTOCOL_* 不变。然后,您可以将它与任何允许您提供自己的API一起使用 SSLContext

import ssl
import urllib2

ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
# set other SSLContext options you might need
response = urllib2.urlopen(url, context=ctx)

使用特定协议版本 或更高 (包括未来版本),使用 ssl.PROTOCOL_SSLv23 然后禁用您不想使用的协议版本:

ctx = ssl.SSLContext(ssl.PROTOCOL_SSLv23)

# allow TLS 1.2 and later
ctx.options |= ssl.OP_NO_SSLv2
ctx.options |= ssl.OP_NO_SSLv3
ctx.options |= ssl.OP_NO_TLSv1
ctx.options |= ssl.OP_NO_TLSv1_1

至于使用自定义 SSLContext 使用请求以强制特定协议版本, 根据文件 似乎没有办法做到这一点请参阅文档中的以下示例


12
2018-03-19 21:50



谢谢@frasertweedale。如何在发送请求时指定TLS的版本? - MultipleCrashes
更新了答案以及更多信息和 ssl 模块代码示例。不幸的是,似乎没有办法使用Requests库执行此操作。 - frasertweedale
如果服务器正在执行TLS 1.2请求怎么可能在python中使用请求库?在我的情况下,当我使用wireshark捕获数据包时,我观察到的是从客户端计算机发出的请求是TLS 1.0,但在服务器上捕获的数据包是TLS 1.2。我无法弄清楚,因为通过发送请求协议而非通过特定端口,服务器和客户端正在协商通过TLS 1.2进行通信。这个链接已经说明了这一点 luxsci.com/blog/ssl-versus-tls-whats-the-difference.html - MultipleCrashes
@testedboy你链接的文章很混乱并使用了奇怪的术语。 SSL和TLS握手类似;两者都是“通过港口”。 “按协议”是指应用层协议升级机制,如STARTTLS。正如您所指出的,SSL / TLS版本在握手期间进行协商;通常使用服务器和客户端都支持的高版本。 - frasertweedale
请求库支持设置特定版本的ssl: docs.python-requests.org/en/latest/user/advanced/... - brianz


如果无法升级代码,您应该能够使用squid服务器或nginx代理连接。这是一个鱿鱼“碰撞”方法示例:

我可以使用Squid升级客户端TLS连接吗?

另一种选择是保留代理但重写URL(http到https)并让你的应用程序向http发送请求(看起来很奇怪,但如果实现正确则有效)。


0
2018-04-02 22:17