mirror of
https://github.com/luzifer-docker/personal-dns.git
synced 2024-12-30 01:11:19 +00:00
124 lines
3.3 KiB
Python
Executable file
124 lines
3.3 KiB
Python
Executable file
#!/usr/bin/env python
|
|
|
|
import random
|
|
import re
|
|
|
|
import requests
|
|
import jinja2
|
|
import dns.resolver
|
|
|
|
|
|
BLACKLIST_FILE = 'https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts'
|
|
IANA_TLD_LIST = 'https://data.iana.org/TLD/tlds-alpha-by-domain.txt'
|
|
INTERNIC_ROOT_FILE = 'https://www.internic.net/domain/named.root'
|
|
OPENNIC_ROOT = '75.127.96.89'
|
|
OPENNIC_FILTER = ["..", "opennic.glue."]
|
|
IANA_FILTERS = ['arpa.']
|
|
|
|
roots = None
|
|
|
|
|
|
def get_generic_ip(fqdn):
|
|
res = dns.resolver.Resolver()
|
|
ans = res.query(fqdn, 'A')
|
|
|
|
return ans.rrset.items[0].to_text()
|
|
|
|
|
|
def get_iana_tlds():
|
|
tlds = requests.get(IANA_TLD_LIST).text.split("\n")
|
|
return [t.lower()+'.' for t in tlds if len(t) > 0 and t[0] != "#"]
|
|
|
|
|
|
def get_internic_roots():
|
|
global roots
|
|
|
|
if roots is not None:
|
|
return roots
|
|
|
|
named_file = requests.get(INTERNIC_ROOT_FILE).text
|
|
roots = []
|
|
for line in named_file.split("\n"):
|
|
match = re.search(r"\s+A\s+([0-9]+\.[0-9]+\.[0-9]+\.[0-9]+)$", line)
|
|
if match is None:
|
|
continue
|
|
roots.append(match.group(1))
|
|
return roots
|
|
|
|
|
|
def get_iana_zone_master(zone):
|
|
query = dns.message.make_query(zone, dns.rdatatype.NS)
|
|
ans = dns.query.tcp(query, random.choice(get_internic_roots()))
|
|
|
|
glue = {i.name.__str__(): i.items[0].address
|
|
for i in ans.additional
|
|
if i.rdtype == dns.rdatatype.A}
|
|
|
|
auth = [i.to_text() for i in ans.authority[0].items]
|
|
|
|
return [glue[i] for i in auth if i in glue]
|
|
|
|
|
|
def opennic_ip_from_master(master):
|
|
res = dns.resolver.Resolver()
|
|
res.nameservers = [OPENNIC_ROOT]
|
|
ans = res.query(master, 'A')
|
|
|
|
return [i.to_text() for i in ans.rrset.items]
|
|
|
|
|
|
def get_opennic_zone_master(zone):
|
|
res = dns.resolver.Resolver()
|
|
res.nameservers = [OPENNIC_ROOT]
|
|
ans = res.query('{}.opennic.glue.'.format(zone.strip('.')), 'CNAME')
|
|
|
|
masters = [t.strip('"')
|
|
for t in ans.rrset.items[0].to_text().split(" ")
|
|
if t.startswith('ns')]
|
|
masters.append('ns0.opennic.glue.')
|
|
master_ips = [opennic_ip_from_master(m) for m in masters]
|
|
return [item for sublist in master_ips for item in sublist]
|
|
|
|
|
|
def get_opennic_tlds():
|
|
res = dns.resolver.Resolver()
|
|
res.nameservers = [OPENNIC_ROOT]
|
|
ans = res.query('tlds.opennic.glue.', 'TXT')
|
|
|
|
return [t.strip('"')+'.' for t in ans.rrset.items[0].to_text().split(" ")]
|
|
|
|
|
|
def main():
|
|
entries = {
|
|
"opennic.glue.": [OPENNIC_ROOT],
|
|
}
|
|
|
|
iana_tlds = get_iana_tlds()
|
|
if len(iana_tlds) == 0:
|
|
raise Exception("No IANA TLDs found")
|
|
for tld in get_iana_tlds():
|
|
if tld in IANA_FILTERS:
|
|
continue
|
|
print("Working on IANA TLD '{}'...".format(tld))
|
|
entries[tld] = get_iana_zone_master(tld)
|
|
|
|
opennic_tlds = get_opennic_tlds()
|
|
if len(opennic_tlds) == 0:
|
|
raise Exception("No OpenNIC TLDs found")
|
|
for tld in get_opennic_tlds():
|
|
if tld in OPENNIC_FILTER:
|
|
continue
|
|
print("Working on OpenNIC TLD '{}'...".format(tld))
|
|
entries[tld] = get_opennic_zone_master(tld)
|
|
|
|
with open('named.stubs', 'w') as f:
|
|
f.write(render_corefile(entries))
|
|
|
|
|
|
def render_corefile(entries):
|
|
template = jinja2.Template(open("named.stubs.j2").read())
|
|
return template.render(entries=entries)
|
|
|
|
|
|
if __name__ == '__main__':
|
|
main()
|