Skip to content

Demo: real HTTP Proxy, instead of destination socket rewrite #34

Open
mame82 opened this issue Nov 12, 2021 · 4 comments
Open

Demo: real HTTP Proxy, instead of destination socket rewrite #34

mame82 opened this issue Nov 12, 2021 · 4 comments
Labels
enhancement New feature or request

Comments

@mame82
Copy link

mame82 commented Nov 12, 2021

Hi, thx for the great project. I was working on a use case, where Flutter has to be forced to use a real HTTP proxy (instead of silently redirecting to a transparent proxy).

I want to share my patch for info, maybe sbdy could use it (targets Dart's HttpClient implementation, enforces proxy and prevents overwriting it via findProxy setter):
20211112_161915

Here's a short Twitter thread, showing it applied to a target app:
https://twitter.com/mame82/status/1459157357989187592

@Impact-I
Copy link
Contributor

Impact-I commented Nov 13, 2021

Hi @mame82 ,
Thank you for your interest in the project.

When making these changes to the files /src/third_party/dart/tools/sdks/dart-sdk/lib/_http/http_impl.dart
/src/third_party/dart/sdk/lib/_http/http_impl.dart
Nothing happens. How did you get libflutter_patched.so?
It will be great if you share the library.

@mame82
Copy link
Author

mame82 commented Nov 14, 2021

Okay, as already discussed on Twitter, this approach was invalid.

Patches for SDK code (namely HttpClient) do not end up in libflutter.so as the VM snapshot is compiled into libapp.so.

A working approach to make HttpClient use a proxy by modifying the Dart runtime (and thus ending up in libflutter.so) was found. This could be achieved by modifying the native code implementing Platfom::Environment to add in http_proxyand https_proxy environment variables, which are missing on Android.

The shortcoming of this (compared to overwriting the destination IP for socket connections): While the default behaviour of HttpClient is to determin the Proxy to use based on these environment variables, the application could use HttpClient.findProxy to define a Proxy on App-level, which would overwrite the Proxy defined by the patch.

The screenshot shows a patch-diff for Androids Platform::Environment implementation:

proxified4

Beside not having to rely on an interception proxy which works in transparent mode, a benefit is, that the environment variable also stores the proxy port in the string. So it could be easily overwritten on a pre-compiled binary, as reFlutter already does with the proxy IP.
proxified5

Also adding no_proxy environment variable could add more fine-grained control (not tested).

Last but not least: Such a patch does not interfere with the socket.cc patches already applied. If the proxy defined in the environment variables is used by the app (which is the default for Flutter), the socket.cc patch would rewrite the destination which to the same values which are already set. The difference would be, that the client communicates with the proxy as expected (sends CONNECT requests and uses absolute URLs in request lines.

If the App overwrites the findProxy function, the connect.cc patch still would overwrite the target IP and port. Thus, traffic would still end up at the proxy, but has to be handled transparently (determine target host from Host header, as no absolute URLs are use in request line and no CONNECT requests get sent).

With that, I think there is not much more to add and I want to say THANK YOU for the great project, again!

@Impact-I Impact-I added the enhancement New feature or request label Nov 14, 2021
@mame82
Copy link
Author

mame82 commented Nov 14, 2021

For completeness, I attach a compiled libflutter.so:

  • Snapshot hash: 9cf77f4405212c45daf608e1cd646852
  • Platform: Android
  • Arch: arm32
  • Patches: All reFlutter patches, connect.cc patches have Address rewrite disabled, but still print "ref: <destination IP>" to logcat for TCP connections (not Datagram). The environment variables are altered as described above, by adding the following vars:
    • http_proxy=192.168.8.199:8080
    • https_proxy=192.168.8.199:8080
    • MAME82=test

The following app currently uses a matching libflutter.so and was used for testing: "Knowunity". All flutter connections are correctly passed on to the proxy, without the need of destination IP rewrites.

libflutter_arm32_9cf77f4405212c45daf608e1cd646852.zip

@Impact-I
Copy link
Contributor

@mame82 , Thanks for the contribution to the project. You are a purposeful person.

Ditching a transparent proxy is very tempting. I will need to write a universal patch for all supported Flutter Engine versions. Hopefully this patch will appear in reFlutter. Perfect solution!

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants