def resolve_domain(domain, rdtype): # FIXME make this work for IPv6-only hosts too.. ok, result = dig(dyn_host, "A") dyn_host_ip = result[0] if ok == "ok" and len(result) else None if not dyn_host_ip: raise YunohostError("Failed to resolve %s" % dyn_host) ok, result = dig(domain, rdtype, resolvers=[dyn_host_ip]) if ok == "ok": return result[0] if len(result) else None elif result[0] == "Timeout": logger.debug( "Timed-out while trying to resolve %s record for %s using %s" % (rdtype, domain, dyn_host)) else: return None logger.debug("Falling back to external resolvers") ok, result = dig(domain, rdtype, resolvers="force_external") if ok == "ok": return result[0] if len(result) else None elif result[0] == "Timeout": logger.debug( "Timed-out while trying to resolve %s record for %s using external resolvers : %s" % (rdtype, domain, result)) else: return None raise YunohostError("Failed to resolve %s for %s" % (rdtype, domain), raw_msg=True)
def check_expiration_date(self, domains): """ Alert if expiration date of a domain is soon """ details = {"not_found": [], "error": [], "warning": [], "success": []} for domain in domains: expire_date = self.get_domain_expiration(domain) if isinstance(expire_date, str): status_ns, _ = dig(domain, "NS", resolvers="force_external") status_a, _ = dig(domain, "A", resolvers="force_external") if "ok" not in [status_ns, status_a]: details["not_found"].append(( "diagnosis_domain_%s_details" % (expire_date), { "domain": domain }, )) else: self.logger_debug("Dyndns domain: %s" % (domain)) continue expire_in = expire_date - datetime.now() alert_type = "success" if expire_in <= timedelta(15): alert_type = "error" elif expire_in <= timedelta(45): alert_type = "warning" args = { "domain": domain, "days": expire_in.days - 1, "expire_date": str(expire_date), } details[alert_type].append(("diagnosis_domain_expires_in", args)) for alert_type in ["success", "error", "warning", "not_found"]: if details[alert_type]: if alert_type == "not_found": meta = {"test": "domain_not_found"} else: meta = {"test": "domain_expiration"} # Allow to ignore specifically a single domain if len(details[alert_type]) == 1: meta["domain"] = details[alert_type][0][1]["domain"] yield dict( meta=meta, data={}, status=alert_type.upper() if alert_type != "not_found" else "WARNING", summary="diagnosis_domain_expiration_" + alert_type, details=details[alert_type], )
def check_blacklist(self): """ Check with dig onto blacklist DNS server This check is ran on IPs and domains we could used to send mail. """ dns_blacklists = read_yaml(DEFAULT_DNS_BLACKLIST) for item in self.ips + self.mail_domains: for blacklist in dns_blacklists: item_type = "domain" if ":" in item: item_type = "ipv6" elif re.match(r"^\d+\.\d+\.\d+\.\d+$", item): item_type = "ipv4" if not blacklist[item_type]: continue # Build the query for DNSBL subdomain = item if item_type != "domain": rev = dns.reversename.from_address(item) subdomain = str(rev.split(3)[0]) query = subdomain + "." + blacklist["dns_server"] # Do the DNS Query status, _ = dig(query, "A") if status != "ok": continue # Try to get the reason details = [] status, answers = dig(query, "TXT") reason = "-" if status == "ok": reason = ", ".join(answers) details.append("diagnosis_mail_blacklist_reason") details.append("diagnosis_mail_blacklist_website") yield dict( meta={ "test": "mail_blacklist", "item": item, "blacklist": blacklist["dns_server"], }, data={ "blacklist_name": blacklist["name"], "blacklist_website": blacklist["website"], "reason": reason, }, status="ERROR", summary="diagnosis_mail_blacklist_listed_by", details=details, )
def check_blacklist(self): """ Check with dig onto blacklist DNS server This check is ran on IPs and domains we could used to send mail. """ dns_blacklists = read_yaml(DEFAULT_DNS_BLACKLIST) for item in self.ips + self.mail_domains: for blacklist in dns_blacklists: item_type = "domain" if ":" in item: item_type = 'ipv6' elif re.match(r'^\d+\.\d+\.\d+\.\d+$', item): item_type = 'ipv4' if not blacklist[item_type]: continue # Build the query for DNSBL subdomain = item if item_type != "domain": rev = dns.reversename.from_address(item) subdomain = str(rev.split(3)[0]) query = subdomain + '.' + blacklist['dns_server'] # Do the DNS Query status, _ = dig(query, 'A') if status != 'ok': continue # Try to get the reason details = [] status, answers = dig(query, 'TXT') reason = "-" if status == 'ok': reason = ', '.join(answers) details.append("diagnosis_mail_blacklist_reason") details.append("diagnosis_mail_blacklist_website") yield dict(meta={ "test": "mail_blacklist", "item": item, "blacklist": blacklist["dns_server"] }, data={ 'blacklist_name': blacklist['name'], 'blacklist_website': blacklist['website'], 'reason': reason }, status="ERROR", summary='diagnosis_mail_blacklist_listed_by', details=details)
def get_current_record(self, domain, name, type_): query = "%s.%s" % (name, domain) if name != "@" else domain success, answers = dig(query, type_, resolvers="force_external") if success != "ok": return None else: return answers[0] if len(answers) == 1 else answers
def check_fcrdns(self): """ Check the reverse DNS is well defined by doing a Forward-confirmed reverse DNS check This check is ran on IPs we could used to send mail. """ for ip in self.ips: if ":" in ip: ipversion = 6 details = [ "diagnosis_mail_fcrdns_nok_details", "diagnosis_mail_fcrdns_nok_alternatives_6" ] else: ipversion = 4 details = [ "diagnosis_mail_fcrdns_nok_details", "diagnosis_mail_fcrdns_nok_alternatives_4" ] rev = dns.reversename.from_address(ip) subdomain = str(rev.split(3)[0]) query = subdomain if ipversion == 4: query += '.in-addr.arpa' else: query += '.ip6.arpa' # Do the DNS Query status, value = dig(query, 'PTR', resolvers="force_external") if status == "nok": yield dict(meta={ "test": "mail_fcrdns", "ipversion": ipversion }, data={ "ip": ip, "ehlo_domain": self.ehlo_domain }, status="ERROR", summary="diagnosis_mail_fcrdns_dns_missing", details=details) continue rdns_domain = '' if len(value) > 0: rdns_domain = value[0][:-1] if value[0].endswith( '.') else value[0] if rdns_domain != self.ehlo_domain: details = [ "diagnosis_mail_fcrdns_different_from_ehlo_domain_details" ] + details yield dict( meta={ "test": "mail_fcrdns", "ipversion": ipversion }, data={ "ip": ip, "ehlo_domain": self.ehlo_domain, "rdns_domain": rdns_domain }, status="ERROR", summary="diagnosis_mail_fcrdns_different_from_ehlo_domain", details=details)