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.
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.
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
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.
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.