celzero / rethink-app

DNS over HTTPS / DNS over Tor / DNSCrypt client, WireGuard proxifier, firewall, and connection tracker for Android.
https://rethinkfirewall.com/
Apache License 2.0
2.79k stars 139 forks source link

Bug: "Universally bypassed" apps are NOT universally bypassing the DNS / Firewall #1598

Open esrat opened 1 month ago

esrat commented 1 month ago

Hi, I noticed a rather destructive bug on Android 13 on a Moto E13!

Just configure a browser of your choice (tested with F-Droid's Fennec and Mull) as "Bypass Universal". (General settings are to block all connections and unblock single apps.) This works most of the time, with web servers on standard ports and only one port per server, quite well. But it does not work in this situation: I am connecting to a web server to load some web-application. This JS-application does call an application server on the same machine but a different port. According to Rethink's log there are no blocked connections. I can see the access to the web server for each resource as well as the FIRST access to the application server's port. But only the first one is let passed! Normally there is an update cycle which executes the same request (to the application server and displays the results) again and again - but on my LAN even this fails (web- and application-service both on the same IP-address - no DNS needed)! At least this part somehow works when accessing the server with its public DNS name. - But when the sequential requests are different from each other then all requests beginning from the second one are not coming through any more!

On the application server's log I can always see the first call coming from the web application, but never the second one! Rethink's log never shows additional connection attempts despite the first one.

I did not find any other settings in Rethink to make it work. The only "work around" I know of is to completely disable Rethink! (The DNS-part I already disabled before.) But running no firewall at all is of course no solution, so I have to switch back to Netguard which never had this problem, no matter if I do use LAN or public connections.

I cannot find out what is the part which Rethink is still blocking since the log is disabled when the firewall is turned off. So I have nothing to compare. I guess it must be some fundamental network mechanism since I always see only the very first request to the application server. Requests to the web server are not blocked.

ignoramous commented 1 month ago

Thanks.

Can you please share code or steps to reproduce the issue on our Androids to help debug this?

have to switch back to Netguard which never had this problem, no matter if I do use LAN or public connections. I cannot find out

I don't use NetGuard but, NetGuard's "bypass" may be equivalent to Rethink's "Exclude" (and not "Bypass Universal").

esrat commented 1 month ago

Hi, I do not want to "Exclude" any app - even Fennec is making lots of unknown connections I do not need and do not want to happen. With excluding an app I cannot even see these connection attempts any more. Sadly, that is no solution. And yes, the interaction between web application and application server works fine with excluding the whole browser app --- and no, NetGuard's implementation is not equivalent to this! The free version only enables the user to block or unblock the network access of an app completely (distinguished by WLAN and mobile data). But it still handles the connection attempts for unblocked apps. It is aware of these attempts and does show them to the user if they wish to see them. - So, it is no "exclusion" from the VPN.

Can you please share code or steps to reproduce the issue on our Androids to help debug this?

Sadly, I cannot give you access to the service I am experiencing problems with. It is a private project. But I can try to explain the situation more systematically. I have access to the application server which is implementing a REST service and does log all connection attempts. So I can see any requests reaching the server.

The setup is this: Machine A runs a web server on port X and the application server on port Y. Machine B, the Android device, runs a JavaScript enabled browser to connect to the web server on port X.

There are no problems connecting to the web server. All resources can be loaded from port X.

Then the JS script (/ browser app) starts connecting to the application server on port Y (which also talks HTTP to provide its REST service). So it uses a base URI of the type "http://the.same.domain:portY/" (instead of "http://the.same.domain:portX/" to load resources from the web server).

This works when it is only one request. The web application gets its response and displays the data inside the website.

But when there are two different requests to the application server then only the first one succeeds! Machine B (the web application running on the browser app) has to start request 1, wait for its result and then start request 2 (and wait for its result). But on the server log I can see only request 1! No other request makes it through.

The two requests only differ on the application level (calling different URLs on the same server domain and port Y). These should not make a difference on lower network layers, but still, only the first one comes through, the second one gets filtered by Rethink!

ignoramous commented 1 month ago

Gotcha. Thanks for the detailed writeup.

Is portY (the one doesn't work in your example above) one of 53, 443 or 853? If so, see if changing it to some other port number rectifies the issue you're seeing.

esrat commented 1 month ago

No, both ports are "free", meaning residing within the user range >= 1024. No well-known ports are used.

ignoramous commented 1 month ago

No, both ports are "free", meaning residing within the user range >= 1024. No well-known ports are used.

If you're technical enough, can you put Rethink in Very Verbose mode from Configure -> Settings -> Log level, and then capture and share (email: mz at celzero dot com; mention this github issue please) the output from adb logcat | grep -iE "(vpnlife|golog)"?