无法在 Ubuntu Linux 中使用 pip 安装 Python 包:InsecurePlatformWarning、SSLError、tlsv1 警报协议版本 [英] Unable to install Python packages using pip in Ubuntu Linux: InsecurePlatformWarning, SSLError, tlsv1 alert protocol version

查看:43
本文介绍了无法在 Ubuntu Linux 中使用 pip 安装 Python 包:InsecurePlatformWarning、SSLError、tlsv1 警报协议版本的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以前我曾经通过 pip 安装软件包,但现在我尝试使用 pip 安装 Python 库,出现 SSL 错误:

/home/teleduce/.virtualenvs/teleduce_handler/local/lib/python2.7/site-packages/pip/_vendor/requests/packages/urllib3/util/ssl_.py:318: SNIMissingWarning: 一个 HTTPS请求已发出,但 TLS 的 SNI(主题名称指示)扩展在此平台上不可用.这可能会导致服务器提供不正确的 TLS 证书,从而导致验证失败.您可以升级到更新版本的 Python 来解决此问题.有关更多信息,请参阅 https://urllib3.readthedocs.org/en/latest/security.html#snimissingwarning.SNIMissingWarning/home/teleduce/.virtualenvs/teleduce_handler/local/lib/python2.7/site-packages/pip/_vendor/requests/packages/urllib3/util/ssl_.py:122: InsecurePlatformWarning: 一个真正的 SSLContext 对象不可用.这会阻止 urllib3 正确配置 SSL,并可能导致某些 SSL 连接失败.您可以升级到更新版本的 Python 来解决此问题.有关更多信息,请参阅 https://urllib3.readthedocs.org/en/latest/security.html#insecureplatformwarning.不安全平台警告无法获取 URL https://pypi.python.org/simple/xlwt/:确认 ssl 证书时出现问题:[Errno 1] _ssl.c:504:错误:1407742E:SSL 例程:SSL23_GET_SERVER_HELLO:tlsv1 警报协议版本 - 跳过

OpenSSL 和 TLS 版本

OpenSSL 1.0.1 2012 年 3 月 14 日SSLv3TLSv1.2

Pip 版本

pip 8.1.2 from/home/teleduce/.virtualenvs/project_name/local/lib/python2.7/site-packages (python 2.7)

操作系统信息

Ubuntu 12.04.4 LTS (GNU/Linux 3.8.0-44-generic x86_64)

我试过了

pip install --upgrade pipcurl https://bootstrap.pypa.io/get-pip.py |Python

但它对我不起作用.得到一个错误信息是

<块引用>

SSL 例程:SSL23_GET_SERVER_HELLO:tlsv1 警报协议版本

我该如何解决这个错误?

解决方案

发生 SSLError 是因为系统 OpenSSL 库版本(编译时链接到您的 Python 的版本)低于 1.0.1 安装 Python 的那一天 或您当前的 Python 版本低于 2.7.9/3.4,因为它们都不真正支持 Python Package Index (PyPI) 现在需要来自 pip 连接.

发行版通常无法在不进行完整操作系统升级的情况下轻松升级旧的 openssl 和系统 Python,这并不总是可取的.您可以从最近的 sources 编译自己的非系统"OpenSSL,然后尝试编译一个独立的 '非系统'Python 将它链接到您刚刚编译的 OpenSSL,但有时这种方法是由于各种限制,也不可行.

解决方案

流行的建议,例如 pip install requests[secure] 或 urllib3[secure],通常无法帮助修复 pip,因为 pip 本身受影响 并且将无法连接到 PyPI 来安装任何东西.我们不能要求 pip 连接到 PyPI 来修复 pip 无法连接到 PyPI 的问题.:) 要在不升级Python的情况下修复它,我们需要手动安装相关包,解决依赖:

  • PyOpenSSLcryptography(它的 manylinux1 轮提供更新的 openssl 库);
  • 他们的依赖:asn1cryptocffienum34idnaipaddress, pycparser, 6;
  • 任何 pip 10+ 版本,因为旧的 pip 版本并没有真正使用加密 - 只有标准库的 ssl 模块(如果你的已经是 10 或以上,任何 pip v10+ 都可以)
<块引用>

在古老的 Ubuntu 上使用旧的非工作 pip 和过时的系统 openssl 版本进行测试.

第 1 步 - 下载

