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.96k stars 148 forks source link

[Enhancement] Forward Hostname together with SOCKS5 to Orbot 🧅 instead IP #339

Open 4-FLOSS-Free-Libre-Open-Source-Software opened 3 years ago

4-FLOSS-Free-Libre-Open-Source-Software commented 3 years ago

Is there any chance of forwarding the hostname in the SOCKS5 Connect request if we know, instead of IP, instead a previously resolved IP address where known?

Benefits:

Performance

Privacy

Example of resolving and connection user wants to Visit https://rethinkdns.com, and we assume the user connects through OrBot and sets non-leaking DNS to OrBot DNSPort current standard connection setup:

  1. Browser ask rethinkdns.com
  2. A Query for rethinkdns.com gets forwarded to OrBot DNSPort
  3. Orbot uses a 3-hop circuit and asks the exit server for the IP of rethinkdns.com
  4. The exit server reply with 172.67.154.200 all the way back.
  5. Orbot forwards the resolving reply through rethinkdns to the browser
  6. Browser start connection to 172.67.154.200 which rethinkdns forward to orbot over socks5
  7. Orbot uses a 3-hop circuit and asks the exit server to connect to the IP of 172.67.154.200
  8. Orbot waits the exit TCP connection success reply and once received sends back a SOCKS5 Established status message.
  9. The browser starts TLS handshaking and afterwards finally sending GET request for rethinkdns.com

Tor Browser behavior:

  1. Tor Browser start connection to rethinkdns.com over socks5
  2. Tor uses a 3-hop circuit and asks the exit server to connect to the rethinkdns.com Hostname
  3. Tor waits for the exit to resolve the domain and reply TCP connection success reply, and once received sends back a SOCKS5 Established status message.
  4. The Tor Browser starts TLS handshaking and afterwards finally sending GET request for rethinkdns.com

I hope this comparison shows which time-consuming unnecessary steps could be skipped.

ignoramous commented 3 years ago

The more I think about this, the more I feel that this behaviour cannot be changed by RethinkDNS or by Orbot.

  1. The browser does not know there is a SOCKS5 proxy active (when RethinkDNS is setup to forward it over SOCKS5), and hence does not know to send DNS request and the web (HTTP GET) request as one query.
  2. Even if browser knew that connections are forwarded over SOCKS5 (for example, by setting SOCKS5 proxy in Browser's own network settings), I doubt it skips the DNS resolution part.

The Tor Browser is rather optimizing for this behaviour in a very clever way that is otherwise not possible to do outside of a Browser.

Would you know if we can we talk to someone from the GuardianProject to confirm this one way or other?

4-FLOSS-Free-Libre-Open-Source-Software commented 3 years ago
  1. The browser does not know there is a SOCKS5 proxy active (when RethinkDNS is setup to forward it over SOCKS5), and hence does not know to send DNS request and the web (HTTP GET) request as one query.

If the browser is setup to forward to https proxy, it does send the hostname or no?

I see the underlying application got no clue where it's send to actually is socks in VPN mode. Bad example but in windows for example there exists proxifier software which does answer Answer DNS and forward TCP to socks (including hostname of DNS)

Assume If I request DNS.google firewall app resolves 8.8.8.8. if same app that asked resolve IP connect to TCP 8.8.8.8, could firewalls VPN mode TCP forward to socks5 include DNS.google in it's destination As hostname instead just 8.8.8.8 for the connection? So the real Domainname get passed all the way to the actual socks5 proxy? As we earlier learned it by resolve? Could that work?

  1. Even if browser knew that connections are forwarded over SOCKS5 (for example, by setting SOCKS5 proxy in Browser's own network settings), I doubt it skips the DNS resolution part.

Yes, It's called socks5h. To include hostname in socks5 query. Supported natively by chrome and Firefox. The latter have an option in the dialog for it and on Android you can change it by proxy Socks remote DNS flag: .jpg

Would you know if we can we talk to someone from the GuardianProject to confirm this one way or other?

No. I don't.

4-FLOSS-Free-Libre-Open-Source-Software commented 2 years ago

Couldn't this also solve the hostname forwarding issue partially, at least for HTTP/S Destination, since on those protocols the Hostname should be known.

Extract server name requested through SNI Client Hello For the unknown hostname of TLS traffic, it could be extracted from SNI, found one way in reverse proxy mode of how nginx does it:

https://nginx.org/en/docs/stream/ngx_stream_ssl_preread_module.html

ignoramous commented 2 years ago

We could extract the SNI, the capability is already there, but the problem is SNI will soon be ECHd. So that isn't a fool-proof solution either, but sure, it remains a possibility even if it adds a bit of complexity in a critical path (in handling http/s).

ignoramous commented 2 years ago

Extract server name requested through SNI Client Hello. For the unknown hostname of TLS traffic, it could be extracted from SNI...

As an exercise I built just this, but not for Rethink: https://github.com/celzero/midway 'twas fun.

Assume If I request DNS.google firewall app resolves 8.8.8.8. if same app that asked resolve IP connect to TCP 8.8.8.8, could firewalls VPN mode TCP forward to socks5 include DNS.google in it's destination As hostname instead just 8.8.8.8 for the connection? So the real Domainname get passed all the way to the actual socks5 proxy? As we earlier learned it by resolve? Could that work?

Another users pointed me to RFC3089 which describes a mechanism similar to socks5h (?). We are impl exactly this as part of #270