No se pueden instalar paquetes de Python usando pip en Ubuntu Linux: InsecurePlatformWarning, SSLError, tlsv1 alert protocol version

Anteriormente solía instalar paquetes por pip pero ahora estoy tratando de instalar una biblioteca de Python usando pip, obteniendo un error de 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 

Versiones OpenSSL y TLS

 OpenSSL 1.0.1 14 Mar 2012 SSLv3 TLSv1.2 

Versión pip

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

Información del SO

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

Lo intenté

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

Pero no funciona para mí. Tengo un mensaje de error es

Rutinas SSL: SSL23_GET_SERVER_HELLO: versión del protocolo de alerta tlsv1

¿Cómo soluciono este error?

El SSLError se produce porque la versión de la biblioteca del sistema OpenSSL (la que está vinculada a su Python en la comstackción) estaba por debajo de 1.0.1 el día en que se instaló Python o su versión actual de Python está por debajo de 2.7.9 / 3.4, porque ninguno de estos es realmente compatible con TLS 1.2 versión del protocolo que el Índice de Paquetes de Python (PyPI) ahora requiere de pip para conectarse.

Las distribuciones generalmente no pueden actualizar fácilmente el openssl antiguo y el sistema Python sin una actualización completa del sistema operativo, lo que no siempre es deseable. Puede comstackr su propio OpenSSL ‘no-sistema’ de fonts recientes y luego intentar comstackr un Python ‘no-sistema’ independiente que lo vincule con el OpenSSL que acaba de comstackr, pero a veces este enfoque también es inviable debido a varias limitaciones.

Solución

Las recomendaciones populares, como las solicitudes de instalación de pip [secure] o urllib3 [secure], a menudo no pueden ayudar a arreglar pip porque pip está afectado y no podrá conectarse a PyPI para instalar nada. No podemos pedirle a pip que se conecte a PyPI para corregir la incapacidad de pip para conectarse a PyPI. 🙂 Para solucionarlo sin actualizar Python, necesitamos instalar los paquetes relevantes manualmente, resolviendo las dependencias:

  • PyOpenSSL y la cryptography (su rueda manylinux1 incluye una biblioteca más nueva de openssl);
  • sus dependencias: asn1crypto , cffi , enum34 , idna , pycparser , pycparser , six ;
  • cualquier versión de pip 10+, porque las versiones de pip anteriores no utilizaban realmente la criptografía; solo el módulo ssl la biblioteca estándar (no necesita una nueva versión de pip si la suya ya es 10 o superior, cualquier pip v10 + funcionará)

Probado en la antigua Ubuntu con el viejo pip que no funciona y la versión abierta del sistema obsoleto.

Paso 1 – Descargar

Descargue los siguientes paquetes de Python Packing Index (pypi.org) a través del navegador web que elija . Elija las recientes llantas manylinux1 ( .whl ) para su sistema operativo / plataforma:

pip , asn1crypto , enum34 , idna , six , ipaddress , pyOpenSSL , cffi , ruedas de criptografía ; y también pycparser (un no-wheel, será un tar.gz)

cp27- significa Python 2.7, cp36- para Python 3.6;
Las ruedas mu-tipo manylinux son una opción común, como lo son para los Pythons que almacenan datos Unicode en formato UCS-4 (UTF-32); aquí hay cómo comprobarlo:
$ python -c "import sys; print('UCS4/UTF-32: mu-manylinux1' if sys.maxunicode > 65535 else 'UCS2/UTF-16: m-manylinux1')"

Nota para Python 3 : la cp34-abi3-manylinux1 criptografía cp34-abi3-manylinux1 se puede usar con cualquier versión de Python> = 3.4 porque abi3 admite varias versiones de Python3, por ejemplo, cryptography-2.5-cp34-abi3-manylinux1_x86_64.whl (2.4 MB)

Básicamente, las ruedas son archivos ZIP con un nombre de archivo especialmente formateado y la extensión .whl, que contiene un paquete de Python reubicable. El paquete puede ser de python puro, pero también puede tener bibliotecas de C precomstackdas para enlaces de python, por lo que puede instalarse sin la necesidad de tener ciertas dependencias del sistema como gcc, python-dev y otras cabeceras / libertades de C, que a menudo se requieren para Paquetes de formato clásico .tar.gz. Esto también permite utilizar versiones exactas de los progtwigs incluidos en cada rueda. La etiqueta de plataforma de rueda manylinux1 _ {x86_64, i686} se adoptó en PEP-513 y funcionará en muchos sistemas Linux, incluidas las populares distribuciones de escritorio y servidores de uso común. Espere la etiqueta manylinux2 en el futuro!

Simplemente cree un nuevo directorio, por ejemplo:
$ mkdir ~/wheels_dir
y copie (o mueva) todos los paquetes descargados a ese directorio.

No hay otros archivos (excepto las ruedas descargadas) y no hay subdirectorios por favor!

Paso 2 – Instalar

Si su versión actual de pip está por debajo de 8.1, la versión más reciente de pip debe instalarse antes de continuar con todos los demás paquetes:
$ pip install --user --no-index ~/wheels_dir/pip-19.0.1-py2.py3-none-any.whl
Mejorará pip para manejar el nuevo formato de rueda multilinux1 y ayudará a evitar el error “no es compatible con una rueda en esta plataforma” .