从 Python Packing Index (pypi.org) 通过您选择的网络浏览器下载以下包 -- 选择最近的 manylinux1 轮子 (.whl) 适用于您的操作系统/平台:

<块引用>

pip, asn1crypto, enum34, idna, 六个ipaddresspyOpenSSL, cffi密码学轮子;还有 pycparser(非轮子,它将是 tar.gz)

cp27- 代表 Python 2.7,cp36- 代表 Python 3.6;
mu- 类型的 manylinux 轮子是一种常见的选择,因为它们适用于以 UCS-4 (UTF-32) 格式存储 Unicode 数据的 Python —— 以下是检查方法:
$ python -c "import sys;print('UCS4/UTF-32: mu-manylinux1' if sys.maxunicode > 65535 else 'UCS2/UTF-16: m-manylinux1')"

Python 3 的注意事项:cp34-abi3-manylinux1 加密轮可以与任何 Python 版本>=3.4 一起使用,因为 abi3 支持多个版本的Python3,例如cryptography-2.5-cp34-abi3-manylinux1_x86_64.whl (2.4 MB)

基本上,轮子是具有特殊格式文件名和 .whl 扩展名的 ZIP 档案,其中包含可重定位的 Python 包.包可以是纯python的,也可以有预编译的用于python绑定的C库,所以它可以安装而无需像gcc、python-dev和其他C这样的某些系统依赖项头文件/库,经典的 .tar.gz 格式包通常需要.这也允许使用捆绑在每个轮子中的程序的确切版本.ma​​nylinux1_{x86_64,i686} 轮平台标签已在 PEP-513 并将适用于许多 linux 系统,包括常用的流行桌面和服务器发行版.期待未来 manylinux2 标签!

只需新建一个目录,例如:
$ mkdir ~/wheels_dir
并将所有下载的包复制(或移动)到该目录.

没有其他文件(除了下载的轮子),也没有子目录!

第 2 步 - 安装

如果您当前的 pip 版本低于 8.1,则必须先安装较新的 pip 版本,然后才能继续安装所有其他软件包:
$ pip install --user --no-index ~/wheels_dir/pip-19.0.1-py2.py3-none-any.whl
它将升级 pip 以处理新的 multilinux1 轮格式,并有助于避免 此平台上不支持的轮" 错误.

