# Reverse Zone Compiler (rzc) This is a tool to automate the process of maintaining reverse DNS zones given a collection of forward zones. Primary use case is a small operation that runs a few POPs full of VMs for researchers, friends, and various public benefit projects: keeping track of the DNS names of all of one's tenents in this case is a pain, and the desired data is already present in the forward zones, so an automatic tool to construct the reverse zone(s) may help. Basic model is to configure this tool as a DNS XFR client for all the relevant forward zones, and to specify the reverse zones to be generated. The tool then downloads all of the specified forward zones, trawls them for A and AAAA RRs, and translates those into PTR RRs, throwing away any PTR RRs that don't fall within the specified set of reverse zones. After exhausting this process, the tool writes out a set of reverse zone files and exits. The tool caches local copies of the downloaded forward zones, both to allow it to ride out temporary transfer failures and to allow it to use IXFR rather than AXFR to save bandwidth when conditions permit. All of the heavy lifting is done by Bob Halley's excellent `dnspython` library. You will also need the TOML library. apt install python3-toml python3-dnspython All configuration is stored in a TOML file. The default name of the TOML file is the same as the tool, with the `.py` suffix changed to `.toml`, but one can override this by passing the name of the configuration file via the `RZC_CONFIG` environment variable or on the command line. Sample configuration file: [output] directory = "output" ttl = 3600 soa.mname = "localhost" soa.rname = "ns0.example.org" soa.refresh = 10803 soa.retry = 900 soa.expire = 604800 soa.minimum = 600 ns = [ "ns1.example.org", "ns2.example.org", ] zones = [ "1.0.10.in-addr.arpa", "2.0.10.in-addr.arpa", "3.0.10.in-addr.arpa", "1.0.a.2.0.0.2.ip6.arpa", "2.0.a.2.0.0.2.ip6.arpa", "3.0.a.2.0.0.2.ip6.arpa", ] [input] xfr_timeout = 300 cache = "cache" [[input.zone]] name = "fred.example" server = "10.100.0.1" tsig = { "tsig.example.org" = ["hmac-sha256", "36A2xRALPymYl3Q7axrtAk1AICJyPhu2KkK7PxJhTQ8=" ] } [[input.zone]] name = "barney.example" server = "10.200.0.1" Most of this should be self-explanatory. The configuration is divided into two sections, `input` and `output`: `input` is about fetching the forward zones, `output` is about generating the reverse zones. `input.cache` is where cached copies of the forward zones will be stored. `output.directory` is where the reverse zones files will be written. Both directories will be created if needed. `output.ns` is the list of nameservers to be listed in `NS` RRs in the output zones. Similarly, `output.soa` gives all the parameters needed for the `SOA` rdata, except for the `serial` value, which will be generated automatically using the seconds-since-epoch convention. `output.zones` is the list of reverse zones to be generated. Each `[[input.zone]]` block defines one forward zone to be retrieved. `name` is the name of the zone, `server` is the IPv4 or IPv6 address from which to retrieve the zone. `tsig`, if given, specifies the `TSIG` key data to use when retrieving this zone: the syntax is a little weird, because it's a direct TOML representation of the form `dnspython` uses for a single-entry TSIG keyring, the general form is tsig = { "name.of.tsig.key" = [ "tsig-key-type", "tsig-secret-encoded-as-base64" ] } Since the TSIG secrets are embedded directly in the TOML file, you might want to `chmod` the TOML file to restrict unauthorized readers. At some point I might add validation of the TOML via via `jsonschema`, but the schema required would nearly double the size of the program.