arvidn / libtorrent

an efficient feature complete C++ bittorrent implementation
http://libtorrent.org
Other
5.23k stars 996 forks source link

[Feature request] Introduce ECH (Encrypted Client Hello) support for HTTPS-enabled announcers #7529

Open giantplaceholder opened 1 year ago

giantplaceholder commented 1 year ago

A sort of follow-up of https://github.com/arvidn/libtorrent/issues/5222

Suggestion

As far as I understand, right now libtorrent does support HTTPS-enabled announcers.

I'm wondering whether you would consider to introduce ECH support for them as well.

In some countries -- in this particular example, Russia -- government telecommunication wachdogs are enforcing numerous ways to block communication with certain web-sites, including torrent trackers and their infrastructure, leveraging the fact that SNI and ALPN during TLS handshake are left unencrypted:

image

This allows gov't firewalls and traffic sniffing solutions to effectively block communications with web-site or announcer even when they are hiding behind Cloudflare (or other domain-front or CDN).

ECH sole purpose is to rectify that, and it is currently being deployed en masse by Cloudflare, Mozilla and Google with their Chrome browser. It is also supported by various middleware, such as openssl, boringssl, nginx, Apache, haproxy and so on.

Use case

Let's assume that third party can monitor our traffic on the go and intercept TLS handshakes:

0) We're using libtorrent-powered client, like qBittorrent, with some private torrent in it (no DHT, no LSD, no PeX) 1) Torrent client tries to communicate with HTTPS-enabled announcer currently "banned" by gov't: bt.announcer.tld 2) In this example, bt.announcer.tld is hiding behind Cloudflare (for whatever reasons -- for instance, Rutracker does this) and as such, it is ECH-enabled 3) DPI solution on the ISP side intercepts TLS handshake and parses SNI, extracting our destination: "bt.announcer.tld" 4) DPI solution drops all traffic to that CF endpoint from that specific client containing requests for bt.announcer.tld 4) Since this torrent is private, torrent client is unable to learn about any peers and download is effectively stalled

(this is very short and not entirely correct way of describing how Russia's country-wide filtering works for sites behind CF, Akamai and Fastly, without actually black-holing all traffic originating to and from those CDNs)

This might be an even worse issue for the end user if they are using a torrent site which keeps track of users ratio and limits user's ability to download should their ratio fall below some arbitrary threshold -- because torrent client if is not able to communicate with announcer, it won't be able to report user's stats back to the site.

But if ECH is utilized when torrent client makes TLS handshake, DPI service on the ISP side won't be able to extract our destination (announcer's TLD) from the SNI, and insted will see only a domain name of CDN's TLS endpoint -- in this case, Cloudflare front:

image

This, in turn, will allow the client to communicate with announcer as if nothing's ever happened.

As such, third party will be left with a choice:

It needs to be stated that ECH works most reliable when user is making use of encrypted DNS upstream, be that DoH or DoT, to avoid DNS spoofing by the ISP -- otherwise, you might be redirected to wherever ISP wants instead of your TLS front. For instance, Firefox requires DoH to be enabled in order to use ECH -- whilst Google Chrome does not.

Some may see this as a disadvantage because most think of Cloudflare or Google DNS services when they hear DoH or DoT. But there's a lot of public services not affiliated with these big companies, and a lot of them are run by privacy-conscious volunteers.

Extra info/examples/attachments

Quick write-up by CF on how ECH operates: https://blog.cloudflare.com/announcing-encrypted-client-hello/

@arvidn any kind of reply from you would be very much appreciated.

arvidn commented 1 year ago

do you have a reason to believe ECH is not already supported? libtorrent doesn't explicitly ask for any particular kind of SNI, it calls SSL_set_tlsext_host_name(). Is that insufficient for OpenSSL to use ECH?

arvidn commented 1 year ago

it appears OpenSSL may not support it yet: https://github.com/sftcd/openssl/blob/ECH-draft-13c/doc/designs/ech-api.md

giantplaceholder commented 1 year ago

@arvidn

do you have a reason to believe ECH is not already supported? libtorrent doesn't explicitly ask for any particular kind of SNI, it calls SSL_set_tlsext_host_name(). Is that insufficient for OpenSSL to use ECH?

I've captured some traffic exchanged between libtorrent-powered client and an announcer of Rutracker.org. SNI portion of the exchange is still in plain text.

it appears OpenSSL may not support it yet: https://github.com/sftcd/openssl/blob/ECH-draft-13c/doc/designs/ech-api.md

If we are talking mainline, then yes. AFAIK, OpenSSL devs are not putting nothing in the project unless there's an RFC for that. ECH, to be clear, is still in RFC draft state.

As of now, this is the only document I was able to quickly find that covers building one's own fork of OpenSSL with ECH support: https://github.com/sftcd/openssl/blob/ECH-draft-13c/esnistuff/building-curl-openssl-with-ech.md. The fork itself is hosted here: https://github.com/sftcd/openssl/

Am I correct to assume that unless that would be present in mainline OpenSSL, you won't be open to hacking in ECH support to libtorrent via the fork (say, defo.ie one) or somehow else?

arvidn commented 1 year ago

Am I correct to assume that unless that would be present in mainline OpenSSL, you won't be open to hacking in ECH support to libtorrent via the fork (say, defo.ie one) or somehow else?

OpenSSL is a dependency, whoever builds libtorrent can chose which version of OpenSSL to use. Now, it seems like there are new APIs to enable it client side though.

What would be necessary for the libtorrent side is a way to detect support in OpenSSL (say, a define), and also patching to enable it. Perhaps even a libtorrent option to enable it.

in libtorrent master, there is also support for GnuTLS, which might be another path towards ECH.

giantplaceholder commented 1 year ago

@arvidn this is specifically the reason I've pinged you directly. I've already been at the door of the qBittorrent devs with the same ask, and since they are using bone-stock libtorrent as-is, they seem this as a dependency issue rather their own.

My hope is that if ECH (and, by extension, OpenSSL ECH-enabled fork) support would be flag-defined, qBT devs can be reasoned with.

arvidn commented 1 year ago

My hope is that if ECH (and, by extension, OpenSSL ECH-enabled fork) support would be flag-defined, qBT devs can be reasoned with.

I'm not distributing binaries of libtorrent nor OpenSSL (and I don't think that would be a good idea). The most I could do (or someone contributing patches to libtorrent) is to make it possible to build libtorrent against a patched OpenSSL

giantplaceholder commented 1 year ago

That would be wonderful, to be honest. This would open a way for me to at least build a binaries myself and introduce that as an AUR build for Arch. Whomever would be comfortable using that at least would be able to.

SemiAccurate commented 11 months ago

@giantplaceholder have you thought about using BoringSSL? It already has ECH.

@arvidn I wonder if libtorrent should support BoringSSL instead of OpenSSL. The former is Google's simplified fork of OpenSSL with non of the cruft that has built up over the years and features much improved security processes that result in significantly reduced vulnerabilities issues, if any.

arvidn commented 11 months ago

as long as BoringSSL is backwards compatible enough for boost.asio to support it, it should be pretty straight-forward