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.64k stars 135 forks source link

First few requests to DNSCrypt not routed over proxy #1307

Open plkonbklo opened 3 months ago

plkonbklo commented 3 months ago

Rethink configuration: Connect over SOCKS5 proxy. Configuration -> Network -> enabled "Use all available networks (experimental)" and "Loopback (experimental)" Configuration -> Network -> "Choose fallback DNS" set to None Configuration -> DNS -> Other DNS -> DNSCrypt -> Quad9

I'm checking the traffic with wireshark and I see that the DNSCrypt Quad9 traffic to 9.9.9.12:8443 is going outside of SOCKS5. If I change DNS to DoH Quad9 then DNS traffic is going over SOCKS5. So the problem is only with DNSCrypt.

ignoramous commented 3 months ago

Thanks. Super strange. We will take a look.

What you observe also happens with the Loopback mode turned OFF?

plkonbklo commented 3 months ago

Enabling or disabling loopback seems to make no change.

With enabled or disabled loopback and DoH: Resolved successfully for test.com resolved anonymously X min. ago by dns.quad9.net via proxy S5 Resolved successfully for dns.quad9.net resolved X min. ago by rethink 8.8.4.4:53 No leak in wireshark for test.com resolving but dns.quad9.net resolving is leaked.

With enabled or disabled loopback and DNS 53: Resolved successfully for test.com resolved anonymously X min. ago by 9.9.9.9:53 via proxy S5 No leak in wireshark.

With enabled or disabled loopback and DoT: Resolved successfully for test.com resolved anonymously X min. ago by adblock.dns.mullvad.net:853 via proxy S5 Resolved successfully for adblock.dns.mullvad.net resolved X min. ago by rethink 192.168.240.1:53 No leak in wireshark for test.com resolving but adblock.dns.mullvad.net resolving is leaked.

With enabled or disabled loopback and DNSCrypt: Resolved successfully for test.com resolved anonymously X min. ago by 2.dnscrypt-cert.quad9.net via proxy S5 No leak in wireshark for test.com resolving and 2.dnscrypt-cert.quad9.net resolving. But Rethink connects to 9.9.9.12:8443 directly and not through proxy when you change DNS to Quad9 DNSCrypt and before you try to resolve test.com.

plkonbklo commented 3 months ago

Also even though in Rethink log the dns.quad9.net and adblock.dns.mullvad.net are shown as resolved by Cache but the DNS queries to resolve these hosts are still sent over clearnet using System DNS every time when you switch the DNS.

plkonbklo commented 3 months ago

I'm checking the traffic with wireshark and I see that the DNSCrypt Quad9 traffic to 9.9.9.12:8443 is going outside of SOCKS5. If I change DNS to DoH Quad9 then DNS traffic is going over SOCKS5.

To correct myself, the DNS traffic to resolve the hosts is going through SOCKS5 but the initial connection to DNSCrypt server when you switch the DNS is going directly and not through SOCKS5.

ignoramous commented 3 months ago

but the initial connection to DNSCrypt server when you switch the DNS is going directly and not through SOCKS5.

This is expected. Rethink uses "Fallback DNS" to resolve domains that it needs to. "None" means it uses "System DNS".

Also even though in Rethink log the dns.quad9.net and adblock.dns.mullvad.net are shown as resolved by Cache but the DNS queries to resolve these hosts are still sent over clearnet using System DNS every time when you switch the DNS.

Cache may refresh entries in the background (which means, even though the Cache responded to the query, it may still forward it to a DNS upstream if it thinks the entries are "old").

As above, "Fallback DNS" determines the DNS server Rethink itself uses to resolve domains for its own self, where "None" means "System DNS".

plkonbklo commented 3 months ago

but the initial connection to DNSCrypt server when you switch the DNS is going directly and not through SOCKS5.

This is expected. Rethink uses "Fallback DNS" to resolve domains that it needs to. "None" means it uses "System DNS".

