Hi again :)
On 20/01/2025 13:30, Michael Rogers via anti-censorship-team wrote:
I made a mistake about OnionShare's use of Moat. It *does* use obfs4proxy for the meek connection (and will use Lyrebird in the next release), but then the HTTPS request through the meek tunnel fails on Android < 7.1.1 because bridges.torproject.org also uses a Let's Encrypt certificate. To fix that, I need to investigate whether we can get the libraries we're using for HTTPS (OkHttp and Conscrypt) to trust a pinned certificate.
Another thing I need to investigate is a difference in failure modes between Lyrebird 0.5.0 and obfs4proxy 0.0.14 on Android 7.0.
On Android 7.1.1, both versions of the transport are able to make meek connections via CDN77 and Azure and then connect to bridges.torproject.org through the tunnel.
On Android 7.0, both versions of the transport are able to make meek connections to Azure. (They then fail to connect to bridges.torproject.org through the tunnel as I mentioned above, but that's a separate issue.)
But on Android 7.0, obfs4proxy 0.0.14 can make a meek connection to CDN77 before failing to connect through the tunnel, whereas Lyrebird 0.5.0 fails with a timeout error instead.
An update on this:
* I've persuaded OkHttp to validate the Let's Encrypt cert from bridges.torproject.org on Android < 7.1.1 by using a custom X509TrustManager. * This has revealed that the difference in failure modes between obfs4proxy 0.0.14 and Lyrebird 0.5.0 when using CDN77 on Android < 7.1.1 was not what I thought. * Lyrebird fails with a timeout before making the meek connection. * obfs4proxy fails with an SSLHandshakeException after making the meek connection. I thought this was due to OkHttp failing to validate the certificate, but it's actually due to the tunneled connection to bridges.torproject.org being closed before OkHttp even sees the certificate.
So neither 0.0.14 nor 0.5.0 can make a tunneled connection via CDN77 on Android < 7.1.1. The failure modes are different but they both fail to create a usable connection.
Since both versions *can* make a usable connection on Android >= 7.1.1, where the root cert used by Let's Encrypt is in the device's certificate store, I think the issue must be related to the PT's TLS handshake relying on the device's certificate store. So to get this working, we need to be able to validate Let's Encrypt certs at the PT layer as well as the proxied-application layer.
I'll start working on this next, but if anyone on the list has experience with customising certificate validation in Go, I'd be grateful for any hints you can offer!
Thanks, Michael