Httpx: Consider explicitly allowing usage of insecure SSL/TLS versions

Created on 7 Jan 2020  Â·  10Comments  Â·  Source: encode/httpx

How would I be able to get some sort of ssl context to work when I get this sslerror? Any ideas? fyi the ip that I'm trying to connect to is: 62.28.216.189 as an example.

tls+pki

Most helpful comment

You can pass a raw SSLContext instance for httpx to use, with verify=[SSLContext].

We don't have any public API for just changing the SSL/TLS versions, but you could use something like this...

from httpx.config import SSLConfig  # Careful, anything outside the top-level `httpx` is private API.

import ssl
import httpx

ssl_context = SSLConfig().ssl_context
ssl_context.options &= ~ssl.OP_NO_TLSv1_1

async with httpx.AsyncClient(verify=ssl_context):
    ...

(Similar to @florimondmanca's answer, but a slightly different approach.)

All 10 comments

Hi @freis,

Yes, we're currently not wrapping SSL errors — and I'd agree they can get somewhat cryptic — and that's definitely something we'd want to look at, but not sure where that lands in terms of priority. We could indeed wrap them and make the ssl_context used available on the exception, to help with debugging. (Though right now you can also put breakpoints in the HTTPX code via your IDE right before the exception is made, FWIW.)

As for the error, I remember we had some discussion with you about SSL errors in #646. Could it be the case this time that the host is not supporting the TLS versions that HTTPX uses? See https://github.com/encode/httpx/issues/646#issuecomment-566942505

@freis Is this issue linked to https://github.com/encode/httpx/issues/646#issuecomment-571667397?

This time I think that the problem is indeed that the is is not supporting the TLS versions that HTTPX uses, that's why I opened a new issue to try to understand how could I get hold of the context to change and force TLS1 or even SSLv2/v3.

I see… As of 0.10.1 I don't think there's a way to do this easily.

On master you could reach into undocumented APIs with…

import ssl
import httpx
from httpx.dispatch.connection_pool import ConnectionPool

connection_pool = ConnectionPool()
connection_pool.ssl.ssl_context.options &= ~ssl.OP_NO_TLSv1_1

async with httpx.AsyncClient(dispatch=connection_pool) as client:
    ...

I guess we could consider making SSLConfig public at some point, with an additional API to allow insecure versions we blacklist by default…

import httpx

ssl = httpx.SSLConfig(allowed_insecure_versions=["SSLv3", "TLSv1_1"])
async with httpx.AsyncClient(ssl=ssl) as client:
    ...

Changed the issue title to better reflect what I think is the requested feature here, sounds good?

You can pass a raw SSLContext instance for httpx to use, with verify=[SSLContext].

We don't have any public API for just changing the SSL/TLS versions, but you could use something like this...

from httpx.config import SSLConfig  # Careful, anything outside the top-level `httpx` is private API.

import ssl
import httpx

ssl_context = SSLConfig().ssl_context
ssl_context.options &= ~ssl.OP_NO_TLSv1_1

async with httpx.AsyncClient(verify=ssl_context):
    ...

(Similar to @florimondmanca's answer, but a slightly different approach.)

For some reason I can't get ssl_context from both:
from httpx.config import SSLConfig or
from httpx.dispatch.connection_pool import ConnectionPool

@freis What do you mean by "can't get"? Are they not importable? Please, as a general rule of thumb you should try to be as specific as possible… (Also, as I mentioned earlier the snippets above should mostly only work on the master version of the repo — or the next release.)

Since we've given fairly reasonable workaround for this (although it would now require reaching into httpx._config?), I'm going to close this off. If needed let's reopen.

Good call. It’s feasible that we could promote SSLconfig into public API at some point, but let’s leave this as is for now.

Was this page helpful?
0 / 5 - 0 ratings