From 32a8e2fd7e4d64bb39da986b3c2afbcb01112c60 Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Thu, 28 Sep 2017 11:27:04 +0100 Subject: [PATCH 1/2] Handle SERVFAILs when doing AAAA lookups for federation ... to cope with people with broken dnssec setups, mostly --- synapse/http/endpoint.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/synapse/http/endpoint.py b/synapse/http/endpoint.py index 241b17f2cb9a..a29cb3165551 100644 --- a/synapse/http/endpoint.py +++ b/synapse/http/endpoint.py @@ -354,8 +354,14 @@ def cb(res): return res[0] - def eb(res): - res.trap(DNSNameError) + def eb(res, record_type): + if not res.check(DNSNameError): + # we log errors that occur here, but otherwise treat them as an + # empty result, which means we'll fall back to the A record if the + # AAAA record lookup fails, etc. (Which happens when people + # mess up their DNSSEC deployments) + logger.warn("Error looking up %s for %s: %s", + record_type, host, res, res.value) return [] # no logcontexts here, so we can safely fire these off and gatherResults From 3d475936dcb3907b73ae1c2b9ade733ef23d4779 Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Thu, 28 Sep 2017 12:57:38 +0100 Subject: [PATCH 2/2] Avoid blowing out cache on temporary DNS failures If all of the lookups for a particular host fail, fall back to using the cache. --- synapse/http/endpoint.py | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/synapse/http/endpoint.py b/synapse/http/endpoint.py index a29cb3165551..a97532162f1c 100644 --- a/synapse/http/endpoint.py +++ b/synapse/http/endpoint.py @@ -355,21 +355,27 @@ def cb(res): return res[0] def eb(res, record_type): - if not res.check(DNSNameError): - # we log errors that occur here, but otherwise treat them as an - # empty result, which means we'll fall back to the A record if the - # AAAA record lookup fails, etc. (Which happens when people - # mess up their DNSSEC deployments) - logger.warn("Error looking up %s for %s: %s", - record_type, host, res, res.value) - return [] + if res.check(DNSNameError): + return [] + logger.warn("Error looking up %s for %s: %s", + record_type, host, res, res.value) + return res # no logcontexts here, so we can safely fire these off and gatherResults d1 = dns_client.lookupAddress(host).addCallbacks(cb, eb) d2 = dns_client.lookupIPV6Address(host).addCallbacks(cb, eb) - results = yield defer.gatherResults([d1, d2], consumeErrors=True) + results = yield defer.DeferredList( + [d1, d2], consumeErrors=True) + + # if all of the lookups failed, raise an exception rather than blowing out + # the cache with an empty result. + if results and all(s == defer.FAILURE for (s, _) in results): + defer.returnValue(results[0][1]) + + for (success, result) in results: + if success == defer.FAILURE: + continue - for result in results: for answer in result: if not answer.payload: continue