In case of DNSCrypt it's not trying to resolve 2.dnscrypt-cert.quad9.net or some other domain using System DNS when you change the DNS to DNSCrypt but it's connecting to IP address 9.9.9.12:8433 directly avoiding proxy.

As above, "Fallback DNS" determines the DNS server Rethink itself uses to resolve domains for its own self, where "None" means "System DNS".

Was the behavior of "Fallback DNS" set to "None" changed after completing this issue? https://github.com/celzero/rethink-app/issues/967 Or was the meaning of "disables fallback" just that it's using System DNS instead of not using any? In that case it'd be better to rename "None" to "System DNS" so there won't be any misunderstandings.

ignoramous commented 3 months ago

Or was the meaning of "disables fallback" just that it's using System DNS instead of not using any? In that case it'd be better to rename "None" to "System DNS" so there won't be any misunderstandings.

There's a subtle difference. May be it isn't worded right, but "None" means uses whatever is the underlying network's DNS (often same as "System DNS" but not always), which was the case before "Fallback DNS" was introduced.

connecting to IP address 9.9.9.12:8433 directly avoiding proxy

That's a bug. I'll take a look pronto. In DNS Logs, it should have ideally reported, resolved anonymously X min. ago by 2.dnscrypt-cert.quad9.net via proxy:S5 (which you're not seeing).

plkonbklo commented 3 months ago

There's a subtle difference. May be it isn't worded right, but "None" means uses whatever is the underlying network's DNS (often same as "System DNS" but not always), which was the case before "Fallback DNS" was introduced.

I've tested it and it actually works as None should for DNS queries that Rethink is handling. I guess only the DNS queries that are trying to resolve chosen DNS (and maybe proxy?) host are going to System DNS in case the fallback DNS is None. I think it'd be good to make a note of this behavior near the None entry in the fallback DNS selection menu.

That's a bug. I'll take a look pronto. In DNS Logs, it should have ideally reported, resolved anonymously X min. ago by 2.dnscrypt-cert.quad9.net via proxy:S5 (which you're not seeing).

Yes, I don't see the DNS query in the Logs -> DNS for 2.dnscrypt-cert.quad9.net but I see the connections to 9.9.9.12 in the Logs -> Rethink tab.

ignoramous commented 2 months ago

We have fixed a tonne of bug in v055f including relay selection for DNSCrypt.

F-Droid and Play Store should get the update within a week. Please test it and let us know if the issue has been fixed for you.

plkonbklo commented 2 months ago

This issue wasn't fixed in v055f. If I switch to Quad9 DNSCrypt then I see the connections to 9.9.9.12 in the Logs -> Rethink tab and in Wireshark.

hussainmohd-a commented 2 months ago

The default Quad9 DNSCrypt stamp points to 9.9.9.12 Quad9 (anycast) no-dnssec/no-log/no-filter/ecs 9.9.9.12

plkonbklo commented 2 months ago

I have SOCKS5 proxy configured so the expected behavior is for DNSCrypt initial connection to go through proxy, but for some reason when you change the used DNS server to DNSCrypt it'll connect directly to DNSCrypt server bypassing proxy at first and only following DNS requests will be forwarded through proxy. If it needs to resolve some DNSCrypt server domain (e.g. 2.dnscrypt-cert.quad9.net?) during this initial connection then I'd assume it'd use System DNS (or Fallback DNS) while bypassing proxy and not the DNSCrypt server itself while bypassing proxy. At least that's how it works for DoH servers.

ignoramous commented 2 months ago

If it needs to resolve some DNSCrypt server domain (e.g. 2.dnscrypt-cert.quad9.net?) during this initial connection then I'd assume it'd use System DNS (or Fallback DNS) while bypassing proxy and not the DNSCrypt server itself while bypassing proxy. At least that's how it works for DoH servers.

Ah, I see. This is expected. As part of AKE, the DNSCrypt protocol requires that the keys be fetched straight from the DNSCrypt resolver itself.

# a TXT record with public key for adguard.com's dnscrypt servers is fetched 
# from adguard's own resolver but on port 5443; this information is embed in
# DNSCrypt stamp "sdns://...", which for adguard.com is:
# sdns://AQMAAAAAAAAAETk0LjE0MC4xNC4xNDo1NDQzINErR_JS3PLCu_iZEIbq95zkSV2LFsigxDIuUso_OQhzIjIuZG5zY3J5cHQuZGVmYXVsdC5uczEuYWRndWFyZC5jb20
dig -t TXT @94.140.14.14 2.dnscrypt.default.ns1.adguard.com. -p 5443 +tcp +short | hexdump -C

00000000  22 44 4e 53 43 5c 30 30  30 5c 30 30 31 5c 30 30  |"DNSC\000\001\00|
00000010  30 5c 30 30 30 5c 30 32  39 2b 5c 32 30 37 5c 32  |0\000\029+\207\2|
00000020  33 35 42 7e 5c 31 36 32  5c 32 31 37 5c 30 31 31  |35B~\162\217\011|
00000030  5c 31 33 39 5c 31 34 32  5c 22 5c 31 34 32 5c 31  |\139\142\"\142\1|
00000040  35 34 67 5c 30 30 37 68  60 43 30 67 29 5c 31 34  |54g\007h`C0g)\14|
00000050  32 5c 32 35 34 2c 5c 32  33 38 76 5d 5c 30 30 39  |2\254,\238v]\009|
00000060  40 5c 32 34 38 5c 31 33  38 5c 31 32 38 73 5c 32  |@\248\138\128s\2|
00000070  33 34 5c 30 31 37 6c 50  5c 32 31 34 5c 32 31 34  |34\017lP\214\214|
00000080  56 5c 30 32 30 5c 32 32  31 5c 32 35 31 5c 32 34  |V\020\221\251\24|
00000090  37 5c 32 30 37 69 5c 32  32 33 5c 31 38 35 5c 31  |7\207i\223\185\1|
000000a0  34 35 39 24 5c 30 31 33  5c 32 32 31 5c 31 38 30  |459$\013\221\180|
000000b0  4a 57 3f 5c 32 33 31 63  5a 5c 30 31 32 6c 5c 30  |JW?\231cZ\012l\0|
000000c0  30 35 5c 31 36 37 63 5c  31 37 37 5c 30 32 33 5c  |05\167c\177\023\|
000000d0  30 30 38 51 5c 31 34 36  5c 32 35 31 5c 32 34 34  |008Q\146\251\244|
000000e0  5f 5c 30 32 31 5c 32 32  39 5c 30 32 30 5c 32 30  |_\021\229\020\20|
000000f0  34 58 58 5c 30 31 33 51  5c 32 31 37 3b 5c 31 39  |4XX\013Q\217;\19|
00000100  30 33 62 3d 20 5c 32 33  32 5c 31 35 32 5c 30 31  |03b= \232\152\01|
00000110  38 3a 7b 4b 5d 5c 30 30  30 5c 30 30 30 5c 30 30  |8:{K]\000\000\00|
00000120  30 5c 30 30 30 5c 30 30  30 5c 30 30 30 5c 30 30  |0\000\000\000\00|
00000130  30 5c 30 30 30 66 29 30  6d 66 29 30 6d 68 5c 30  |0\000f)0mf)0mh\0|
00000140  31 30 63 5c 32 33 37 22  0a                       |10c\237".|
00000149
plkonbklo commented 2 months ago

Is it possible to configure it to fetch the keys through proxy?

ignoramous commented 2 months ago

Is it possible to configure it to fetch the keys through proxy?

We explicitly don't do that since retrieving certs via proxy/relay was found to be unreliable. We could bring it back, but it comes with significant complexity in terms of failure modes and how it should be communicated to the user.

plkonbklo commented 2 months ago

Isn't it a privacy issue when you generate a key using your clearnet IP and then use it using your proxy IP? That way the DNSCrypt provider will know your real IP address behind proxy. For example, it'd be a threat for someone using Orbot and assuming their clearnet IP won't be leaked while using DNSCrypt.

I don't know how DNSCrypt works in details so correct me if I'm wrong and this is not an issue.

ignoramous commented 2 months ago

Isn't it a privacy issue

Not really. Actual DNS queries are always sent from behind a proxy. And so, DNSCrypt server has no way to correlate between request sent to fetch its public key and the DNS requests themselves.

when you generate a key

The first phase (in "clearnet") isn't key generation, but rather key discovery.

DNSCrypt provider will know your real IP address

Yes, but this isn't as big a concern.

it'd be a threat for someone using Orbot and assuming their clearnet IP won't be leaked while using DNSCrypt.

It is problematic to expect privacy with any DNS over Orbot. Folks should prefer Orbot's DNS or use ODoH (Oblivious DNS over HTTPS) or use DNSCrypt with Anonymizing Relays.

plkonbklo commented 2 months ago

Not really. Actual DNS queries are always sent from behind a proxy. And so, DNSCrypt server has no way to correlate between request sent to fetch its public key and the DNS requests themselves.

I've read the RFC draft and it seems that it could be used for targeted attack if DNSCrypt resolver send you a separate private certificate that it'll dedicate only for your session.

I've also found this info there:

The client must check for new certificates every hour, and switch to a new certificate if: the current certificate is not present or not valid any more or a certificate with a higher serial number than the current one is available.

I guess this periodic cert check will be through clearnet in Rethink as well?

It is problematic to expect privacy with any DNS over Orbot. Folks should prefer Orbot's DNS or use ODoH (Oblivious DNS over HTTPS) or use DNSCrypt with Anonymizing Relays.

I'd be good to make a note of this DNSCrypt behavior at least, because I think any user would assume that all DNSCrypt traffic will go through proxy.

ignoramous commented 2 months ago

if DNSCrypt resolver send you a separate private certificate

If a rouge resolver does so, I don't see how a intermediate proxy helps mitigate it.

guess this periodic cert check will be through

Yes, but this check happens once every 4 hours (code).

good to make a note of this DNSCrypt behavior at least

Makes sense. Though, I'm leaning towards removing DNSCrypt altogether, tbh.

plkonbklo commented 2 months ago

If a rouge resolver does so, I don't see how a intermediate proxy helps mitigate it.

The attack can be done like this: You're using proxy (or proxy chain) with Rethink to access some websites and attacker wants to know what websites are you accessing through proxy. Or even your activity on these websites if attacker has access to them. You have a static clearnet IP address and attacker knows it. Or attacker can determine that specific connection is coming from your device (have access to your ISP info). Attacker is controlling the DNSCrypt resolver that you choose in Rethink. You're connecting to DNSCrypt resolver from your clearnet IP address and DNSCrypt resolver gives you a private certificate to track you for this session. When you're connecting to https://github.com using your browser through proxy, Rethink is using this certificate to send a query to resolve "github.com" domain to DNSCrypt resolver and this query is going through proxy. Now DNSCrypt resolver knows that the certificate issued to your clearnet IP address is being used by this proxy IP address and this proxy IP address is associated with you. But if you're connecting to DNSCrypt resolver through proxy when both getting the certificates and querying for domain resolution then DNSCrypt resolver will only know your proxy IP address and won't have any info about your clearnet IP address.

If it's not a private proxy and this IP address is used by multiple people then it won't be possible to confidently tie the proxy to you like this. For public proxies or Tor it won't lead to outright deanonymization, but it'd be easier to do a timing attack.

This is a rather specific attack and couldn't be implement by just anyone but it's a possibility.