Correctly handle cases where domain works in IPv4 but not IPv6 or viceversa

This commit is contained in:
Alexandre Aubin 2020-04-16 03:21:01 +02:00
parent 7f3cc33487
commit e8730ad92b
2 changed files with 38 additions and 20 deletions

View file

@ -48,15 +48,20 @@ class WebDiagnoser(Diagnoser):
# is working and therefore we'll do it only if at least one ipv4 domain
# works.
self.do_hairpinning_test = False
ipversions = []
ipv4 = Diagnoser.get_cached_report("ip", item={"test": "ipv4"}) or {}
if ipv4.get("status") == "SUCCESS":
for item in self.test_http(domains_to_check, ipversion=4):
yield item
ipversions.append(4)
# To be discussed: we could also make this check dependent on the
# existence of an AAAA record...
ipv6 = Diagnoser.get_cached_report("ip", item={"test": "ipv6"}) or {}
if ipv6.get("status") == "SUCCESS":
for item in self.test_http(domains_to_check, ipversion=6):
yield item
ipversions.append(6)
for item in self.test_http(domains_to_check, ipversions):
yield item
# If at least one domain is correctly exposed to the outside,
# attempt to diagnose hairpinning situations. On network with
@ -80,32 +85,44 @@ class WebDiagnoser(Diagnoser):
# issue but something else super weird ...
pass
def test_http(self, domains, ipversion):
def test_http(self, domains, ipversions):
try:
r = Diagnoser.remote_diagnosis('check-http',
data={'domains': domains,
"nonce": self.nonce},
ipversion=ipversion)
results = r["http"]
except Exception as e:
raise YunohostError("diagnosis_http_could_not_diagnose", error=e)
results = {}
for ipversion in ipversions:
try:
r = Diagnoser.remote_diagnosis('check-http',
data={'domains': domains,
"nonce": self.nonce},
ipversion=ipversion)
results[ipversion] = r["http"]
except Exception as e:
raise YunohostError("diagnosis_http_could_not_diagnose", error=e)
assert set(results.keys()) == set(domains)
for domain in domains:
for domain, result in results.items():
if result["status"] == "ok":
if ipversion == 4:
# If both IPv4 and IPv6 (if applicable) are good
if all(results[ipversion][domain]["status"] == "ok" for ipversion in ipversions):
if 4 in ipversions:
self.do_hairpinning_test = True
yield dict(meta={"domain": domain},
status="SUCCESS",
summary="diagnosis_http_ok")
else:
# If both IPv4 and IPv6 (if applicable) are failed
elif all(results[ipversion][domain]["status"] != "ok" for ipversion in ipversions):
detail = results[4 if 4 in ipversions else 6][domain]["status"]
yield dict(meta={"domain": domain},
status="ERROR",
summary="diagnosis_http_unreachable",
details=[result["status"].replace("error_http_check", "diagnosis_http")])
details=[detail.replace("error_http_check", "diagnosis_http")])
# If only IPv4 is failed or only IPv6 is failed (if applicable)
else:
passed, failed = (4, 6) if results[4][domain]["status"] == "ok" else (6, 4)
detail = results[failed][domain]["status"]
yield dict(meta={"domain": domain},
data={"passed": passed, "failed": failed},
status="ERROR",
summary="diagnosis_http_partially_unreachable",
details=[detail.replace("error_http_check", "diagnosis_http")])
def main(args, env, loggers):

View file

@ -217,6 +217,7 @@
"diagnosis_http_unknown_error": "An error happened while trying to reach your domain, it's very likely unreachable.",
"diagnosis_http_bad_status_code": "Timed-out while trying to contact your server from outside. It might be that another machine answered instead of your server.<br>1. The most common cause for this issue is that you did not correctly configure port forwarding for port 80.<br>2. On more complex setups: make sure that a firewall or reverse-proxy is not interfering.",
"diagnosis_http_unreachable": "Domain {domain} appears unreachable through HTTP from outside the local network.",
"diagnosis_http_partiallu_unreachable": "Domain {domain} appears unreachable through HTTP from outside the local network in IPv{failed}, though it works in IPv{passed}.",
"diagnosis_http_nginx_conf_not_up_to_date": "This domain's nginx configuration appears to have been modified manually, and prevents YunoHost from diagnosing if it's reachable on HTTP.",
"diagnosis_http_nginx_conf_not_up_to_date_details": "To fix the situation, inspect the difference with the command line using <cmd>yunohost tools regen-conf nginx --dry-run --with-diff</cmd> and if you're ok, apply the changes with <cmd>yunohost tools regen-conf nginx --force</cmd>.",
"diagnosis_unknown_categories": "The following categories are unknown: {categories}",