Commit 79540ae6 authored by Felix Yan's avatar Felix Yan

verify: refactor and improve

parent f7f0dae6
...@@ -2,3 +2,4 @@ www.azure.cn.mschcdn.com ...@@ -2,3 +2,4 @@ www.azure.cn.mschcdn.com
www.gov.cn www.gov.cn
a1.cdn-hotels.com a1.cdn-hotels.com
cdn.jsdelivr.net cdn.jsdelivr.net
edge.yunjiasu.com
\ No newline at end of file
...@@ -6,85 +6,166 @@ import random ...@@ -6,85 +6,166 @@ import random
import ipaddress import ipaddress
import tldextract import tldextract
with open("ns-whitelist.txt") as f:
whitelist = list([l.rstrip('\n') for l in f if l])
with open("ns-blacklist.txt") as f: class ChnroutesNotAvailable(Exception):
blacklist = list([l.rstrip('\n') for l in f if l]) pass
with open("cdn-testlist.txt") as f: class NSNotAvailable(Exception):
cdnlist = list([l.rstrip('\n') for l in f if l]) pass
try: # OK
with open("/usr/share/chnroutes2/chnroutes.txt") as f: class OK(Exception):
chnroutes = list([l.rstrip('\n') for l in f if l and not l.startswith("#")]) pass
except:
print(colored("Failed to load chnroutes, CDN check disabled"), "red")
chnroutes = None
class WhitelistMatched(OK):
pass
with open("accelerated-domains.china.raw.txt") as f: class CDNListVerified(OK):
domains = random.sample([line.rstrip('\n') for line in f], 100) pass
# domains = [line.rstrip('\n') for line in f][13820:13830]
class NSVerified(OK):
pass
# Not OK
class NotOK(Exception):
pass
class NXDOMAIN(NotOK):
pass
class BlacklistMatched(NotOK):
pass
class CDNListNotVerified(NotOK):
pass
class NSNotVerified(NotOK):
pass
class ChinaListVerify(object):
whitelist_file = "ns-whitelist.txt"
blacklist_file = "ns-blacklist.txt"
cdnlist_file = "cdn-testlist.txt"
chnroutes_file = "/usr/share/chnroutes2/chnroutes.txt"
def __init__(self):
self.whitelist = self.load_list(self.whitelist_file)
self.blacklist = self.load_list(self.blacklist_file)
self.cdnlist = self.load_list(self.cdnlist_file)
try:
self.chnroutes = self.load_list(self.chnroutes_file)
except FileNotFoundError:
print(colored("Failed to load chnroutes, CDN check disabled", "red"))
self.chnroutes = None
def load_list(self, filename):
with open(filename) as f:
return list([l.rstrip('\n') for l in f if l and not l.startswith("#")])
def test_cn_ip(self, domain):
if self.chnroutes is None:
raise ChnroutesNotAvailable
def cn_ip_test(domain):
answers = dns.resolver.query(domain, 'A') answers = dns.resolver.query(domain, 'A')
answer = answers[0].to_text() answer = answers[0].to_text()
return any(ipaddress.IPv4Address(answer) in ipaddress.IPv4Network(n) for n in chnroutes) return any(ipaddress.IPv4Address(answer) in ipaddress.IPv4Network(n) for n in self.chnroutes)
def check_whitelist(self, nameservers):
if any(i in " ".join(nameservers) for i in self.whitelist):
raise WhitelistMatched
def check_blacklist(self, nameservers):
if any(i in " ".join(nameservers) for i in self.blacklist):
raise BlacklistMatched
def check_cdnlist(self, domain):
if self.test_cn_ip(domain):
raise CDNListVerified
else:
raise CDNListNotVerified
for domain in domains: def check_domain(self, domain):
if domain: nameservers = []
nameserver = None
nameserver_text = ""
ns_failed = False
try: try:
answers = dns.resolver.query(domain, 'NS') answers = dns.resolver.query(domain, 'NS')
except dns.resolver.NXDOMAIN: except dns.resolver.NXDOMAIN:
print(colored("NXDOMAIN found in domain: " + domain, "white", "on_red")) raise NXDOMAIN
continue except:
except Exception: pass
ns_failed = True
else: else:
for rdata in answers: for rdata in answers:
if nameserver is None:
nameserver = rdata.to_text() nameserver = rdata.to_text()
nameserver_text += rdata.to_text() if tldextract.extract(nameserver).registered_domain:
nameservers.append(nameserver)
testdomain = None self.check_whitelist(nameservers)
if any(i in nameserver_text for i in whitelist):
print(colored("NS Whitelist matched for domain: " + domain, "green")) # Assuming CDNList for non-TLDs
elif domain.count(".") > 1 and tldextract.extract(domain).registered_domain != domain or any(testdomain.endswith(domain) for testdomain in cdnlist): if domain.count(".") > 1 and tldextract.extract(domain).registered_domain != domain:
for testdomain in cdnlist: self.check_cdnlist(domain)
for testdomain in self.cdnlist:
if testdomain.endswith(domain): if testdomain.endswith(domain):
break self.check_cdnlist(testdomain)
else:
testdomain = domain self.check_blacklist(nameservers)
if chnroutes:
for nameserver in nameservers:
try: try:
if cn_ip_test(testdomain): if self.test_cn_ip(nameserver):
print(colored("CDNList matched and verified for domain: " + domain, "green")) raise NSVerified
except (dns.resolver.NoAnswer, dns.resolver.NXDOMAIN):
pass
if nameservers:
raise NSNotVerified
else: else:
print(colored("CDNList matched but failed to verify for domain: " + domain, "red")) raise NSNotAvailable
def check_domain_quiet(self, domain):
try:
self.check_domain(domain)
except OK:
return True
except NotOK:
return False
except: except:
print("Failed to find A for cdnlist domain:", testdomain) return None
continue
else:
print(colored("CDNList matched (but verification is not available) for domain: " + domain))
elif any(i in nameserver_text for i in blacklist):
print(colored("NS Blacklist matched for domain: " + domain, "red"))
else: else:
if ns_failed: return None
print("Failed to find NS for domain: " + domain)
elif chnroutes: def check_domain_list(self, domain_list, sample=100):
domains = self.load_list(domain_list)
if sample:
domains = random.sample(domains, sample)
for domain in domains:
try: try:
if cn_ip_test(nameserver): self.check_domain(domain)
except NXDOMAIN:
print(colored("NXDOMAIN found in domain: " + domain, "white", "on_red"))
except WhitelistMatched:
print(colored("NS Whitelist matched for domain: " + domain, "green"))
except CDNListVerified:
print(colored("CDNList matched and verified for domain: " + domain, "green"))
except CDNListNotVerified:
print(colored("CDNList matched but failed to verify for domain: " + domain, "red"))
except BlacklistMatched:
print(colored("NS Blacklist matched for domain: " + domain, "red"))
except NSVerified:
print(colored("NS verified for domain: " + domain, "green")) print(colored("NS verified for domain: " + domain, "green"))
else: except NSNotVerified:
print(colored("NS failed to verify for domain: " + domain, "red")) print(colored("NS failed to verify for domain: " + domain, "red"))
except: except ChnroutesNotAvailable:
print("Failed to find A for NS domain:", nameserver, "domain:", domain) print("Additional Check disabled due to missing chnroutes. domain:", domain)
except NSNotAvailable:
print("Failed to get correct name server for domain:", domain)
else: else:
print("Neutral domain:", domain) raise NotImplementedError
if __name__ == "__main__":
v = ChinaListVerify()
v.check_domain_list("accelerated-domains.china.raw.txt")
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment