]> git.ipfire.org Git - thirdparty/tor.git/commitdiff
Fix DNS resolution on busy exit relays
authorSebastian Hahn <sebastian@torproject.org>
Fri, 3 Nov 2017 02:06:12 +0000 (03:06 +0100)
committerNick Mathewson <nickm@torproject.org>
Sun, 5 Nov 2017 19:36:32 +0000 (14:36 -0500)
Thanks to Dhalgren who analyzed this issue two years ago and found a
solution!

changes/bug21394 [new file with mode: 0644]
src/or/dns.c

diff --git a/changes/bug21394 b/changes/bug21394
new file mode 100644 (file)
index 0000000..e5452e2
--- /dev/null
@@ -0,0 +1,9 @@
+  o Major bugfixes (Exit nodes):
+    - Fix an issue causing high-bandwidth exit nodes to fail a majority
+      or all of their DNS requests, making them basically unsuitable for
+      regular usage in Tor circuits. The problem is related to
+      libevent's DNS handling, but we can work around it in Tor. Fixes
+      bugs 21394 and 18580; bugfix on 0.1.2.2-alpha which introduced
+      eventdns. Credit goes to Dhalgren for identifying and finding a
+      workaround to this bug and to gamambel, arthuredelstein and
+      arma in helping to track it down and analyze it.
index 0ad4c0f5056d9a5934fffa9c0f5f6393ceef5d88..c1e3c3256edfd0297e073ebc273af8093be987ee 100644 (file)
@@ -1425,14 +1425,31 @@ configure_nameservers(int force)
 
 #define SET(k,v)  evdns_base_set_option(the_evdns_base, (k), (v))
 
+  // If we only have one nameserver, it does not make sense to back off
+  // from it for a timeout. Unfortunately, the value for max-timeouts is
+  // currently clamped by libevent to 255, but it does not hurt to set
+  // it higher in case libevent gets a patch for this.
+  // Reducing attempts in the case of just one name server too, because
+  // it is very likely to be a local one where a network connectivity
+  // issue should not cause an attempt to fail.
   if (evdns_base_count_nameservers(the_evdns_base) == 1) {
-    SET("max-timeouts:", "16");
-    SET("timeout:", "10");
+    SET("max-timeouts:", "1000000");
+    SET("attempts:", "1");
   } else {
     SET("max-timeouts:", "3");
-    SET("timeout:", "5");
   }
 
+  // Elongate the queue of maximum inflight dns requests, so if a bunch
+  // time out at the resolver (happens commonly with unbound) we won't
+  // stall every other DNS request. This potentially means some wasted
+  // CPU as there's a walk over a linear queue involved, but this is a
+  // much better tradeoff compared to just failing DNS requests because
+  // of a full queue.
+  SET("max-inflight:", "8192");
+
+  // Time out after 5 seconds if no reply.
+  SET("timeout:", "5");
+
   if (options->ServerDNSRandomizeCase)
     SET("randomize-case:", "1");
   else