211 lines
7.9 KiB
Python
Executable file
211 lines
7.9 KiB
Python
Executable file
#!/usr/bin/env python3
|
|
|
|
import dns
|
|
|
|
from dns import 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) -> dns.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 = dns.name.Name((local, *dns.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, dns.name.from_text(address)),
|
|
)
|
|
|
|
|
|
class MailExchangeRecord(Record):
|
|
def __init__(self, name: str, priority: int, exchange: str):
|
|
super().__init__(
|
|
name,
|
|
MX.MX(rdataclass.IN, rdatatype.MX, priority, dns.name.from_text(exchange)),
|
|
)
|
|
|
|
|
|
class NameServerRecord(Record):
|
|
def __init__(self, name: str, address: str):
|
|
super().__init__(
|
|
name, NS.NS(rdataclass.IN, rdatatype.NS, dns.name.from_text(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,
|
|
dns.name.from_text(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())
|