要在用户主目录级别安装所有软件包:
$ pip install --user --no-index ~/wheels_dir/*
$ pip3 在 Python 3 中

如果安装在新的或现有的 virtualenv 中,请省略 --user 选项:

$ source bin/activate$ pip install --no-index ~/wheels_dir/*

Pip 将自动解析正确的安装顺序和依赖项g.(如果需要,也可以为此创建一个 requirements.txt)

<块引用>

注意:除非您安装在 Python virtualenv 或 venv 中,否则强烈建议始终将 --user 标志与 pip 一起使用.然后它会在 ~/.local/lib/中的你的主目录下部署 python 包事实上,这个选项在 python3-pipOncode> 和 python-pip 包在 最新 版本的流行发行版中,例如 Ubuntu、Debian、Fedora 等.请尝试 避免 sudo pip,因为使用具有 root 访问权限的 pip 会干扰您的操作系统包管理器子系统(apt、yum 等)并且可能 影响 依赖于发行版提供的系统 python 的基本操作系统组件.

运行 $ pip freeze(或 Python 3 中的 pip3 freeze)命令以检查结果并确保已为您的 Python 环境安装所有包.

恭喜!现在您的 pip 应该可以与 PyPI 一起使用了,您可以尝试从在线 PyPI 存储库中查找类似 pip search colorama 的内容.

验证

您可以通过直接查询已安装的 pyOpenSSL 库来查看系统 SSL/TLS 设置的详细摘要:
$ python -m OpenSSL.debug
(ModuleNotFoundError 表示未安装 pyOpenSSL 包)

密码学的链接 OpenSSL 共享库与您的系统 Python 的 openssl 版本没有任何冲突.现在可能是通过安装最新的 python certifi 包来更新您的根 SSL 证书集合的好机会.

为什么有效

早期版本的 pip(10 之前)仅使用标准库的 ssl 模块(它是系统 OpenSSL 库的 Python API),而没有任何可能的回退到其他库,例如 cryptography.从版本 10 开始,pip 现在可以将 pyOpenSSL 与加密一起使用(如果环境中存在).

cryptography 包的 manylinux1 轮子包括最新的 OpenSSL 库,该库支持所有 TLS 协议高达 v1.3,无论您使用什么平台(PyPI 期望 pip 支持 TLSv1.2).这就是这个轮子重 2.1 Mb 的原因——档案提供了一个共享的 lib 绑定​​:

$ strings site-packages/cryptography/hazmat/bindings/_openssl.so |grep OpenSSL -m1OpenSSL 1.1.1a 2018 年 11 月 20 日$ python -c "from cryptography.hazmat.backends.openssl import backend as b;打印 b.openssl_version_text()";OpenSSL 1.1.1a 2018 年 11 月 20 日$ python -c "from OpenSSL import SSL;打印 SSL.SSLeay_version(0)";OpenSSL 1.1.1a 2018 年 11 月 20 日$ python -c "导入请求;打印 requests.get('https://www.howsmyssl.com/a/check').json()['tls_version']"TLS 1.3

<块引用>

加密轮包含静态链接的 OpenSSL 绑定,可确保您可以访问最新的 OpenSSL 版本,而不会破坏您的系统依赖项.
这将允许您继续使用相对较旧的 Linux 发行版(例如 LTS 版本),同时确保您的 Python 程序可以使用最新的 OpenSSL.(https://cryptography.io/en/latest/installation/)

在 Python 2 中,标准库的 ssl 模块从 2.7.9 版开始明确支持 PROTOCOL_TLSv1_2 标志,而在 Python 3 中 - 从 3.4 版开始;但是 TLSv1.2 连接仅当且仅当支持 TLSv1.2 的系统范围的 OpenSSL 库在 Python 编译时已经在系统中可用才有效并与之联系起来.TLSv1.2 至少需要 OpenSSL 1.0.1 才能运行,但通常建议使用 OpenSSL 1.0.2(或更高版本)(默认使用 TLSv1.2).

如果您确实有 Python 2.7.9+ 或 3.4+,并且其 ssl 模块实际上已经针对系统 openssl 编译,例如 v1.0.2k,那么即使是旧的 pip(例如作为 v6.0.8) 将在撰写本文时仍然使用 PyPI,您甚至不需要密码学.检查标准库 Python ssl 和系统 openssl 版本:
$ python -c "import ssl;打印(ssl.OPENSSL_VERSION)";&&openssl 版本
OpenSSL 0.9.8o 2010 年 6 月 1 日

即使我们升级了一些过时的发行版提供的 openssl,或者编译了最新的,我们也不能只是将现有的 Python 安装重新链接到它:ssl 模块被硬链接到编译/安装 Python 时系统提供的 OpenSSL,反之亦然.因此,基本上,如果不重新编译/重新安装 Python 本身(至少应该是 2.7.9+/3.4+ 版本)将其链接到新的系统 openssl 库,就无法利用新的 TLS 协议.这就是上述 pyopenssl+cryptography 方法派上用场的地方.

TLSing 快乐!:)


Previously I used to install packages by pip but now I am trying to install a Python library using pip, getting an SSL error:

 /home/teleduce/.virtualenvs/teleduce_handler/local/lib/python2.7/site-packages/pip/_vendor/requests/packages/urllib3/util/ssl_.py:318: SNIMissingWarning: An HTTPS request has been made, but the SNI (Subject Name Indication) extension to TLS is not available on this platform. This may cause the server to present an incorrect TLS certificate, which can cause validation failures. You can upgrade to a newer version of Python to solve this. For more information, see https://urllib3.readthedocs.org/en/latest/security.html#snimissingwarning.
  SNIMissingWarning
 /home/teleduce/.virtualenvs/teleduce_handler/local/lib/python2.7/site-packages/pip/_vendor/requests/packages/urllib3/util/ssl_.py:122: InsecurePlatformWarning: A true SSLContext object is not available. This prevents urllib3 from configuring SSL appropriately and may cause certain SSL connections to fail. You can upgrade to a newer version of Python to solve this. For more information, see https://urllib3.readthedocs.org/en/latest/security.html#insecureplatformwarning.
  InsecurePlatformWarning
  Could not fetch URL https://pypi.python.org/simple/xlwt/: There was a problem confirming the ssl certificate: [Errno 1] _ssl.c:504: error:1407742E:SSL routines:SSL23_GET_SERVER_HELLO:tlsv1 alert protocol version - skipping

OpenSSL and TLS Version

OpenSSL 1.0.1 14 Mar 2012
SSLv3
TLSv1.2

Pip version

pip 8.1.2 from /home/teleduce/.virtualenvs/project_name/local/lib/python2.7/site-packages (python 2.7)

OS Information

Ubuntu 12.04.4 LTS (GNU/Linux 3.8.0-44-generic x86_64)

I tried

pip install --upgrade pip
curl https://bootstrap.pypa.io/get-pip.py | python

but it does not work for me. Got an error message is

SSL routines: SSL23_GET_SERVER_HELLO:tlsv1 alert protocol version

How do I fix this error?

解决方案

The SSLError occurs because system OpenSSL library version (the one linked to your Python upon compilation) was below 1.0.1 the day when Python has been installed or your current Python version is below 2.7.9 / 3.4, because neither of these really support TLS 1.2 protocol version which the Python Package Index (PyPI) now requires from pip to connect.

Distributions usually cannot easily upgrade old openssl and system Python without undergoing a full OS upgrade, which is not always desirable. You could compile your own 'non-system' OpenSSL from recent sources and then try to compile a standalone 'non-system' Python linking it against the OpenSSL you have just compiled, but sometimes this approach is also unfeasible due to various limitations.

Solution

Popular recommendations, such as to pip install requests[secure] or urllib3[secure], often cannot help fix pip because pip itself is affected and won't be able to connect to PyPI to install anything. We cannot ask pip to connect to PyPI to fix pip's inability to connect to PyPI. :) To fix it without upgrading Python, we need to install relevant packages manually, resolving dependencies:

  • PyOpenSSL and cryptography (its manylinux1 wheel ships newer openssl library);
  • their dependencies: asn1crypto, cffi, enum34, idna, ipaddress, pycparser, six;
  • any pip 10+ version, because older pip versions did not really use cryptography - only the standard library's ssl module (you don't require a new pip version if yours is already 10 or above, any pip v10+ will do)

Tested on ancient Ubuntu with old non-working pip and outdated system openssl version.

Step 1 - Download

Download the following packages from Python Packing Index (pypi.org) via your web browser of choice -- choose recent manylinux1 wheels (.whl) for your OS/platform:

pip, asn1crypto, enum34, idna, six, ipaddress, pyOpenSSL, cffi, cryptography wheels; and also pycparser (a non-wheel, it will be a tar.gz)

cp27- stands for Python 2.7, cp36- for Python 3.6;
mu- type manylinux wheels are a common choice, as they are for Pythons that store Unicode data in UCS-4 (UTF-32) format -- here's how to check it:
$ python -c "import sys; print('UCS4/UTF-32: mu-manylinux1' if sys.maxunicode > 65535 else 'UCS2/UTF-16: m-manylinux1')"

Note for Python 3: the cp34-abi3-manylinux1 cryptography's wheel can be used with any Python version>=3.4 because abi3 support multiple versions of Python3, e.g cryptography-2.5-cp34-abi3-manylinux1_x86_64.whl (2.4 MB)

Basically, wheels are ZIP archives with a specially formatted file name and the .whl extension, containing a relocatable Python package. The package can be pure-python, but also can have pre-compiled C libraries for python bindings, so it can be installed without the need to have certain system dependencies like gcc, python-dev and other C headers/libs, often required for classic .tar.gz format packages. This also allows to use exact versions of programs bundled within each wheel. The manylinux1_{x86_64,i686} wheel platform tag was adopted in PEP-513 and will work on many linux systems, including the popular desktop and server distros in common use. Expect manylinux2 tag in future!

Simply create a new directory, for example:
$ mkdir ~/wheels_dir
and copy (or move) all the downloaded packages to that directory.

No other files (except the downloaded wheels) and no subdirs there please!

Step 2 - Install

If your current pip version is below 8.1, the newer pip version has to be installed before proceeding with all other packages:
$ pip install --user --no-index ~/wheels_dir/pip-19.0.1-py2.py3-none-any.whl
It will upgrade pip to handle the new multilinux1 wheel format and help avoid the "not a supported wheel on this platform" error.

To install all the packages at user home level:
$ pip install --user --no-index ~/wheels_dir/*
$ pip3 in Python 3

If installing in a new or existing virtualenv, omit the --user option:

$ source bin/activate
$ pip install --no-index ~/wheels_dir/*

Pip will resolve correct installation order and dependencies automagically. (one could also create a requirements.txt for this if so needed)

Note: Unless you install in a Python virtualenv or venv, it is highly recommended to always use --user flag with pip. It then deploys python packages under your home dir in ~/.local/lib/ In fact, this option is always On by default in distro-patched pip versions provided by python3-pip and python-pip packages in recent versions of popular distros such as Ubuntu, Debian, Fedora, etc. Please try to avoid sudo pip, as using pip with root access interferes with your OS package manager subsystem (apt, yum, etc) and may affect essential OS components that depend on the distro-supplied system python.

Run $ pip freeze (or pip3 freeze in Python 3) command to check the results and ensure all packages have been installed for your Python environment.

Congratulations! Now your pip should work with PyPI, and you can try to look up something like pip search colorama from the online PyPI repo.

Verify

You can see the detailed summary of your system SSL/TLS setup by querying the installed pyOpenSSL lib directly:
$ python -m OpenSSL.debug
(a ModuleNotFoundError would mean the pyOpenSSL package was not installed)

Cryptography's linked OpenSSL shared lib doesn't conflict in any way with your system Python's openssl version. It may now be a good opportunity to also update your collection of root SSL certificates for the future by installing the latest python certifi package.

Why it works

Earlier versions of pip (before 10) only used the standard library's ssl module (which is a Python API to system OpenSSL library) without any possible fallback to other libraries like cryptography. Since version 10, pip now can use pyOpenSSL with cryptography, if present in the environment.

The manylinux1 wheel of cryptography package includes recent OpenSSL library that supports all TLS protocols as high as v1.3 regardless of what's on your platform (PyPI expects pip to support TLSv1.2). That's why this wheel weighs 2.1 Mb -- the archive ships a shared lib binding:

$ strings site-packages/cryptography/hazmat/bindings/_openssl.so | grep OpenSSL -m1  
OpenSSL 1.1.1a  20 Nov 2018  
$ python -c "from cryptography.hazmat.backends.openssl import backend as b; print b.openssl_version_text()"  
OpenSSL 1.1.1a  20 Nov 2018  
$ python -c "from OpenSSL import SSL; print SSL.SSLeay_version(0)"  
OpenSSL 1.1.1a  20 Nov 2018  
$ python -c "import requests; print requests.get('https://www.howsmyssl.com/a/check').json()['tls_version']"  
TLS 1.3  

The Cryptography wheel contains a statically-linked OpenSSL binding, which ensures that you have access to the most-recent OpenSSL releases without corrupting your system dependencies.
This will allow you to continue to use relatively old Linux distributions (such as LTS releases), while making sure you have the most recent OpenSSL available to your Python programs. (https://cryptography.io/en/latest/installation/)

In Python 2, the standard library's ssl module began supporting PROTOCOL_TLSv1_2 flag explicitly since version 2.7.9, while in Python 3 - since version 3.4; but TLSv1.2 connections would only work if and only if the TLSv1.2-capable system-wide OpenSSL library was already available in the system by the time Python was being compiled and linked against it. TLSv1.2 requires a minimum of OpenSSL 1.0.1 to function but OpenSSL 1.0.2 (or later) is generally recommended (it uses TLSv1.2 by default).

If you do have Python 2.7.9+ or 3.4+, and its ssl module had been, in fact, compiled against system openssl, say v1.0.2k, then even old pip (such as v6.0.8) would still be working with PyPI as of the time of this writing, and you would not even need cryptography for that. To check the standard library Python ssl and system openssl versions:
$ python -c "import ssl; print(ssl.OPENSSL_VERSION)" && openssl version
OpenSSL 0.9.8o 01 Jun 2010

Even if we upgraded some outdated distro-supplied openssl, or compiled the newest one, we can't just re-link the existing Python installation to it: the ssl module was hard-linked to the system-supplied OpenSSL upon compilation/installation of Python, and not vice versa. So, basically, one could not take advantage of new TLS protocols without recompiling/reinstalling Python itself (that should be versions 2.7.9+ / 3.4+ at least) to link it to the new system openssl library. This is where the above pyopenssl+cryptography approach comes to the rescue.

Happy TLSing! :)


这篇关于无法在 Ubuntu Linux 中使用 pip 安装 Python 包:InsecurePlatformWarning、SSLError、tlsv1 警报协议版本的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