Para instalar todos los paquetes en el nivel de inicio del usuario:
$ pip install --user --no-index ~/wheels_dir/*
$ pip3 en Python 3

Si está instalando en un virtualenv nuevo o existente, omita la opción --user :

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

Pip resolverá el orden de instalación correcto y las dependencias de forma automática. (También se puede crear un Requirements.txt para esto si es necesario)

Nota: A menos que instale en Python virtualenv o venv, se recomienda siempre usar --user flag con pip. A continuación, implementa los paquetes de Python bajo su directorio de inicio en ~ / .local / lib / De hecho, esta opción está siempre activada de forma predeterminada en las versiones de parches distribuidos por distro proporcionados por los python3-pip y python-pip en versiones recientes de distribuciones populares como como Ubuntu, Debian, Fedora, etc. Intente evitar el sudo pip , ya que el uso de pip con acceso raíz interfiere con el subsistema del administrador de paquetes de su sistema operativo (apt, yum, etc.) y puede afectar a los componentes esenciales del sistema operativo que dependen del sistema suministrado por la distribución. python.

Ejecute el comando $ pip freeze (o pip3 freeze en Python 3) para verificar los resultados y asegurarse de que se hayan instalado todos los paquetes para su entorno Python.

¡Felicidades! Ahora su pip debería funcionar con PyPI, y puede intentar buscar algo como pip search colotwig en el repository de PyPI en línea.

Verificar

Puede ver el resumen detallado de la configuración de SSL / TLS de su sistema consultando la pyOpenSSL instalada directamente:
$ python -m OpenSSL.debug
(un ModuleNotFoundError significaría que el paquete pyOpenSSL no estaba instalado)

La biblioteca compartida OpenSSL vinculada de Cryptography no entra en conflicto de ninguna manera con la versión de su servidor en Python’s openssl. Ahora puede ser una buena oportunidad para actualizar también su colección de certificados SSL raíz para el futuro instalando el último paquete certifi Python.

Por que funciona

Las versiones anteriores de pip (antes de las 10) solo usaban el módulo ssl la biblioteca estándar (que es una API de Python para la biblioteca OpenSSL del sistema) sin ningún posible respaldo a otras bibliotecas como la cryptography . Desde la versión 10, pip ahora puede usar pyOpenSSL con criptografía, si está presente en el entorno.

El manylinux1 wheel of cryptography incluye la biblioteca OpenSSL reciente que admite todos los protocolos TLS tan altos como v1.3, independientemente de lo que haya en su plataforma (PyPI espera que pip admita TLSv1.2). Es por eso que esta rueda pesa 2.1 Mb: el archivo envía un enlace de biblioteca compartida:

 $ 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 

La rueda de cifrado contiene un enlace OpenSSL enlazado estáticamente, lo que garantiza que tenga acceso a las versiones más recientes de OpenSSL sin dañar las dependencias de su sistema.
Esto le permitirá continuar usando distribuciones de Linux relativamente antiguas (como las versiones LTS), mientras se asegura de tener el OpenSSL más reciente disponible para sus progtwigs de Python. ( https://cryptography.io/en/latest/installation/ )

En Python 2, el módulo ssl la biblioteca estándar comenzó a admitir el indicador PROTOCOL_TLSv1_2 explícitamente desde la versión 2.7.9, mientras que en Python 3, desde la versión 3.4; pero las conexiones TLSv1.2 solo funcionarán si y solo si la biblioteca OpenSSL para todo el sistema con capacidad para TLSv1.2 ya estuviera disponible en el sistema en el momento en que Python se estaba comstackndo y enlazando con él. TLSv1.2 requiere un mínimo de OpenSSL 1.0.1 para funcionar, pero generalmente se recomienda OpenSSL 1.0.2 (o posterior) (utiliza TLSv1.2 de forma predeterminada).

Si tiene Python 2.7.9+ o 3.4+, y su módulo ssl ha sido, de hecho, comstackdo contra el sistema openssl, digamos v1.0.2k, entonces incluso el viejo pip (como v6.0.8) aún estaría trabajando con PyPI en el momento de escribir este artículo, y ni siquiera necesitaría la criptografía para eso. Para verificar la biblioteca estándar de Python ssl y las versiones de sistema openssl:
$ python -c "import ssl; print(ssl.OPENSSL_VERSION)" && openssl version
OpenSSL 0.9.8o 01 jun 2010

Incluso si actualizamos algunos openssl desactualizados de la distribución obsoleta, o comstackmos el más reciente, no podemos simplemente volver a vincular la instalación de Python existente: el módulo ssl estaba conectado al OpenSSL suministrado por el sistema en la comstackción / instalación de Python, y no al revés. Básicamente, uno no podría aprovechar los nuevos protocolos TLS sin volver a comstackr / reinstalar el propio Python (que debería ser al menos las versiones 2.7.9+ / 3.4+) para vincularlo a la nueva biblioteca openssl del sistema. Aquí es donde el enfoque de cryptography pyopenssl + anterior viene al rescate.

Feliz TLSing! 🙂