Python请求使用TLSv1或TLSv1.1库,尽管升级到Python 2.7
我想确保在使用请求库发布到HTTP服务器时,它会拒绝使用TLSv1或TLSv1.1进行通信。为此,我将我的https服务器配置为强制SSL协议使用TLSv1或TLSv1.1。我预计这些版本会被拒绝。Python请求使用TLSv1或TLSv1.1库,尽管升级到Python 2.7
我的Python程序CentOS的机器上运行:
cat /etc/centos-release
CentOS release 6.7 (Final)
默认的Python版本是2.6.6:
which python
/usr/bin/python
Python 2.6.6 (r266:84292, Aug 18 2016, 15:13:37)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-17)] on linux2
我安装的Python 2.7:
which python2.7
/usr/local/bin/python2.7
Python 2.7.6 (default, Jun 2 2017, 11:37:31)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-16)] on linux2
>>> import ssl
>>> ssl.OPENSSL_VERSION
'OpenSSL 1.0.1e-fips 11 Feb 2013'
openssl version
OpenSSL 1.0.1e-fips 11 Feb 2013
使用PIP2 .7,我安装了需要运行的请求库。我没有对openssl进行任何更改。
我发送了两个测试警报,看来我的程序已经协商到TLSv1。我的印象是TLSv1已被弃用。该程序正在使用python 2.7执行,而不是python 2.6的系统默认值。
在Python程序的顶部嵌入我! #在/ usr/local/bin目录/ python2.7
下面是2个警报后,显示TLSv1.1和使用TLSv1经历:
"POST /testpost HTTP/1.1" 200 43 TLSv1.1/ECDHE-RSA-AES256-SHA "-" "python-requests/2.5.1 CPython/2.6.6 Linux/2.6.32-573.22.1.el6.x86_64" 0.006 <"{for: test purposes}"
"POST /testpost HTTP/1.1" 200 43 TLSv1/ECDHE-RSA-AES256-SHA "-" "python-requests/2.5.1 CPython/2.6.6 Linux/2.6.32-573.22.1.el6.x86_64" 0.006 <"{for: test purposes}"
有什么想法?
ssl模块的文档有一个表格,显示哪些协议设置一起工作。通常,如果客户端和服务器都使用PROTOCOL_TLS
(与PROTOCOL_SSLv23
相同)连接,则它们使用最高的共享协议版本。如果没有兼容的版本(例如,服务器只会说1.1,客户端只有1.0),那么你会得到一个错误。
的requests
documentation展示了如何强制客户使用特定的TLS版本,例如强制TLS 1.2可以使用(略微变形例):
import ssl
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.poolmanager import PoolManager
class Tls12Adapter(HTTPAdapter):
""""Transport adapter that forces TLSv1.2"""
def init_poolmanager(self, *pool_args, **pool_kwargs):
self.poolmanager = PoolManager(
*pool_args,
ssl_version=ssl.PROTOCOL_TLSv1_2,
**pool_kwargs)
Recent版本urllib3
(其用于连接的请求的用途)允许通过一个SSLContext
代替,其允许更灵活的配置,例如阻止特定版本,同时允许任何新版本:
import ssl
import requests
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.poolmanager import PoolManager
from requests.packages.urllib3.util import ssl_
class TlsAdapter(HTTPAdapter):
def __init__(self, ssl_options=0, **kwargs):
self.ssl_options = ssl_options
super(TlsAdapter, self).__init__(**kwargs)
def init_poolmanager(self, *pool_args, **pool_kwargs):
ctx = ssl_.create_urllib3_context(ssl.PROTOCOL_TLS)
# extend the default context options, which is to disable ssl2, ssl3
# and ssl compression, see:
# https://github.com/shazow/urllib3/blob/6a6cfe9/urllib3/util/ssl_.py#L241
ctx.options |= self.ssl_options
self.poolmanager = PoolManager(*pool_args,
ssl_context=ctx,
**pool_kwargs)
session = requests.session()
# disallow tls1.0 and tls1.1, allow only tls1.2 (and newer if suported by
# the used openssl version)
adapter = TlsAdapter(ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1)
session.mount("https://", adapter)
第二个代码块是正确的方法,非常好的例子。 – miigotu
谢谢,这工作。就像参考一样,你需要为第一种方法使用Python 2.7.9,在第二种方法中使用2.7.13。我从2.7.6升级到2.7.13,以使其工作。 –
客户端将尝试说服务器支持的tls版本,除非您告诉它,否则它不会自动拒绝它。你在剧本中是如何做到的?请参阅[本文](https://lukasa.co.uk/2013/01/Choosing_SSL_Version_In_Requests/)(或[this](http://docs.python-requests.org/en/master/user/advanced/#例如特定的ssl版本))如何强制一个特定的ssl/tls版本。 – mata
谢谢,这是我所怀疑的,但并不清楚。我已经阅读过你提到的那篇博客文章,似乎它只限于一种协议。我希望能够提供一份你可以接受的清单。 –