Module resty.dns.client
DNS client.
Works with OpenResty only. Requires the lua-resty-dns
module.
NOTES:
- parsing the config files upon initialization uses blocking i/o, so use with care. See init for details.
- All returned records are directly from the cache. So do not modify them! If you need to, copy them first.
- TTL for records is the TTL returned by the server at the time of fetching and won't be updated while the client serves the records from its cache.
- resolving IPv4 (A-type) and IPv6 (AAAA-type) addresses is explicitly supported. If the hostname to be resolved is a valid IP address, it will be cached with a ttl of 10 years. So the user doesn't have to check for ip adresses.
Info:
- Copyright: 2016-2017 Kong Inc.
- License: Apache 2.0
- Author: Thijs Schreijer
Resolving
init (options) | Initialize the client. |
resolve (qname, r_opts, dnsCacheOnly, try_list) | Resolve a name. |
toip (qname, port, dnsCacheOnly, try_list) | Resolves to an IP and port number. |
Socket functions
connect (sock, host, port, opts) | Implements tcp-connect method with dns resolution. |
setpeername (sock, host, port) | Implements udp-setpeername method with dns resolution. |
Resolving
The dnsCacheOnly
parameter found with resolve and toip can be used in
contexts where the co-socket api is unavailable. When the flag is set
only cached data is returned, but it will never use blocking io.
- init (options)
-
Initialize the client. Can be called multiple times. When called again it
will clear the cache.
Parameters:
- options Same table as the OpenResty dns resolver, with some extra fields explained in the example below.
Returns:
true
on success,nil+error
, or throw an error on bad inputUsage:
-- config files to parse --
hosts
andresolvConf
can both be a filename, or a table with file-contents -- The contents of thehosts
file will be inserted in the cache. -- Fromresolv.conf
thenameserver
,search
,ndots
,attempts
andtimeout
values will be used. local hosts = {} -- initialize without any blocking i/o local resolvConf = {} -- initialize without any blocking i/o -- when getting nameservers fromresolv.conf
, get ipv6 servers? local enable_ipv6 = false -- Order in which to try different dns record types when resolving -- 'last'; will try the last previously successful type for a hostname. local order = { "last", "SRV", "A", "AAAA", "CNAME" } -- Stale ttl for how long a stale record will be served from the cache -- while a background lookup is in progress. local staleTtl = 4.0 -- in seconds (can have fractions) -- Cache ttl for empty and 'name error' (3) responses local emptyTtl = 30.0 -- in seconds (can have fractions) -- Cache ttl for other error responses local badTtl = 1.0 -- in seconds (can have fractions) -- Overriding ttl for valid queries, if given local validTtl = nil -- in seconds (can have fractions) --ndots
, same as theresolv.conf
option, if not given it is taken from --resolv.conf
or otherwise set to 1 local ndots = 1 --no_random
, if set disables randomly picking the first nameserver, if not -- given it is taken fromresolv.conf
optionrotate
(inverted). -- Defaults totrue
. local no_random = true --search
, same as theresolv.conf
option, if not given it is taken from --resolv.conf
, or set to thedomain
option, or no search is performed local search = { "mydomain.com", "site.domain.org", } -- Disables synchronization between queries, resulting in each lookup for the -- same name being executed in it's own query to the nameservers. The default -- (false
) will synchronize multiple queries for the same name to a single -- query to the nameserver. noSynchronisation = false assert(client.init({ hosts = hosts, resolvConf = resolvConf, ndots = ndots, no_random = no_random, search = search, order = order, badTtl = badTtl, emptyTtl = emptTtl, staleTtl = staleTtl, validTtl = validTtl, enable_ipv6 = enable_ipv6, noSynchronisation = noSynchronisation, }) ) - resolve (qname, r_opts, dnsCacheOnly, try_list)
-
Resolve a name.
If
r_opts.qtype
is given, then it will fetch that specific type only. Ifr_opts.qtype
is not provided, then it will try to resolve the name using the record types, in the order as provided to init.Note that unless explictly requesting a CNAME record (by setting
r_opts.qtype
) this function will dereference the CNAME records.So requesting
my.domain.com
(assuming to be an AAAA record, and defaultorder
) will try to resolve it (the first time) as;- SRV,
- then A,
- then AAAA (success),
- then CNAME (after AAAA success, this will not be tried)
A second lookup will now try (assuming the cached entry expired);
- AAAA (as it was the last successful lookup),
- then SRV,
- then A,
- then CNAME.
The outer loop will be based on the
search
andndots
options. Within each of those, the inner loop will be the query/record type.Parameters:
- qname Name to resolve
- r_opts
Options table, see remark about the
qtype
field above and OpenResty docs for more options. - dnsCacheOnly Only check the cache, won't do server lookups
- try_list (optional) list of tries to add to
Returns:
list of records + nil + try_list
, ornil + err + try_list
. - toip (qname, port, dnsCacheOnly, try_list)
-
Resolves to an IP and port number.
Builds on top of resolve, but will also further dereference SRV type records.
When calling multiple times on cached records, it will apply load-balancing based on a round-robin (RR) scheme. For SRV records this will be a weighted round-robin (WRR) scheme (because of the weights it will be randomized). It will apply the round-robin schemes on each level individually.
Example;
SRV record for "my.domain.com", containing 2 entries (this is the 1st level);
target = 127.0.0.1, port = 80, weight = 10
target = "other.domain.com", port = 8080, weight = 5
A record for "other.domain.com", containing 2 entries (this is the 2nd level);
ip = 127.0.0.2
ip = 127.0.0.3
Now calling
local ip, port = toip("my.domain.com", 123)
in a row 6 times will result in;127.0.0.1, 80
127.0.0.2, 8080
(port from SRV, 1st IP from A record)127.0.0.1, 80
(completes WRR 1st level, 1st run)127.0.0.3, 8080
(port from SRV, 2nd IP from A record, completes RR 2nd level)127.0.0.1, 80
127.0.0.1, 80
(completes WRR 1st level, 2nd run, with different order as WRR is randomized)
Debugging:
This function both takes and returns a
try_list
. This is an internal object representing the entire resolution history for a call. To prevent unnecessary string concatenations on a hot code path, it is not logged in this module. If you need to log it, just logtostring(try_list)
from the caller code.Parameters:
- qname hostname to resolve
- port
(optional) default port number to return if none was found in
the lookup chain (only SRV records carry port information, SRV with
port=0
will be ignored) - dnsCacheOnly Only check the cache, won't do server lookups (will not invalidate any ttl expired data and will hence possibly return expired data)
- try_list (optional) list of tries to add to
Returns:
ip address + port + try_list
, or in case of an errornil + error + try_list
Socket functions
- connect (sock, host, port, opts)
-
Implements tcp-connect method with dns resolution.
This builds on top of toip. If the name resolves to an SRV record,
the port returned by the DNS server will override the one provided.
NOTE: can also be used for other connect methods, eg. http/redis clients, as long as the argument order is the same
Parameters:
- sock the tcp socket
- host hostname to connect to
- port port to connect to (will be overridden if toip returns a port)
- opts the options table
Returns:
success
, ornil + error
- setpeername (sock, host, port)
-
Implements udp-setpeername method with dns resolution.
This builds on top of toip. If the name resolves to an SRV record,
the port returned by the DNS server will override the one provided.
Parameters:
- sock the udp socket
- host hostname to connect to
- port port to connect to (will be overridden if toip returns a port)
Returns:
success
, ornil + error