尽管升级到Python 2.7,Python仍然使用TLSv1或TLSv1.1请求库

Amr*_*nes 0 python pyopenssl python-requests tls1.2

我想确保在使用请求库发布到HTTP服务器时,它会拒绝使用TLSv1或TLSv1.1进行通信.为此,我配置了我的https服务器以强制SSL协议使用TLSv1或TLSv1.1.我希望这些版本被拒绝.

我的python程序在CentOs机器上运行:

cat /etc/centos-release
CentOS release 6.7 (Final)
Run Code Online (Sandbox Code Playgroud)

默认的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
Run Code Online (Sandbox Code Playgroud)

我安装了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
Run Code Online (Sandbox Code Playgroud)

使用pip2.7,我安装了所需的库以获取运行请求.我没有对openssl做任何改动.

我发送了两个测试警报,似乎我的程序协商到TLSv1.我的印象是TLSv1已被弃用.该程序使用python 2.7执行,而不是python 2.6的系统默认值.

在我嵌入的python程序的顶部:#!/ usr/local/bin/python2.7

以下是显示TLSv1.1和TLSv1的2个帖子警报:

"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}"
Run Code Online (Sandbox Code Playgroud)

有什么想法吗?

mat*_*ata 6

ssl模块的文档有一个表格,显示哪些协议设置一起工作.通常,如果客户端和服务器都使用PROTOCOL_TLS(相同PROTOCOL_SSLv23)连接,则使用最高共享协议版本.如果没有兼容版本(例如服务器只说1.1,客户端只有1.0),那么你会收到一个错误.

requests 文档显示了如何强制客户端使用特定的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)
Run Code Online (Sandbox Code Playgroud)

最新版本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)
Run Code Online (Sandbox Code Playgroud)