Skip to content

Instantly share code, notes, and snippets.

@ahupowerdns
Last active July 18, 2024 17:53
Show Gist options
  • Save ahupowerdns/1e8bfbba95a277a4fac09cb3654eb2ac to your computer and use it in GitHub Desktop.
Save ahupowerdns/1e8bfbba95a277a4fac09cb3654eb2ac to your computer and use it in GitHub Desktop.
The LUA record type for Lua-powered DNS records

LUA Record Type for Lua-powered DNS records for standards based fail-over and geographical load balancing

GitHub branch -> https://github.com/ahupowerdns/pdns/tree/luarec

Recently, many zone owners could not migrate away from Dyn since they were benefiting from non-standardised DNS-based failover and geographical loadbalancing features. What you see below is an attempt to get standards based but flexible equivalents of these currently proprietary features. Here is a zone:

$TTL 60
lua.br. IN      SOA     a.lua.br. nstld.verisign-grs.com. (
        2016032300      ; Serial
        14400           ; Refresh
        7200            ; Retry
        1209600         ; Expiry
        3600000 )       ; Minimum

; NS Set follows

lua.br. IN      NS      a.lua.br.
        IN      LUA     A       "return '1.2.3.4'"
        IN      LUA     AAAA    "return '::1'"
        IN      LUA     MX      "return '25 a.lua.br'"
whoami  IN      LUA     TXT     "return who"
time    IN      LUA     TXT     "return os.date('%c')"
www     IN      LUA     A       "return pickRandom({'1.2.3.4', '4.5.6.7', '8.9.10.11'})"
www2    IN      LUA     A       "return wrandom({ {100, '1.2.3.4'}, {50, '5.4.3.2'}, {1, '192.168.1.0'}})"
www3    IN      LUA     A       "return ifportup(443, {'52.48.64.3', '1.2.3.4'})"
                LUA     AAAA    "return ifportup(443, {'2001:888:2000:1d::2', '2001:db8::2:1'})"

www4    IN      LUA     A       (
                                 " return ifurlup('http://www4.lua.org/status',          " 
                                 " {'148.251.24.173','52.48.64.3'},                      "
                                 " {stringmatch='UP', follow='true', interval='10s'})    "
                                )
     
a.lua.br.       IN      A       198.41.0.4

Note how LUA records have an internal type, much like RRSIG records.

Only on the authoritative server

LUA records function a lot like wildcard records in that they synthesise new records. LUA records also can't be queried directly, but do appear in zone transfers, so they can be slaved.

Resolvers never see LUA records, much like they don't usually see wildcard records. They only see the synthesised results.

This means that LUA records work with all resolvers and only need support on the authoritative side.

Examples from the zone

When a query comes in for the TXT record of time.lua.br, the authoritative server executes the code on line 19 and returns the current time. Similarly, whoami.lua.br returns the IP address of the resolver talking to the authoritative server.

www.lua.br gets a random IP address on line 20, www2 a weighted random IP address. Finally and most powerfully, for www3.lua.b3, IPv4 and IPv6 records are returned only if they are listening on port 443.

This is what the debug log looks like for a query for AAAA of www3.lua.br:

Code: "return ifportup(443, {'2001:888:2000:1d::2', '2001:db8::2:1'})"
First ever query for [2001:888:2000:1d::2]:443, launching checker
First ever query for [2001:db8::2:1]:443, launching checker
Have 0 candidate IP addresses: 
Picking a random one, everything is down. Should return all of them
Declaring [2001:888:2000:1d::2]:443 UP!

And on the second query:

Code: "return ifportup(443, {'2001:888:2000:1d::2', '2001:db8::2:1'})"
Have 1 candidate IP addresses: 2001:888:2000:1d::2 

Which is duely returned:

$ dig -t aaaa www3.lua.br @192.168.1.54 -p 5301 
;; QUESTION SECTION:
;www3.lua.br.			IN	AAAA

;; ANSWER SECTION:
www3.lua.br.		60	IN	AAAA	2001:888:2000:1d::2

;; Query time: 0 msec

More features

For host 'www4', the full syntax of ifurlup() is employed, and this record also spans multiple zone lines. For www4, a specific URL is retrieved from each IP address, and the host is only considered up if that URL contains the word 'UP'. In addition, we are willing to follow 3xx redirects, and will check again every 10 seconds.

@muslu
Copy link

muslu commented Nov 11, 2022

Hi;

How can i get IP records from database?

For example:

www IN LUA A "return ifportup(443, {'5.6.7.8', '1.2.3.4'})"

I want to get 5.6.7.8 and 1.2.3.4 from DB.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment