ascension

Migrate DNS zones to the GNU Name System
Log | Files | Refs | README | LICENSE

commit a237ad931d72d2a154f522e2aed9cce359aca67c
parent 28d96ccb827ac45c4e482edecef6c3e33d29fb48
Author: Martin Schanzenbach <schanzen@gnunet.org>
Date:   Sun, 30 Jun 2024 22:40:46 +0200

add alternative import path for broken AXFR servers

Diffstat:
Mascension/ascension.py | 13+++++++------
Mascension/util/argumentparser.py | 3+++
Mascension/util/classes.py | 18+++++++++++-------
Mascension/util/rest.py | 2+-
4 files changed, 22 insertions(+), 14 deletions(-)

diff --git a/ascension/ascension.py b/ascension/ascension.py @@ -255,7 +255,7 @@ class Ascension(): """ data = ascension.util.classes.GNSRecordData( value=pkey, - record_type='PKEY', + record_type='EDKEY', relative_expiration=ttl, is_relative_expiration=True, is_private=not self.gnszone.public @@ -330,7 +330,7 @@ class Ascension(): continue if num_gnspkeys > 1: self.logger.critical( - "Detected ambiguous PKEY records for label %s (not generating PKEY record)", + "Detected ambiguous EDKEY records for label %s (not generating EDKEY record)", name ) continue @@ -348,7 +348,7 @@ class Ascension(): pkey_ttl = self.subzonedict[zone] pkey2, ttl = pkey_ttl if pkey2 != gnspkey: - self.logger.critical("PKEY in DNS does not match PKEY in GNS for name %s", name) + self.logger.critical("EDKEY in DNS does not match EDKEY in GNS for name %s", name) continue # Create missing zones (and add to dict) for GNS zones that are NOT DNS @@ -381,7 +381,7 @@ class Ascension(): self.subzonedict[zonename] = (pkey, ttl) self.ns_process = subprocess.Popen(["gnunet-namestore", "-a", "-S"], stdin=subprocess.PIPE, text=True) - # Generate PKEY records for all entries in subzonedict + # Generate EDKEY records for all entries in subzonedict for zone, pkeyttltuple in self.subzonedict.items(): pkey, ttl = pkeyttltuple # Allow for any amount of subzones @@ -464,10 +464,11 @@ def main(): if not ascender.dnszone.zone or needsupdate: # Zonebackups are needed for retaining information for IXFR and # offer a zone for dnspython to patch - gns_zone_serial = ascender.dnszone.restore_from_file(gns_zone_serial) + gns_zone_serial = ascender.dnszone.restore_from_file(gns_zone_serial, zonefile=args.zonefile) ascender.logger.info("Zone serial for DNS zone transfer used: `%s'", gns_zone_serial) # Transfer the actual zone - ascender.dnszone.transfer_zone(gns_zone_serial) + if None == args.zonefile: + ascender.dnszone.transfer_zone(gns_zone_serial) needsupdate = False soa = ascender.dnszone.get_zone_soa() diff --git a/ascension/util/argumentparser.py b/ascension/util/argumentparser.py @@ -38,6 +38,9 @@ def parse_arguments() -> argparse.Namespace: help='Port to use for zone transfer with nameserver', required=False, default=53) + parser.add_argument('-Z', '--zonefile', + help='Zonefile to use for initial bootstrap', + required=False) parser.add_argument('-k', '--keyfile', help='Keyfile to use for DNS TSIG', required=False, diff --git a/ascension/util/classes.py b/ascension/util/classes.py @@ -86,7 +86,7 @@ class GNSZone(): """ Creates the zone in gnunet """ - data = json.dumps(dict({"name": self.domain})) + data = json.dumps(dict({"name": self.domain, "type": "EDDSA"})) response = self.gnunet_rest.post("/identity", data=data) if response.status_code == 409: @@ -129,7 +129,7 @@ class GNSZone(): :returns: str of pubkey of created or existing GNUnet zone """ # This is needed including the argument for subzones - data = json.dumps(dict({"name": zonename})) + data = json.dumps(dict({"name": zonename, "type": "EDDSA"})) response = self.gnunet_rest.post("/identity", data=data) if response.status_code == 409: @@ -194,8 +194,9 @@ class DNSZone: self, query=zonegenerator, port=self.resolver.port, - timeout=5, - lifetime=5) + timeout=60, + udp_mode=dns.UDPMode.TRY_FIRST, + lifetime=600) except dns.resolver.NoAnswer: self.logger.critical("Nameserver for '%s' did not answer.", domain) return None @@ -233,14 +234,18 @@ class DNSZone: return 0 - def restore_from_file(self, serial: int) -> int: + def restore_from_file(self, serial: int, zonefile: None) -> int: """ Loads a zonebackup previously created to enable incremental zone transfers :param serial: Serial of the zone according to GNS :returns: Serial of the restored zone or 0 if loading failed """ try: - self.zone = dns.zone.from_file(self.zone_backup_file, origin=self.domain) + if zonefile: + zf = zonefile + else: + zf = self.zone_backup_file + self.zone = dns.zone.from_file(zf, origin=self.domain) self.logger.info("Zonebackup file %s loaded", self.zone_backup_file) except FileNotFoundError: self.logger.info("Zonebackup file was not found, will be created") @@ -277,7 +282,6 @@ class DNSZone: query=zonegenerator, port=self.resolver.port) - def get_zone_soa(self) -> dns.rdatatype.SOA: """ Fetches soa record from zone a given dnspython zone diff --git a/ascension/util/rest.py b/ascension/util/rest.py @@ -70,7 +70,7 @@ class GNUnetRestSession: self.retries = requests.adapters.Retry( total=5, backoff_factor=1, - method_whitelist=["GET", "POST", "PUT"] + allowed_methods=["GET", "POST", "PUT"] ) self.session.mount( f"{self.base_url}", requests.adapters.HTTPAdapter(max_retries=self.retries)