Filename: 205-local-dnscache.txt Title: Remove global client-side DNS caching Author: Nick Mathewson Created: 20 July 2012 Status: Open
0. Overview
This proposal suggests that, for reasons of security, we move client-side DNS caching from a global cache to a set of per-circuit caches.
This will break some things that used to work. I'll explain how to fix them.
1. Background and Motivation
Since the earliest Tor releases, we've kept a client-side DNS cache. This lets us implement exit policies and exit enclaves -- if we remember that www.mit.edu is 18.9.22.169 the first time we see it, then we can avoid making future requests for www.mit.edu via any node that blocks net 18. Also, if there happened to be a Tor node at 18.9.22.169, we could use that node as an exit enclave.
But there are security issues with DNS caches. A malicious exit node or DNS server can lie. And unlike other traffic, where the effect of a lie is confined to the request in question, a malicious exit node can affect the behavior of future circuits when it gives a false DNS reply. This false reply could be used to keep a client connecting to an MITM'd target, or to make a client use a chosen node as an exit enclave for that node, or so on.
With IPv6, tracking attacks will become even more possible: A hostile exit node can give every client a different IPv6 address for every hostname they want to resolve, such that every one of those addresses is under the attacker's control.
And even if the exit node is honest, having a cached DNS result can cause Tor clients to build their future circuits distinguishably: the exit on any subsequent circuit can tell whether the client knew the IP for the address yet or not. Further, if the site's DNS provides different answers to clients from different parts of the world, then the client's cached choice of IP will reveal where it first learned about the website.
So client-side DNS caching needs to go away.
2. Design
2.1. The basic idea
I propose that clients should cache DNS results in per-circuit DNS caches, not in the global address map.
2.2. What about exit policies?
Microdescriptor-based clients have already dropped the ability to track which nodes declare which exit policies, without much ill effect. As we go forward, I think that remembering the IP address of each request so that we can match it to exit policies will be even less effective, especially if proposals to allow AS-based exit policies can succeed.
2.3. What about exit enclaves?
Exit enclaves are already borken. They need to move towards a cross-certification solution where a node advertises that it can exit to a hostname or domain X.Y.Z, and a signed record at X.Y.Z advertises that the node is an enclave exit for X.Y.Z. That's out-of-scope for this proposal, except to note that nothing proposed here keeps that design from working.
2.4. What about address mapping?
Our current address map algorithm is, more or less:
N = 0 while N < MAX_MAPPING && exists map[address]: address = map[address] N = N + 1 if N == MAX_MAPPING: Give up, it's a loop.
Where 'map' is the union of all mapping entries derived from the controller, the configuration file, trackhostexits maps, virtual-address maps, DNS replies, and so on.
With this design, the DNS cache will not be part of the address map. That means that entries in the address map which relied on happening after the DNS cache entries can no longer work so well. These would include:
A) Mappings from an IP address to a particular exit, either manually declared or inserted by TrackHostExits. B) Mappings from IP addresses to other IP addresses. C) Mappings from IP addresses to hostnames.
We can try to solve these by introducing an extra step of address mapping after the DNS cache is applied. In other words, we should apply the address map, then see if we can attach to a circuit. If we can, we try to apply that circuit's dns cache, then apply the address map again.
2.5. What about the performance impact?
That all depends on application behavior.
If the application continues to make all of its requests with the hostname, there shouldn't be much trouble. Exit-side DNS caches and exit-side DNS will avoid any additional round trips across the Tor network; compared to that, the time to do a DNS resolution at the exit node *should* be small.
That said, this will hurt performance a little in the case where the exit node and its resolver don't have the answer cached, and it takes a long time to resolve the hostname.
If the application is doing "resolve, then connect to an IP", see 2.6 below.
2.6. What about DNSPort?
If the application is doing its own DNS caching, they won't get much security benefit from here.
If the application is doing a resolve before each connect, there will be a performance hit when the resolver is using a circuit that hadn't previously resolved the address.
Also, DNSPort users: AutomapHostsOnResolve is your friend.
3. Alternate designs and future directions
3.1. Why keep client-side DNS caching at all?
A fine question! I am not sure it actually buys us anything any longer, since exits also have DNS caching. Shall we discuss that? It would sure simplify matters.
3.2. The impact of DNSSec
Once we get DNSSec support, clients will be able to verify whether an exit's answers are correctly signed or not. When that happens, we could get most of the benefits of global DNS caching back, without most of the security issues, if we restrict it to DNSSec-signed answers.
[tl;dr: We should make client-side DNS cacheing off by default.]
On Fri, Jul 20, 2012 at 6:27 PM, Nick Mathewson nickm@freehaven.net wrote:
Filename: 205-local-dnscache.txt Title: Remove global client-side DNS caching Author: Nick Mathewson Created: 20 July 2012 Status: Open
[...] For the original proposal, see https://lists.torproject.org/pipermail/tor-dev/2012-July/003817.html
3.1. Why keep client-side DNS caching at all?
A fine question! I am not sure it actually buys us anything any longer, since exits also have DNS caching. Shall we discuss that? It would sure simplify matters.
On consideration, I'm actually reasonably sure that eliminating client-side DNS cacheing (or at least, turning it off by default) is a much better answer than making DNS caches per-circuit. I've got an implementation of my new approach on ticket #7570 (https://trac.torproject.org/projects/tor/ticket/7570).
So, why is it okay to disable client-side DNS cacheing entirely?
Applications that care about speed should be doing a one-round-trip connect mechanism: either a SOCKS request with a hostname in it, or a TransPort request to an automapped address. If client-side DNS cacheing is disabled, these behaviors result in Tor sending the exit node a RELAY_BEGIN cell with a hostname in it. If the exit node is has received a request for that hostname recently, it will have the answer in its DNS cache, and the use of the hostname won't slow the request down. If the exit node has _not_ received a request for that hostname recently, there will be no answer in its cache... but neither would there be any answer in a per-circuit DNS cache for a circuit to that exit.
Applications that do a two-step "resolve then connect" approach will be a little slowed down in cases where Tor would have kept the answer in the client cache. But they would already be slowed down somewhat by proposal 205, which can't be avoided if we want proposal 205's improved security. See note on automapping below for a workaround.
(And if you're asking, "Why would I even want to disable client-side DNS cacheing?", see proposal 205, linked above.)
Incidentally, elsewhere in the proposal I said,
If the application is doing its own DNS caching, they won't get much security benefit from here.
It looks like a bunch of applications *do* DNS cacheing. For them, in 0.2.4, I'd suggest maybe running Tor in a configuration where every name lookup gets automapped to a random IPv6 address. That kind of automapping should be possible in Tor 0.2.4 , if the changes in ticket #7571 are right and get merged.
Another note that I had forgotten: Applications that do their own DNS cacheing won't get affected by proposal 205, or by disabling client-side DNS cacheing, unless they use Tor's DNSPort or Tor's "SOCKS RESOLVE" extension to do name lookups. That's because (I think!) our SOCKS replies don't include IP addresses; If I'm reading this code right, they just set the address to 0.0.0.0, which applications should interpret as "Tor isn't going to tell you what the IP is".
yrs,
On Sun, Nov 25, 2012 at 7:54 PM, Nick Mathewson nickm@freehaven.net wrote:
[tl;dr: We should make client-side DNS cacheing off by default.]
Nitpickery: s/cacheing/caching/g
Applications that care about speed should be doing a one-round-trip connect mechanism: either a SOCKS request with a hostname in it, or a TransPort request to an automapped address. If client-side DNS cacheing is disabled, these behaviors result in Tor sending the exit node a RELAY_BEGIN cell with a hostname in it. If the exit node is has received a request for that hostname recently, it will have the answer in its DNS cache, and the use of the hostname won't slow the request down. If the exit node has _not_ received a request for that hostname recently, there will be no answer in its cache... but neither would there be any answer in a per-circuit DNS cache for a circuit to that exit.
Applications that do a two-step "resolve then connect" approach will be a little slowed down in cases where Tor would have kept the answer in the client cache. But they would already be slowed down somewhat by proposal 205, which can't be avoided if we want proposal 205's improved security. See note on automapping below for a workaround.
(And if you're asking, "Why would I even want to disable client-side DNS cacheing?", see proposal 205, linked above.)
FWIW this makes sense to me from a DNS point of view, and I agree that the one-trip case should be no worse under this proposal than it was previously.
Incidentally, elsewhere in the proposal I said,
If the application is doing its own DNS caching, they won't get much security benefit from here.
It looks like a bunch of applications *do* DNS cacheing. For them, in 0.2.4, I'd suggest maybe running Tor in a configuration where every name lookup gets automapped to a random IPv6 address. That kind of automapping should be possible in Tor 0.2.4 , if the changes in ticket #7571 are right and get merged.
Alas, yes, and browsers (I'm looking at you, Firefox) are some of the worst offenders (though hopefully not in the "normal" Tor case of SOCKS). I have issued many curses towards applications doing their own caching (often ignoring TTLs too, of course). The automapping in question seems sane to me.
Tim
On Sun, Nov 25, 2012 at 07:54:51PM -0500, Nick Mathewson wrote:
[tl;dr: We should make client-side DNS cacheing off by default.]
Be careful -- we seem to rely on the client-side dns cache to let us move on to a new circuit if the current circuit's exit policy doesn't like the stream.
See in connection_ap_process_end_not_open() when we get an END cell of reason END_STREAM_REASON_EXITPOLICY. In that case we remember the mapping between the hostname we sent and the IP address we got back in the END cell: client_dns_set_addressmap(circ, conn->socks_request->address, &addr, conn->chosen_exit_name, ttl); and then when we call /* rewrite it to an IP if we learned one. */ if (addressmap_rewrite(conn->socks_request->address, sizeof(conn->socks_request->address), NULL, NULL)) { it gets rewritten to the IP address so we'll avoid this circuit when we call connection_ap_detach_retriable(). If the rewrite doesn't look at the cache, then we'll just try this circuit once more.
(Also, if we have no client-side dns cache, further streams requesting the same address, e.g. fetching pictures from the website, might try the same circuit even if we could know that its exit policy would refuse the stream.)
While I was looking at this design, I thought of a cool attack on 0.2.3 users: a malicious website embeds a link to an image at the IP address of the exit relay. The client will check whether her circuit's exit node can handle it: connection_ap_can_use_exit() calls compare_tor_addr_to_node_policy() which calls compare_tor_addr_to_short_policy() which says yes (or more precisely, not no). When the client attempts the connection, the exit relay (which probably has ExitPolicyRejectPrivate set) refuses it, and the client then says: /* check if he *ought* to have allowed it */ if (exitrouter && (rh->length < 5 || (tor_inet_aton(conn->socks_request->address, &in) && !conn->chosen_exit_name))) { log_info(LD_APP, "Exitrouter %s seems to be more restrictive than its exit " "policy. Not using this router as exit for now.", node_describe(exitrouter)); policies_set_node_exitpolicy_to_reject_all(exitrouter); } i.e. the client never uses that exit as an exit again, until either it falls out of the consensus or she restarts her client. (Neither nodelist_set_consensus() nor nodelist_add_microdesc() updates node->rejects_all.)
(The website can't launch this attack by linking to a 10.x.y.z IP address, since the client checks: if (get_options()->ClientDNSRejectInternalAddresses && tor_addr_is_internal(&addr, 0)) { log_info(LD_APP,"Address '%s' resolved to internal. Closing,", )
So the attack is that the website methodically targets all users coming from all exit relays it doesn't control. If the user logs in to the website or otherwise identifies herself, then the attack variant is that the website can target just her. A popular website (say, one of the ad servers) could potentially get quite thorough attack coverage quite quickly.
In compare_tor_addr_to_short_policy() I wrote about a similar attack, but apparently I didn't think about the "website causes you to open a stream there" angle at the time.)
The bandaid fix is that we should reset node->rejects_all in nodelist_set_consensus() just like we reset is_valid, is_running, etc from the consensus.
The better fix is that we need to either make clients have an accurate view of the relay's exit policy (is that ticket 1774?), or we need to stop behaving so drastically when we only know a microdescriptor for the relay and it declines to exit to an address that its short policy looks like it should accept.
And assuming this last approach is best, that ties it into the first half of this email.
--Roger
On Tue, 27 Nov 2012 00:49:28 -0500 Roger Dingledine arma@mit.edu wrote:
(Also, if we have no client-side dns cache, further streams requesting the same address, e.g. fetching pictures from the website, might try the same circuit even if we could know that its exit policy would refuse the stream.)
So, perhaps have a cache but only consult it for making decisions about whether to use a circuit, not for resolving client requests? Although this is still vulnerable to poisoning, that could perhaps be mitigated by capping the TTL at some small value.
The bandaid fix is that we should reset node->rejects_all in nodelist_set_consensus() just like we reset is_valid, is_running, etc from the consensus.
The better fix is that we need to either make clients have an accurate view of the relay's exit policy (is that ticket 1774?), or we need to stop behaving so drastically when we only know a microdescriptor for the relay and it declines to exit to an address that its short policy looks like it should accept.
What an interesting vulnerability, especially as it shows that ad servers can in fact be a serious attack vector. May I propose a more thorough solution? What if there were some mechanism by which, when an exit rejects the connection, it can provide its full policy to the client at that point? This would give it a chance to explain the situation (i.e. it's not actually rejecting everything), without requiring any change to the microdescriptor. Obviously the client can cache this info, and any node which subsequently doesn't honour its declared policy can still be (temporarily?) blacklisted.
(Please forgive me if I'm missing something obvious. I'm not yet as familiar with Tor's inner workings as I'd like to be.)
Julian
On Tue, Nov 27, 2012 at 10:08 AM, Julian Yon julian@yon.org.uk wrote:
On Tue, 27 Nov 2012 00:49:28 -0500 Roger Dingledine arma@mit.edu wrote:
(Also, if we have no client-side dns cache, further streams requesting the same address, e.g. fetching pictures from the website, might try the same circuit even if we could know that its exit policy would refuse the stream.)
So, perhaps have a cache but only consult it for making decisions about whether to use a circuit, not for resolving client requests? Although this is still vulnerable to poisoning, that could perhaps be mitigated by capping the TTL at some small value.
There's an interesting idea! I wonder, can we come up with a way to tell whether it's necessary?
It's not likely to help typical clients, since microdescriptor-users (and all IPv6 users) don't see the full exit policy, but only a policy summary.
The bandaid fix is that we should reset node->rejects_all in nodelist_set_consensus() just like we reset is_valid, is_running, etc from the consensus.
The better fix is that we need to either make clients have an accurate view of the relay's exit policy (is that ticket 1774?), or we need to stop behaving so drastically when we only know a microdescriptor for the relay and it declines to exit to an address that its short policy looks like it should accept.
What an interesting vulnerability, especially as it shows that ad servers can in fact be a serious attack vector. May I propose a more thorough solution? What if there were some mechanism by which, when an exit rejects the connection, it can provide its full policy to the client at that point? This would give it a chance to explain the situation (i.e. it's not actually rejecting everything), without requiring any change to the microdescriptor. Obviously the client can cache this info, and any node which subsequently doesn't honour its declared policy can still be (temporarily?) blacklisted.
(Please forgive me if I'm missing something obvious. I'm not yet as familiar with Tor's inner workings as I'd like to be.)
My main worry here is that an exit could give different clients different exit policies. I'm not sure yes if there's a clever way to bootstrap that into a full attack, but generally when you give an attacker the ability to give different clients different views of the network, you can run into trouble.
yrs,
On Tue, 27 Nov 2012 20:53:03 -0500 Nick Mathewson nickm@alum.mit.edu wrote:
On Tue, Nov 27, 2012 at 10:08 AM, Julian Yon julian@yon.org.uk wrote:
So, perhaps have a cache but only consult it for making decisions about whether to use a circuit, not for resolving client requests? Although this is still vulnerable to poisoning, that could perhaps be mitigated by capping the TTL at some small value.
There's an interesting idea! I wonder, can we come up with a way to tell whether it's necessary?
It might be possible experimentally. Implement it as an optional codepath. Run in both configurations for a while, and in each case monitor the number/percentage of refused connections the average added latency due to refusal, and the percentage of total latency that this represents.
It's not likely to help typical clients, since microdescriptor-users (and all IPv6 users) don't see the full exit policy, but only a policy summary.
Hmm. From the summary we know which destination ports we can use, so the time we have a problem is (e.g.) when an exit allows port 80 in general but not for the particular IP/netblock in question. This is a rare case, but when we do hit it, without DNS caching every single request is going to bounce, isn't it? Given the number of resources on a typical modern webpage, this implies that occasionally somebody is going to find that suddenly their latency goes through the roof because of an unlucky combination of website and exit. And so maybe it's not quite as simple as the above experiment :-/
What's needed is to determine whether the effect is large enough that it needs to be accounted for, or whether it's just an inconvenient corner case. So I think maybe performing some measurements using an artificially small ExitNodes list, giving a high probability of hitting a restrictive exit, may be necessary (obviously the call that Roger mentioned to policies_set_node_exitpolicy_to_reject_all needs to be disabled or it'll just get blacklisted on the first hit).
And of course you're right, unless clients have some way of knowing to avoid the exit it's a moot point, so...
My main worry here is that an exit could give different clients different exit policies. I'm not sure yes if there's a clever way to bootstrap that into a full attack, but generally when you give an attacker the ability to give different clients different views of the network, you can run into trouble.
Ok, that's a fair concern. Two variations sprang to mind immediately:
(1) Add a hash of each router's full exit policy to the consensus. The client can use this to verify that it's being given the same info as everyone else. For policies that are fully covered by the summary, this line could be omitted (as it should never be needed).
(2) The first time an exit rejects a connection, ask another party (directory authority/mirror) for the full policy at that point. However, I see that a related idea has been floated before (Proposal 141). Presumably there were good reasons why that proposal wasn't implemented. Certainly I can immediately see the potential for information leakage.
But as I was writing the top half of this email I then thought:
(3) Don't bother trying to ascertain the full exit policy, but rather maintain a simple table of exit/IP/port combinations that have been rejected and consult it when building/using circuits. This requires no protocol changes (win!) at the cost of no longer blacklisting dishonest exits entirely. Some mechanism for expiring entries would probably be a good idea, and/or maybe hold it in a circular list so that there's a maximum number.
As far as I can see, all of these would mitigate Roger's attack, and (3) feels like it should be particularly easy to implement and while it doesn't solve #1774 I can't see how it introduces any new problems. Thoughts? Is it really that simple?
Julian
On Thu, Nov 29, 2012 at 06:14:23PM +0000, Julian Yon wrote:
(3) Don't bother trying to ascertain the full exit policy, but rather maintain a simple table of exit/IP/port combinations that have been rejected and consult it when building/using circuits. This requires no protocol changes (win!) at the cost of no longer blacklisting dishonest exits entirely. Some mechanism for expiring entries would probably be a good idea, and/or maybe hold it in a circular list so that there's a maximum number.
I had this same thought while rereading my earlier message: just prepend a reject rule for this ip:port to our local version of the relay's exit policy.
It does let the exit "tag" you with an IP:port combo that you'll never come back to it with. But that seems a small risk compared to the risk of an exit relay with a complex enough policy that it causes clients to spend two circuits for fetching each component of web pages.
--Roger
On Tue, Dec 18, 2012 at 6:42 PM, Roger Dingledine arma@mit.edu wrote:
On Thu, Nov 29, 2012 at 06:14:23PM +0000, Julian Yon wrote:
(3) Don't bother trying to ascertain the full exit policy, but rather maintain a simple table of exit/IP/port combinations that have been rejected and consult it when building/using circuits. This requires no protocol changes (win!) at the cost of no longer blacklisting dishonest exits entirely. Some mechanism for expiring entries would probably be a good idea, and/or maybe hold it in a circular list so that there's a maximum number.
I had this same thought while rereading my earlier message: just prepend a reject rule for this ip:port to our local version of the relay's exit policy.
It does let the exit "tag" you with an IP:port combo that you'll never come back to it with. But that seems a small risk compared to the risk of an exit relay with a complex enough policy that it causes clients to spend two circuits for fetching each component of web pages.
Good idea! I've added it to https://trac.torproject.org/projects/tor/ticket/7582
On Tue, Nov 27, 2012 at 12:49 AM, Roger Dingledine arma@mit.edu wrote:
On Sun, Nov 25, 2012 at 07:54:51PM -0500, Nick Mathewson wrote:
[tl;dr: We should make client-side DNS cacheing off by default.]
Be careful -- we seem to rely on the client-side dns cache to let us move on to a new circuit if the current circuit's exit policy doesn't like the stream.
See in connection_ap_process_end_not_open() when we get an END cell of reason END_STREAM_REASON_EXITPOLICY. In that case we remember the mapping between the hostname we sent and the IP address we got back in the END cell: client_dns_set_addressmap(circ, conn->socks_request->address, &addr, conn->chosen_exit_name, ttl); and then when we call /* rewrite it to an IP if we learned one. */ if (addressmap_rewrite(conn->socks_request->address, sizeof(conn->socks_request->address), NULL, NULL)) { it gets rewritten to the IP address so we'll avoid this circuit when we call connection_ap_detach_retriable(). If the rewrite doesn't look at the cache, then we'll just try this circuit once more.
I think the right answer in this case is not to touch the cache at all, but rather to update conn->socks_request->address, setting it to match addr. Using the cache for this is quite roundabout and silly IMO. I'll add a commit to this effect on my branch.
[...]
While I was looking at this design, I thought of a cool attack on 0.2.3 users:
[...]
The bandaid fix is that we should reset node->rejects_all in nodelist_set_consensus() just like we reset is_valid, is_running, etc from the consensus.
Agreed. As another bandaid, we could give same-IP addresses an exception -- but that wouldn't work for any other interesting exit policies.
The better fix is that we need to either make clients have an accurate view of the relay's exit policy (is that ticket 1774?),
I don't know if it's 1774, since we really don't have a great answer for 1774 other than "we should redesign exit policies." That's not going to happen for 0.2.3, though, and it's doesn't seem likely for 0.2.4 at this point.
or we need to stop behaving so drastically when we only know a microdescriptor for the relay and it declines to exit to an address that its short policy looks like it should accept.
I think that's plausible but vague. There are lots of things under the heading of "less drastic".
At the very least, we need to ensure that this particular stream isn't attached to this circuit again. That wouldn't necessarily be so hard. There are probably even backportable versions of that we could try.
On Tue, Nov 27, 2012 at 8:42 PM, Nick Mathewson nickm@alum.mit.edu wrote:
On Tue, Nov 27, 2012 at 12:49 AM, Roger Dingledine arma@mit.edu wrote:
[...]
While I was looking at this design, I thought of a cool attack on 0.2.3 users:
This is now Ticket #7582 on trac.
yrs,
Thus spake Nick Mathewson (nickm@freehaven.net):
[tl;dr: We should make client-side DNS cacheing off by default.]
On Fri, Jul 20, 2012 at 6:27 PM, Nick Mathewson nickm@freehaven.net wrote:
Filename: 205-local-dnscache.txt Title: Remove global client-side DNS caching Author: Nick Mathewson
For the original proposal, see https://lists.torproject.org/pipermail/tor-dev/2012-July/003817.html
3.1. Why keep client-side DNS caching at all?
A fine question! I am not sure it actually buys us anything any longer, since exits also have DNS caching. Shall we discuss that? It would sure simplify matters.
On consideration, I'm actually reasonably sure that eliminating client-side DNS cacheing (or at least, turning it off by default) is a much better answer than making DNS caches per-circuit. I've got an implementation of my new approach on ticket #7570 (https://trac.torproject.org/projects/tor/ticket/7570).
So, why is it okay to disable client-side DNS cacheing entirely?
Nick asked me this in private email:
Every socks response has an IP address in it. So when Firefox asks for "www.mit.edu" in a SOCKS4a or a SOCKS5 request, Tor gives it "18.9.22.169" in the SOCKS response.
Does Firefox cache these values? That is, in the next SOCKS request that Firefox makes for "www.mit.edu", will Firefox ask Tor to connect to "www.mit.edu", or to "18.9.22.169"?
Under normal non-SOCKS operation, Firefox does attempt to cache DNS resolutions for a long period of time (I think on the order of an hour or more). The reason is because of DNS-based subversions of the same-origin policy: https://en.wikipedia.org/wiki/DNS_rebinding http://www.securityfocus.com/columnists/455
Interestingly, the two main vectors discussed there are not as useful against Tor, but perhaps worth having on your radar when considering DNS cache alterations.
Further, the SOCKS behavior for Firefox is quite different than non-proxied use, perhaps because of the limited vectors for rebinding. It tends to make very few actual SOCKS4a resolutions, instead perferring to use direct SOCKS4A hostname connects. Unfortunately, the details of where and why it actually does decide to do a SOCKS4a resolution are unknown to me and would require some digging.
This reminds me that I plan to re-audit as much of Firefox's networking glue as I can for Firefox 17-ESR, to verify it hasn't changed in ways that allow DNS leaks or proxy bypass. I've created this ticket if you want to add further DNS-related questions for me to look into once I start that process: https://trac.torproject.org/projects/tor/ticket/7248
I'm asking because of proposal-205 reasons.
Proposal 205 might cause problems for DNS rebinding if the dirty circuit expiry is small enough for evil JS to simply wait for a fresh circuit to alter the destination IP of important origins.
However, this vector is eliminated by SSL, and will be mitigated by making circuit use more closely tied to first party origin (using SOCKS username+password from Prop171).
On Tue, Dec 18, 2012 at 7:34 PM, Mike Perry mikeperry@torproject.org wrote:
Thus spake Nick Mathewson (nickm@freehaven.net):
[tl;dr: We should make client-side DNS cacheing off by default.]
On Fri, Jul 20, 2012 at 6:27 PM, Nick Mathewson nickm@freehaven.net wrote:
Filename: 205-local-dnscache.txt Title: Remove global client-side DNS caching Author: Nick Mathewson
For the original proposal, see https://lists.torproject.org/pipermail/tor-dev/2012-July/003817.html
3.1. Why keep client-side DNS caching at all?
A fine question! I am not sure it actually buys us anything any longer, since exits also have DNS caching. Shall we discuss that? It would sure simplify matters.
On consideration, I'm actually reasonably sure that eliminating client-side DNS cacheing (or at least, turning it off by default) is a much better answer than making DNS caches per-circuit. I've got an implementation of my new approach on ticket #7570 (https://trac.torproject.org/projects/tor/ticket/7570).
So, why is it okay to disable client-side DNS cacheing entirely?
Nick asked me this in private email:
Every socks response has an IP address in it. So when Firefox asks for "www.mit.edu" in a SOCKS4a or a SOCKS5 request, Tor gives it "18.9.22.169" in the SOCKS response.
Does Firefox cache these values? That is, in the next SOCKS request that Firefox makes for "www.mit.edu", will Firefox ask Tor to connect to "www.mit.edu", or to "18.9.22.169"?
Under normal non-SOCKS operation, Firefox does attempt to cache DNS resolutions for a long period of time (I think on the order of an hour or more). The reason is because of DNS-based subversions of the same-origin policy: https://en.wikipedia.org/wiki/DNS_rebinding http://www.securityfocus.com/columnists/455
Importantly, I was wrong above. Tor does not actually provide DNS results in response to SOCKS connect requests; only in response to deliberate hostname lookups.
Interestingly, the two main vectors discussed there are not as useful against Tor, but perhaps worth having on your radar when considering DNS cache alterations.
Further, the SOCKS behavior for Firefox is quite different than non-proxied use, perhaps because of the limited vectors for rebinding. It tends to make very few actual SOCKS4a resolutions, instead perferring to use direct SOCKS4A hostname connects. Unfortunately, the details of where and why it actually does decide to do a SOCKS4a resolution are unknown to me and would require some digging.
This might be a little confused. There is no such thing as a standard SOCKS resolution: the ability to do a hostname lookup in SOCKS without doing a connection is a Tor extension.