繁体   English   中英

无法在 Ubuntu Linux 中使用 pip 安装 Python 包:InsecurePlatformWarning、SSLError、tlsv1 警报协议版本

[英]Unable to install Python packages using pip in Ubuntu Linux: InsecurePlatformWarning, SSLError, tlsv1 alert protocol version

以前我曾经通过 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: 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 和 TLS 版本

OpenSSL 1.0.1 14 Mar 2012
SSLv3
TLSv1.2

点子版本

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 pip
curl https://bootstrap.pypa.io/get-pip.py | python

但这对我不起作用。 收到一条错误消息是

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

我该如何解决这个错误?

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

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

解决方案

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

  • PyOpenSSLcryptography (它的manylinux1轮提供更新的 openssl 库);
  • 他们的依赖: asn1cryptocffienum34idnaipaddresspycparsersix
  • 任何pip 10+ 版本,因为旧的 pip 版本并没有真正使用密码学 - 只有标准库的ssl模块(如果你的 pip 版本已经是 10 或更高版本,则不需要新的 pip 版本,任何 pip v10+ 都可以)

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

第 1 步 - 下载

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

pipasn1cryptoenum34idna6ipaddresspyOpenSSLcffi密码轮; 还有pycparser (一个非轮子,它将是一个 tar.gz)

cp27-代表 Python 2.7, cp36-代表 Python 3.6;
型manylinux车轮是一种常见的选择,因为它们是蟒蛇,在UCS-4(UTF-32)格式存储Unicode数据-在这里是如何检查:
$ 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 格式包。 这也允许使用捆绑在每个轮子中的程序的确切版本。 PEP-513 中采用了manylinux1 _{x86_64,i686} 轮平台标签,它将在许多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/*
Python 3 中的$ pip3

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

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

皮普将解决正确的安装顺序和依赖AUTOMAically。 (如果需要,也可以为此创建一个 requirements.txt)

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

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

恭喜! 现在您的 pip 应该可以与 PyPI 一起使用,您可以尝试从在线 PyPI 存储库中pip search colorama类似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 -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  

加密轮包含静态链接的 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 连接仅当且仅当在 Python 被编译和链接时系统中已经存在支持TLSv1.2 的系统范围的 OpenSSL 库时才有效。 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; print(ssl.OPENSSL_VERSION)" && openssl version
OpenSSL 0.9.8o 2010 年 6 月 1 日

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

快乐的 TLSing! :)


暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM