blahblahblah
blahblahblah

Reputation: 2437

Pip install failing due to pyopenssl / OpenSSL error

I'm running Python 3.8.10 on WSL2 (Windows Subsystem for Linux) in a corporate environment and am encountering the below error, which I believe is related to pyopenssl / OpenSSL, when attempting to install anything using pip. It's not clear to me if I made any system-level changes that led to this strange behavior.

urllib3.exceptions.ProtocolError: ('Connection broken: OSError("(104, \'ECONNRESET\')")', OSError("(104, 'ECONNRESET')"))

Here is the full stack trace:

$ pip install --upgrade pip

/usr/share/python-wheels/urllib3-1.25.8-py2.py3-none-any.whl/urllib3/connectionpool.py:999: InsecureRequestWarning: Unverified HTTPS request is being made to host 'pypi.org'. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
/usr/share/python-wheels/urllib3-1.25.8-py2.py3-none-any.whl/urllib3/connectionpool.py:999: InsecureRequestWarning: Unverified HTTPS request is being made to host 'pypi.org'. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
Collecting pip
/usr/share/python-wheels/urllib3-1.25.8-py2.py3-none-any.whl/urllib3/connectionpool.py:999: InsecureRequestWarning: Unverified HTTPS request is being made to host 'files.pythonhosted.org'. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
  Downloading pip-21.3.1-py3-none-any.whl (1.7 MB)
     |███▋                            | 194 kB 54.4 MB/s eta 0:00:01ERROR: Exception:
Traceback (most recent call last):
  File "/usr/share/python-wheels/urllib3-1.25.8-py2.py3-none-any.whl/urllib3/contrib/pyopenssl.py", line 313, in recv_into
    return self.connection.recv_into(*args, **kwargs)
  File "/usr/lib/python3/dist-packages/OpenSSL/SSL.py", line 1822, in recv_into
    self._raise_ssl_error(self._ssl, result)
  File "/usr/lib/python3/dist-packages/OpenSSL/SSL.py", line 1622, in _raise_ssl_error
    raise WantReadError()
OpenSSL.SSL.WantReadError

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/share/python-wheels/urllib3-1.25.8-py2.py3-none-any.whl/urllib3/contrib/pyopenssl.py", line 313, in recv_into
    return self.connection.recv_into(*args, **kwargs)
  File "/usr/lib/python3/dist-packages/OpenSSL/SSL.py", line 1822, in recv_into
    self._raise_ssl_error(self._ssl, result)
  File "/usr/lib/python3/dist-packages/OpenSSL/SSL.py", line 1639, in _raise_ssl_error
    raise SysCallError(errno, errorcode.get(errno))
OpenSSL.SSL.SysCallError: (104, 'ECONNRESET')

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/share/python-wheels/urllib3-1.25.8-py2.py3-none-any.whl/urllib3/response.py", line 425, in _error_catcher
    yield
  File "/usr/share/python-wheels/urllib3-1.25.8-py2.py3-none-any.whl/urllib3/response.py", line 507, in read
    data = self._fp.read(amt) if not fp_closed else b""
  File "/usr/lib/python3.8/http/client.py", line 459, in read
    n = self.readinto(b)
  File "/usr/lib/python3.8/http/client.py", line 503, in readinto
    n = self.fp.readinto(b)
  File "/usr/lib/python3.8/socket.py", line 669, in readinto
    return self._sock.recv_into(b)
  File "/usr/share/python-wheels/urllib3-1.25.8-py2.py3-none-any.whl/urllib3/contrib/pyopenssl.py", line 328, in recv_into
    return self.recv_into(*args, **kwargs)
  File "/usr/share/python-wheels/urllib3-1.25.8-py2.py3-none-any.whl/urllib3/contrib/pyopenssl.py", line 318, in recv_into
    raise SocketError(str(e))
OSError: (104, 'ECONNRESET')

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/pip/_internal/cli/base_command.py", line 186, in _main
    status = self.run(options, args)
  File "/usr/lib/python3/dist-packages/pip/_internal/commands/install.py", line 357, in run
    resolver.resolve(requirement_set)
  File "/usr/lib/python3/dist-packages/pip/_internal/legacy_resolve.py", line 177, in resolve
    discovered_reqs.extend(self._resolve_one(requirement_set, req))
  File "/usr/lib/python3/dist-packages/pip/_internal/legacy_resolve.py", line 333, in _resolve_one
    abstract_dist = self._get_abstract_dist_for(req_to_install)
  File "/usr/lib/python3/dist-packages/pip/_internal/legacy_resolve.py", line 282, in _get_abstract_dist_for
    abstract_dist = self.preparer.prepare_linked_requirement(req)
  File "/usr/lib/python3/dist-packages/pip/_internal/operations/prepare.py", line 480, in prepare_linked_requirement
    local_path = unpack_url(
  File "/usr/lib/python3/dist-packages/pip/_internal/operations/prepare.py", line 282, in unpack_url
    return unpack_http_url(
  File "/usr/lib/python3/dist-packages/pip/_internal/operations/prepare.py", line 158, in unpack_http_url
    from_path, content_type = _download_http_url(
  File "/usr/lib/python3/dist-packages/pip/_internal/operations/prepare.py", line 303, in _download_http_url
    for chunk in download.chunks:
  File "/usr/lib/python3/dist-packages/pip/_internal/utils/ui.py", line 160, in iter
    for x in it:
  File "/usr/lib/python3/dist-packages/pip/_internal/network/utils.py", line 15, in response_chunks
    for chunk in response.raw.stream(
  File "/usr/share/python-wheels/urllib3-1.25.8-py2.py3-none-any.whl/urllib3/response.py", line 564, in stream
    data = self.read(amt=amt, decode_content=decode_content)
  File "/usr/share/python-wheels/urllib3-1.25.8-py2.py3-none-any.whl/urllib3/response.py", line 529, in read
    raise IncompleteRead(self._fp_bytes_read, self.length_remaining)
  File "/usr/lib/python3.8/contextlib.py", line 131, in __exit__
    self.gen.throw(type, value, traceback)
  File "/usr/share/python-wheels/urllib3-1.25.8-py2.py3-none-any.whl/urllib3/response.py", line 443, in _error_catcher
    raise ProtocolError("Connection broken: %r" % e, e)
urllib3.exceptions.ProtocolError: ('Connection broken: OSError("(104, \'ECONNRESET\')")', OSError("(104, 'ECONNRESET')"))

Update: Interestingly, if I leave out the --upgrade argument, I get a slightly different error message that may be more helpful, which is too many 503 error responses.

$ pip install jellyfish

Collecting jellyfish
ERROR: Could not install packages due to an EnvironmentError: HTTPSConnectionPool(host='files.pythonhosted.org', port=443): Max retries exceeded with url: /packages/88/ee/c8c7a899960e3a116c0e0cc95aa250fb7269784a472fa590b5ce042cc48a/jellyfish-0.8.9.tar.gz (Caused by ResponseError('too many 503 error responses'))

I am able to ping both files.pythonhosted.org and pypi.org without issue, but I am not able to wget or curl.

This is the output from curl (redacted some information).

$curl -v https://files.pythonhosted.org/packages/88/ee/c8c7a899960e3a116c0e0cc95aa250fb7269784a472fa590b5ce042cc48a/jellyfish-0.8.9.tar.gz

*   Trying 151.101.129.63:443...
* TCP_NODELAY set
* Connected to files.pythonhosted.org (151.101.129.63) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
*   CAfile: /etc/ssl/certs/ca-certificates.crt
  CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN, server accepted to use h2
* Server certificate:
*  subject: CN=*.pythonhosted.org
*  start date: Dec 24 19:42:31 2021 GMT
*  expire date: Jan 25 19:42:30 2023 GMT
*  subjectAltName: host "files.pythonhosted.org" matched cert's "*.pythonhosted.org"
*  issuer: CN=<redacted company cert>
*  SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x5594a1ea0860)
> GET /packages/88/ee/c8c7a899960e3a116c0e0cc95aa250fb7269784a472fa590b5ce042cc48a/jellyfish-0.8.9.tar.gz HTTP/2
> Host: files.pythonhosted.org
> user-agent: curl/7.68.0
> accept: */*
>
* Connection state changed (MAX_CONCURRENT_STREAMS == 4294967295)!
* Connection state changed (MAX_CONCURRENT_STREAMS == 100)!
< HTTP/2 200
< last-modified: Tue, 26 Oct 2021 15:23:22 GMT
< etag: "8ffa7a9bdb4b7c2746277467ea321ea7"
< content-type: application/x-tar
< x-goog-hash: crc32c=iBiiWQ==
< x-goog-hash: md5=j/p6m9tLfCdGJ3Rn6jIepw==
< server: UploadServer
< cache-control: max-age=365000000, immutable, public
< accept-ranges: bytes
< date: Fri, 07 Jan 2022 17:01:32 GMT
< age: 3218451
< x-served-by: cache-sea4472-SEA, cache-lga21959-LGA
< x-cache: HIT, HIT
< x-cache-hits: 1, 1
< x-timer: S1641574892.134802,VS0,VE1
< strict-transport-security: max-age=31536000; includeSubDomains; preload
< x-frame-options: deny
< x-xss-protection: 1; mode=block
< x-content-type-options: nosniff
< x-robots-header: noindex
< access-control-allow-methods: GET, OPTIONS
< access-control-allow-headers: Range
< access-control-allow-origin: *
< content-length: 137296
<
* transfer closed with 137296 bytes remaining to read
* stopped the pause stream!
* Connection #0 to host files.pythonhosted.org left intact
curl: (18) transfer closed with 137296 bytes remaining to read

Upvotes: 1

Views: 6009

Answers (2)

NotTheDr01ds
NotTheDr01ds

Reputation: 20640

From the comments, we ultimately determined that the pip downloads were being blocked by company policy.

Troubleshooting steps that helped us arrive at the right solution:

  • A ping files.pythonhosted.org was successful, so we next tried ...

  • A manual download of the URI reported by the pip error from the original/updated question:

    pip install jellyfish
    
    Collecting jellyfish
    ERROR: Could not install packages due to an EnvironmentError: HTTPSConnectionPool(host='files.pythonhosted.org', port=443): Max retries exceeded with url: /packages/88/ee/c8c7a899960e3a116c0e0cc95aa250fb7269784a472fa590b5ce042cc48a/jellyfish-0.8.9.tar.gz (Caused by ResponseError('too many 503 error responses'))    
    
    wget https://files.pythonhosted.org/packages/88/ee/c8c7a899960e3a116c0e0cc95aa250fb7269784a472fa590b5ce042cc48a/jellyfish-0.8.9.tar.gz
    

    This also failed with a 503.

  • So to determine if the problem was something in the WSL instance itself or somewhere higher up the stack, we moved to trying the same download from PowerShell:

    Invoke-WebRequest -Uri "https://files.pythonhosted.org/packages/88/ee/c8c7a899960e3a116c0e0cc95aa250fb7269784a472fa590b5ce042cc48a/jellyfish-0.8.9.tar.gz" -OutFile jellyfish-0.8.9.tar.gz
    

    This resulted in a (finally) informative message that:

    Invoke-WebRequest : File Transfer Blocked Transfer of the file you were trying to download or upload has been blocked in accordance with company policy. Please contact your system administrator if you believe this is in error.
    

Leaving these old troubleshooting steps in here in case they help anyone, but note that they were not useful for solving this particular question:

  • First, just a sanity check, but sudo apt update && sudo apt upgrade to make sure there's not some update to certificates that you haven't loaded, but I'm kind of assuming you've done that already.

  • Second, I really don't expect the results here to be any different, but would it make sense to try to create a venv?

    sudo apt install python3-venv
    python -m venv dirname
    source dirname/bin/activate
    

    and try pip in the venv?

  • Next up, it's definitely not recommended, but following the link in the stack trace will take you to the urllib3 Certificate Verification page.

    It seems to indicate that you might try something like cert_reqs = "CERT_NONE" pip install --upgrade pip.

    It might be a little scary to turn off certificate checking, though. I might try this in a "backed up" WSL instance. Let me know if you want instructions on how to do that.

Upvotes: 1

Kovy Jacob
Kovy Jacob

Reputation: 1019

Try this:

python -m pip install --trusted-host pypi.org --trusted-host pypi.python.org --trusted-host files.pythonhosted.org <package name>

Upvotes: 0

Related Questions