ooni / probe

OONI Probe network measurement tool for detecting internet censorship
https://ooni.org/install
BSD 3-Clause "New" or "Revised" License
749 stars 142 forks source link

Add proxyless censorship resillience #2711

Open fortuna opened 2 months ago

fortuna commented 2 months ago

My understanding is that the OONI reporting API has been blocked in China.

It seems like you may have Psiphon or Tor as fallbacks. You can add new alternatives that don't require setting up a tunnel.

For DNS-based blocking, you can use the Outline SDK dns package to create encrypted DNS resolvers and dialers that use Happy Eyeballs. You can easily implement your client.Resolver interface.

For SNI-based blocking, you can use the tlsfrag package to use TLS Record Fragmentation, which works in Russia, China and Iran.

Note that you can combine them. A Dialer can do encrypted DNS and TLS record fragmentation. You may find our FuncStreamDialer useful for creating anonymous StreamDialers that wraps behavior.

In our extensions module, we have a smart dialer, which tries different DNS and TLS strategies to find one that works for a list of domain, usually within 1-2 seconds. Here are example runs in Russia and Iran.

You can probably integrate all of that via the Client.HTTPClient. Our fetch example app illustrates how to do that.

If you'd like to integrate as a local proxy (I see you have a ProxyURL option), you can use our x/httpproxy package.

One great benefit of all of this is that you don't need any infrastructure. However, you also have the options to run Outline Servers and have them as fallback options as well.

bassosimone commented 2 months ago

Nice, thank you for pointing this out! It seems we were working in similar directions, in that we're also doing happy eyeballs and trying different strategies and caching what works. I will take a look at your implementation and see what we can learn from it and whether there's code with can integrate (with attribution!) to improve how we're doing. I'd rather avoid adding external dependencies at this time, since we already have significant issues with finding out the right version of packages for all dependencies. Thanks again!

fortuna commented 2 months ago

The Outline SDK is very lean. We wrote our own code for Shadowsocks, SOCKS5 and Web Proxy. We have very few, small dependencies, and don’t rewrite any dependency, so it shouldn’t give you much trouble.

fortuna commented 2 months ago

You may want to check out our strategy finder as well: https://github.com/Jigsaw-Code/outline-sdk/blob/main/x/smart/stream_dialer.go

bassosimone commented 2 months ago

Thank you!

fortuna commented 1 month ago

I did some more investigation in the OONI implementation.

The transport is injected into the http.Client in Network.NewHTTPClient

The transport is created in network.NewNetwork

This is where the TLS handshake actually happens: https://github.com/ooni/probe-cli/blob/cd2a9f7f73cd9d16ec1d8fa377bd46396afc26f9/internal/enginenetx/httpsdialer.go#L397