From 9ab7ac48141d1e9f054871889bbb0a88ca96ec94 Mon Sep 17 00:00:00 2001 From: Vincent Lafeychine Date: Wed, 22 Dec 2021 00:58:24 +0100 Subject: [PATCH] Initial commit: Working static example of dns.auro.re.zone --- main.py | 201 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 201 insertions(+) create mode 100755 main.py diff --git a/main.py b/main.py new file mode 100755 index 0000000..47f0145 --- /dev/null +++ b/main.py @@ -0,0 +1,201 @@ +#!/usr/bin/env python3 + +from dns import name, rdata, rdataclass, rdatatype +from dns.zone import Zone +from dns.rdtypes.ANY import CNAME, MX, NS, SOA, TXT +from dns.rdtypes.IN import A, AAAA + + +SOA_SERIAL_TIME = 31695 +SOA_REFRESH_TIME = 8640 +SOA_RETRY_TIME = 7200 +SOA_EXPIRE_TIME = 3600000 +SOA_TIME_TO_LIVE = 10800 + + +def format_rname(mail: str) -> name.Name: + """ + Given an email address in the standard string format `mail@example.tld` + return an email address in the format required by RFC 1035 + `mail.example.tld.` + + Be careful when using this function. It is a very simple email parsing + function and does support the wide range of possible emails format. It also + does not check is email is valid and does not escape caracters. + + Return a `dns.name.Name` object. + """ + + local, domain = mail.split("@") + rname = name.Name((local, *name.from_text(domain))) + + return rname + + +class Record: + def __init__(self, name: str, dns_rdata: rdata.Rdata): + self.name = name + self.dns_rdata = dns_rdata + self.dataclass = dns_rdata.rdclass + self.datatype = dns_rdata.rdtype + + +class IPv4Record(Record): + def __init__(self, name: str, address: str): + super().__init__(name, A.A(rdataclass.IN, rdatatype.A, address)) + + +class IPv6Record(Record): + def __init__(self, name: str, address: str): + super().__init__(name, AAAA.AAAA(rdataclass.IN, rdatatype.AAAA, address)) + + +class CanonicalNameRecord(Record): + def __init__(self, name: str, address: str): + super().__init__(name, CNAME.CNAME(rdataclass.IN, rdatatype.CNAME, address)) + + +class MailExchangeRecord(Record): + def __init__(self, name: str, priority: int, exchange: str): + super().__init__(name, MX.MX(rdataclass.IN, rdatatype.MX, priority, exchange)) + + +class NameServerRecord(Record): + def __init__(self, name: str, address: str): + super().__init__(name, NS.NS(rdataclass.IN, rdatatype.NS, address)) + + +class TextRecord(Record): + def __init__(self, name: str, data: str): + super().__init__(name, TXT.TXT(rdataclass.IN, rdatatype.TXT, data)) + + +class StartOfAuthorityRecord(Record): + def __init__( + self, + name: str, + address: str, + rname: str, + serial=SOA_SERIAL_TIME, + refresh=SOA_REFRESH_TIME, + retry=SOA_RETRY_TIME, + expire=SOA_EXPIRE_TIME, + ttl=SOA_TIME_TO_LIVE, + ): + super().__init__( + name, + SOA.SOA( + rdataclass.IN, + rdatatype.SOA, + address, + format_rname(rname), + serial, + refresh, + retry, + expire, + ttl, + ), + ) + + +def main() -> int: + # Sample from "dns.auro.re.zone" file + origin = "auro.re." + records = [ + CanonicalNameRecord("auth", "proxy-ovh.auro.re."), + CanonicalNameRecord("belenios", "proxy-ovh.auro.re."), + CanonicalNameRecord("cas", "proxy-ovh.auro.re."), + CanonicalNameRecord("chat", "proxy-ovh.auro.re."), + CanonicalNameRecord("codimd", "proxy-ovh.auro.re."), + CanonicalNameRecord("dns-main", "serge.auro.re."), + CanonicalNameRecord("dns-secondary", "lama.auro.re."), + CanonicalNameRecord("drone", "proxy.auro.re."), + CanonicalNameRecord("element", "proxy-ovh.auro.re."), + CanonicalNameRecord("etherpad", "proxy-ovh.auro.re."), + CanonicalNameRecord("gitea", "proxy.auro.re."), + CanonicalNameRecord("grafana", "proxy.auro.re."), + CanonicalNameRecord("hedgedoc", "proxy-ovh.auro.re."), + CanonicalNameRecord("imap", "mail.auro.re."), + CanonicalNameRecord("intranet", "proxy.auro.re."), + CanonicalNameRecord("jitsi", "jitsi-aurore.auro.re."), + CanonicalNameRecord("kanboard", "proxy-ovh.auro.re."), + CanonicalNameRecord("litl", "proxy.auro.re."), + CanonicalNameRecord("netbox", "proxy.auro.re."), + CanonicalNameRecord("nextcloud", "proxy.auro.re."), + CanonicalNameRecord("pad", "proxy-ovh.auro.re."), + CanonicalNameRecord("passbolt", "proxy-ovh.auro.re."), + CanonicalNameRecord("paste", "proxy-ovh.auro.re."), + CanonicalNameRecord("phabricator", "proxy-ovh.auro.re."), + CanonicalNameRecord("portail-edc", "portail.accueil.edc.auro.re."), + CanonicalNameRecord("portail-fleming", "portail.accueil.fleming.auro.re."), + CanonicalNameRecord("portail-gs", "portail.accueil.sand.auro.re."), + CanonicalNameRecord("portail-pacaterie", "portail.accueil.pacaterie.auro.re."), + CanonicalNameRecord("portail-rives", "portail.accueil.rives.auro.re."), + CanonicalNameRecord("privatebin", "proxy-ovh.auro.re."), + CanonicalNameRecord("radius", "radius-aurore.auro.re."), + CanonicalNameRecord("re2o", "proxy.auro.re."), + CanonicalNameRecord("re2o-server", "proxy.auro.re."), + CanonicalNameRecord("re2o-test", "proxy.auro.re."), + CanonicalNameRecord("riot", "proxy-ovh.auro.re."), + CanonicalNameRecord("rss", "proxy-ovh.auro.re."), + CanonicalNameRecord("sharelatex", "proxy-ovh.auro.re."), + CanonicalNameRecord("smtp", "mail.auro.re."), + CanonicalNameRecord("status", "proxy-ovh.auro.re."), + CanonicalNameRecord("virtu", "horus.auro.re."), + CanonicalNameRecord("vote", "proxy.auro.re."), + CanonicalNameRecord("wiki", "proxy.auro.re."), + CanonicalNameRecord("wikijs", "proxy.auro.re."), + CanonicalNameRecord("www", "proxy-ovh.auro.re."), + CanonicalNameRecord("zero", "proxy-ovh.auro.re."), + IPv4Record("@", "92.222.211.195"), + IPv4Record("camelot", "45.66.111.59"), + IPv4Record("dns-aurore", "45.66.111.253"), + IPv4Record("galene", "45.66.111.65"), + IPv4Record("horus", "94.23.218.136"), + IPv4Record("jitsi-aurore", "45.66.111.55"), + IPv4Record("lama", "185.230.78.238"), + IPv4Record("mail", "45.66.111.62"), + IPv4Record("passerelle", "45.66.111.254"), + IPv4Record("proxy", "45.66.111.61"), + IPv4Record("proxy-ovh", "92.222.211.195"), + IPv4Record("radius-aurore", "45.66.111.251"), + IPv4Record("router-infra", "45.66.111.10"), + IPv4Record("routeur-aurore", "45.66.111.240"), + IPv4Record("routeur-aurore-backup", "45.66.111.140"), + IPv4Record("routeur-ovh", "92.222.211.198"), + IPv4Record("serge", "92.222.211.196"), + IPv4Record("vpn-ovh", "92.222.211.197"), + IPv6Record("camelot", "2a09:6840:111::59"), + IPv6Record("dns-aurore", "2a09:6840:111::253"), + IPv6Record("galene", "2a09:6840:111:0:1ccb:e1ff:feab:5d88"), + IPv6Record("jitsi-aurore", "2a09:6840:111::55"), + IPv6Record("lama", "2a0c:700:12:0:42:55ff:fe46:5ac5"), + IPv6Record("mail", "2a09:6840:111::62"), + IPv6Record("passerelle", "2a09:6840:111::254"), + IPv6Record("proxy", "2a09:6840:111::61"), + IPv6Record("radius-aurore", "2a09:6840:111::251"), + IPv6Record("router-infra", "2a09:6841:111:0:10::"), + IPv6Record("routeur-aurore", "2a09:6840:111::240"), + IPv6Record("routeur-aurore-backup", "2a09:6840:111::140"), + MailExchangeRecord("@", 5, "mail.auro.re."), + MailExchangeRecord("@", 10, "proxy-ovh.auro.re."), + NameServerRecord("@", "lama.auro.re."), + NameServerRecord("@", "serge.auro.re."), + StartOfAuthorityRecord("auro.re.", "serge.auro.re", "mail@fede-aurore.net"), + TextRecord("@", "v=spf1 mx ~all"), + ] + + zone = Zone(origin) + + for record in records: + node = zone.get_node(record.name, create=True) + dataset = node.get_rdataset(record.dataclass, record.datatype, create=True) + dataset.add(record.dns_rdata) + + print(zone.to_text(relativize=False)) + + return 0 + + +if __name__ == "__main__": + exit(main())