Rednet DNS API (Rewrite & expansion of Mitchfizz05's DNS System) [defunct]

Started by cynagen, Aug 19, 2018, 09:39 pm

Previous topic - Next topic

cynagen

Aug 19, 2018, 09:39 pm Last Edit: Sep 27, 2018, 04:41 am by cynagen Reason: [defunct]
Original post here.

Hello! This is my overnight rewrite of Mitchfizz05's DNS System. His work from so long ago was inspiration, I cleaned up what I could use, rewrote a lot, and made it much more 1.6+ friendly. This implementation is now also rednet 'repeat' friendly, allowing repeaters to carry DNS messages across the network from farther away, or bridge DNS from multiple network segments through repeaters. The 'dnsserver' script is intended to run side-by-side with 'repeat', so an Advanced Computer with Multishell available is highly recommended. The 'dnsserver' script can be run on a standalone computer if you don't want to mix 'repeat' and 'dnsserver' functionality on a single host.

Install
I personally prefer to automatically load APIs like this one at boot. Though a simple os.loadAPI() call will work just fine!

Usage
Code Select
API Usage
os.loadAPI("dns") --DNS API required
os.loadAPI("dnshook") --DNS RedNet hook library recommended (Mitchfizz05's original code, no changes here)
dns.scan() -- Scans for DNS servers on the network. Returns the ID of the first DNS server, if found. If none found, returns nil.
dns.lookup("hostname") -- Resolves the hostname to an ID (if possible, returns nil otherwise)
dns.publish() -- Publishes the computer to the DNS servers on the network (returns true if successful, false otherwise)
dns.unpublish() -- Unpublishes the computer from the DNS servers on the network (returns true if successful, false otherwise)

Server Usage
Configure static hostname mappings using the file data/hosts, same format as Mitchfizz05, hostname:# once per line.
NOTE: Configuring a static mapping on a DNS server will automatically make the server "authoritative" of that hostname. This record cannot be removed with dns.unpublish().
The server has 2 additional options in the head of the script itself, they are as follows:
allowZoneTransfers; Default: false, directs the server whether or not to honor Zone Transfer requests
onlyAuthZone; Default: true, directs the server whether to only share records it loaded itself and is authoritative of, or all current records

Launch however you choose, on-demand, as the startup script, or part of an automated startup script. Display will provide count and list of known hosts. If the hosts list becomes too long, it -will- overflow, known bug. I am looking at ways to address this and welcome feedback.

Example:
Code Select
lua> os.loadAPI("dns")
true
lua> os.setComputerLabel("cynagen")
lua> dns.lookup("cynagen")
lua> dns.publish()
true
lua> dns.lookup("cynagen")
3
lua> dns.unpublish()
true
lua> dns.lookup("cynagen")

Downloads
New DNS API: pastebin get QEYJTFHi dns
New DNS Server: pastebin get fzWmtMLn dnsserver
Old DNS Hook: pastebin get DWyLsEFc dnshook (all code original Mitchfizz05)

Notes
  • This implementation of the DNS API now uses rednet API to streamline the flow of the code and data through the network through usage of rednet.broadcast and the like. I found it quite janky to be using an event handler to capture the data in the original implementation. Additionally, this script is meant for CC 1.6+ because of the usage of protocol naming to help keep this API focused and ignoring other calls on the network.
  • Currently this script uses the protocol name "dns" as the default, though if you wish to, you can alter this name in the relevant places in both 'dns' and 'dnsserver' to whatever you wish.
  • dns.publish() currently can only publish the computer's label, though I may add support to publish user-defined strings in the future. Additionally, you cannot publish your computer to the DNS servers without first setting a computer label
  • dns.scan() returns only the FIRST server to respond (likely to be the closest device on the network)
  • dns.lookup() will wait for as many DNS servers to respond as possible before returning a result to increase your chances of receiving a valid result. WARNING: If your computer can reach multiple dns servers via 'repeat' or local (>3) this can significantly delay the return. However, if the DNS lookup gets a result from a server which reports authenticity/ownership (flag in the hosts table set to true), it will immediately return that result instead as authentic, ignoring all other responses. Otherwise, dns.lookup() will return the last ID transmitted to it, this seriously needs more work and will be cleaned up later

Use Case Scenarios
In a simple network with no repeaters, simply add a computer, provide hosts in 'data/hosts' if you have any to declare, then launch 'dnsserver'. This will get you started with a basic copy of the DNS server, it will respond to and monitor DNS record queries, removals, and creations. It will NOT share any of it's host tables with any other systems in bulk.

If you're running a larger network where you may have one or more repeaters a single DNS server placed may not reach all other systems easily, or you may want to have a "cache" someplace else on the network for backup purposes if the primary DNS server crashes or is disconnected for any reason. Install 2 or more computers on the network where it will still receive DNS messages from one another (either directly or via 'repeat'), designate one as "primary" for sanity purposes, this is the one you'll end up putting your static hostnames on. On your primary system, add static hostnames as usual, then proceed to 'edit dnsserver' and change allowZoneTransfers to true, leave onlyAuthZone as false. This system will now function as a "root" DNS server for static entries. As other DNS servers launch on the network and discover one another, they will share zone information where configured and automatically populate records across the network. This server will additionally function normally as any other DNS server, responding to queries, and will keep track of dynamic records as well. For secondary DNS servers, it is recommended that you leave 'data/hosts' off the system entirely, and instead 'edit dnsserver' and set allowZoneTransfers to true, and onlyAuthZone to false, to allow them to share all records discovered, while not being an authority on any records itself, just a cache.

If you're running an even larger network with a number of smaller subnets attached to it, you may have multiple "root" authoritative servers, they may even have the same hostname listed in 'data/hosts', and may have another computer ID provided (intentionally or not!). Whichever "root" server responds first will be declared the "authority" on the record and the dns.lookup will resolve to the ID provided. This has a number of benefits when your smaller subnets are linked into the larger network via 'repeat'. There is inherent delay in 'repeat', which buys a DNS server on the local cable time to respond before your request is repeated out and responded to by another system, effectively giving that smaller "LAN" it's own local authority to specify static hostnames, while for unknown records, deferring to the public records. For these smaller subnet's DNS servers, I'd recommend allowZoneTransfers:true and onlyAuthZone:false, this way they can act as auth on their own hostnames to the world, but also contribute to the distributed name pool by sharing records previously shared with them. (This is called "DNS Tiering" and "DNS Caching" respectively.)

Thank you for reading, I look forward to feedback from users! Coming soon, demonstration video of DNS API & Server in action, as well as a deeper explanation on DNS Tiering and how it's intended to function.

cynagen

I will be rewriting this to function with the internal RedNet DNS system here soon, abandoning this third-party implementation. Additionally, I plan on building a small tool suite to harness the expanded functionality.