parsing zonefile and putting it in database

This commit is contained in:
Arnold Dechamps 2024-02-26 07:06:14 +01:00
commit 3ba7da8cca
No known key found for this signature in database
GPG key ID: AE66543374E41C89
3 changed files with 102 additions and 18 deletions

View file

@ -1,13 +1,13 @@
from admin_extra_buttons.api import ExtraButtonsMixin, button from admin_extra_buttons.api import ExtraButtonsMixin, button
from admin_extra_buttons.utils import HttpResponseRedirectToReferrer from admin_extra_buttons.utils import HttpResponseRedirectToReferrer
from django.contrib import admin from django.contrib import admin
from .models import TLD from .models import TLD, RootZone
import tldtester.sorter as sorter import tldtester.sorter as sorter
import threading import threading
class tlds(ExtraButtonsMixin, admin.ModelAdmin): class tlds(ExtraButtonsMixin, admin.ModelAdmin):
list_display = ('tld', 'nsamount', 'v4nsamount', 'v6nsamount', 'lastEdition') list_display = ('tld', 'nsamount', 'v4nsamount', 'v6nsamount', 'dnssec', 'lastEdition')
@button(change_form=True, html_attrs={'style': 'background-color:#88FF88;color:black'}) @button(change_form=True, html_attrs={'style': 'background-color:#88FF88;color:black'})
def refresh(self, request): def refresh(self, request):
@ -18,4 +18,9 @@ class tlds(ExtraButtonsMixin, admin.ModelAdmin):
return HttpResponseRedirectToReferrer(request) return HttpResponseRedirectToReferrer(request)
class RootZones(admin.ModelAdmin):
list_display = ('name', 'rectype', 'value', 'lastEdition')
admin.site.register(TLD, tlds) admin.site.register(TLD, tlds)
admin.site.register(RootZone, RootZones)

View file

@ -26,7 +26,7 @@ class TLD(models.Model):
(253, "private algorithm"), (253, "private algorithm"),
(254, "private algorithm OID"), (254, "private algorithm OID"),
(300, "Unknown"), (300, "Unknown"),
(400, "None"),
) )
tld = models.CharField(max_length=30, primary_key=True) tld = models.CharField(max_length=30, primary_key=True)
nsamount = models.IntegerField(default=0) nsamount = models.IntegerField(default=0)
@ -48,14 +48,15 @@ class TLD(models.Model):
class RootZone(models.Model): class RootZone(models.Model):
name = models.CharField(max_length=50) name = models.CharField(max_length=50)
type = models.CharField(max_length=10) rectype = models.CharField(max_length=10)
value = models.CharField(max_length=4096) value = models.CharField(max_length=4096)
lastEdition = models.DateTimeField(auto_now=True)
def __str__(self): def __str__(self):
return self.tld return self.name
class Meta: class Meta:
indexes = [ indexes = [
models.Index(fields=["name"]), models.Index(fields=["name"]),
models.Index(fields=["type"]), models.Index(fields=["rectype"]),
] ]

View file

