簡體   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