@ -3,13 +3,27 @@ This file is dumping the IANA root zone and sorting it in the database
Link to IANA website : https://www.internic.net/domain/root.zone Link to IANA website : https://www.internic.net/domain/root.zone
""" """
import urllib.request import urllib.request
from tldtester.models import TLD from tldtester.models import TLD, RootZone
import dns.resolver import dns.resolver
def downloader(): def zonedownloader():
""" """
Downloads the data. Returns None if not working, returns a list of TLD's if working Downloads the root zone (as to not put constraint on the DNSses and resolve locally). Returns the zonefile in lines.
returns None if not working.
"""
url = urllib.request.urlopen("https://www.internic.net/domain/root.zone")
if url.getcode() == 200:
raw = url.read()
raw = raw.decode("utf-8")
else:
raw = None
return raw
def tlddownloader():
"""
Downloads the TLD data. Returns None if not working, returns a list of TLD's if working. Returns None if not working
""" """
url = urllib.request.urlopen("https://data.iana.org/TLD/tlds-alpha-by-domain.txt") url = urllib.request.urlopen("https://data.iana.org/TLD/tlds-alpha-by-domain.txt")
if url.getcode() == 200: if url.getcode() == 200:
@ -22,7 +36,34 @@ def downloader():
return raw return raw
def dbwriter(recs): def zonesorter(zonefile):
"""
Takes the zonefile as an input and writes the records to the database
"""
for line in zonefile:
value = ""
record = line.split()
if len(record) >= 5:
name = record[0]
recordtype = record[3]
for i in range(len(record) - 4):
value = value + record[i + 4] + " "
towrite = {"name": name, "type": recordtype, "value": value}
zonedbwriter(towrite)
def zonedbwriter(recs):
"""
Writes the Zone File to database
"""
db = RootZone()
db.name = recs["name"]
db.rectype = recs["type"]
db.value = recs["value"]
db.save()
def tlddbwriter(recs):
""" """
Writes the dictionnary values in the database Writes the dictionnary values in the database
""" """
@ -34,6 +75,7 @@ def dbwriter(recs):
db.nsamount = recs["nsserveramount"] db.nsamount = recs["nsserveramount"]
db.v4nsamount = recs["v4resolvers"] db.v4nsamount = recs["v4resolvers"]
db.v6nsamount = recs["v6resolvers"] db.v6nsamount = recs["v6resolvers"]
db.dnssec = recs["algo"]
db.save() db.save()
@ -44,32 +86,68 @@ def grabber(data):
""" """
for tld in data: for tld in data:
nsservers = [] nsservers = []
dnsseckeys = []
Arecords = 0 Arecords = 0
AAAArecords = 0 AAAArecords = 0
ns = dns.resolver.resolve(tld, 'NS') try:
for server in ns: ns = dns.resolver.resolve(tld, 'NS')
nsservers.append(server.to_text()) for server in ns:
nsservers.append(server.to_text())
except Exception as e:
print(e)
for Arecord in nsservers: for Arecord in nsservers:
try: try:
dns.resolver.resolve(Arecord, 'A') try:
dns.resolver.resolve(Arecord, 'A')
except Exception as e:
# retry
print(e)
dns.resolver.resolve(Arecord, 'A')
Arecords += 1 Arecords += 1
except Exception as e: except Exception as e:
print(e) print(e)
for AAAArecord in nsservers: for AAAArecord in nsservers:
try: try:
dns.resolver.resolve(AAAArecord, 'AAAA') try:
dns.resolver.resolve(AAAArecord, 'AAAA')
except Exception as e:
# retry
print(e)
dns.resolver.resolve(AAAArecord, 'AAAA')
AAAArecords += 1 AAAArecords += 1
except Exception as e: except Exception as e:
print(e) print(e)
try:
try:
ds = dns.resolver.resolve(tld, 'DS')
except Exception as e:
# retry
print(e)
ds = dns.resolver.resolve(tld, 'DS')
for dsrecord in ds:
algo = dsrecord.to_text()
line = algo.split()
dnsseckeys.append(int(line[1]))
algo = max(list(dict.fromkeys(dnsseckeys)))
except Exception as e:
algo = 400
print(e)
results = {"tld": tld, "nsserveramount": int(len((nsservers))), "v4resolvers": Arecords, results = {"tld": tld, "nsserveramount": int(len((nsservers))), "v4resolvers": Arecords,
"v6resolvers": AAAArecords} "v6resolvers": AAAArecords, "algo": algo}
dbwriter(results) tlddbwriter(results)
def main(): def main():
try: try:
grabber(downloader()) zonefile = zonedownloader().splitlines(True)
if zonefile is not None:
# First delete the entire zone database if file polling is successful and re write
RootZone.objects.all().delete()
zonesorter(zonefile)
tlds = tlddownloader()
if tlds is not None:
grabber(tlds)
except Exception as e: except Exception as e:
print(e) print(e)