Provided by: gdnsd_2.4.2-1_amd64 

NAME
gdnsd.config - gdnsd configuration file
SYNOPSIS
options => {
log_stats => 86400
tcp_timeout => 15 ; zonefile-style comment
include_optional_ns => true
listen => [ 127.0.0.1, 192.0.2.1 ]
}
# shell-style comment
service_types => {
foosvc => { plugin => http_status, vhost => www.example.com, url_path => "/checkme" }
barsvc => $include{bar-svc.cfg}
$include{other-services.cfg}
}
plugins => {
null => {}
}
DESCRIPTION
This man page describes the syntax of the primary gdnsd configuration file. The primary config file is
always the the file named config in the configuration directory. The default configuration directory is
/etc/gdnsd, but this can be overridden by the "-c" commandline option.
The lower-level syntax and structure of the configuration language is described in detail at the end of
this document, but it should be fairly intuitive from the example above. It is effectively a generic
data structure language allowing arbitrarily-nested ordered hashes, ordered arrays, and scalar values.
Double-quotes are used to quote scalars containing whitespace or various ambiguous metacharacters.
The top-level implicit hash of a gdnsd configuration file allows only 3 legal keys: options,
service_types, and plugins.
Any of them which are present must have a Hash as their value.
All of them are optional, as is the configuration file itself. If you're happy with an all-default
configuration, you can simply not have a config file at all.
OPTIONS HASH
These options control the overall behavior of gdnsd(8).
username
String, defaults to "gdnsd". This is the username the daemon drops privileges to the uid/gid of on
startup if started as root.
weaker_security
Boolean, default false. When false, the daemon may take additional privilege-preventing measures
beyond the basic drop of the uid/gid of the process. These may be platform specific and evolve over
time, and may impose limits that break some users' configurations in corner cases.
This option exists as an escape hatch to get things working again, but the name of the option is
intended to pressure you to find another way to accomplish your goal without requiring reduced
security.
At this time, the only security feature this controls is setting the Linux-specific "prctl()" flag
"PR_SET_NO_NEW_PRIVS" on kernels 3.5 and higher. When this is set, it immutably prevents the process
and all descendants from ever gaining new privileges again. This is done regardless of whether the
daemon initially started as root and voluntarily dropped its own privileges or was started as a
regular user.
Note that "PR_SET_NO_NEW_PRIVS" could break plugin_extmon configurations which execute binaries that
need escalated privileges via set[ug]id bits and/or capabilities bits. A classic example of such a
binary is "ping".
zones_default_ttl
Integer seconds, default 86400. This is the global default time-to-live for any record in any
zonefile. It can be overridden with a more specific default within zone files themselves via the
$TTL directive (see gdnsd.zonefile(5)).
max_ttl
Integer seconds, default 3600000 (~42 days), range 3600 - 268435455 (2^28-1, ~8.5 years). This is
the global maximum TTL. Any TTL found in a zone which exceeds this value will be clamped to this
value with a warning. Note that the default maximum value is what the Internet's root nameservers
currently use for A-record TTLs, and those are arguably the most stable records in the whole system.
It's hard to imagine good reasons to raise this value in practice.
min_ttl
Integer seconds, default 5, range 1 - 86400 (1 day). This is the global minimum TTL. Any TTL found
in a zone which is below this value will be clamped to this value with a warning, including the
minimum TTLs of DYN[AC] records and SOA ncache TTLs. This value must be less than or equal to
max_ttl.
max_ncache_ttl
Integer seconds, default 10800, range 10 - 86400. This is the global maximum for the SOA negative-
cache TTL field. Values above this will be clamped with a warning. This value must be greater than
or equal to min_ttl.
dns_port
Integer port, 1-65535, default 53. This is the global default port number for DNS listener addresses
which do not specify port numbers themselves.
http_port
Integer port, 1-65535, default 3506. This is the default HTTP port number for stats listener
addresses which do not specify port numbers themselves.
listen
The listen option specifies the socket addresses the server listens on for DNS requests.
A listen-address specification is an IP (v4 or v6) address specified as a numeric string with
standard formatting (anything numeric that "getaddrinfo()" supports on your platform), optionally
followed by a colon and a port number. If no port number is specified, it defaults to the value from
"dns_port", which defaults to 53.
Due to various parsing ambiguities, if you wish to specify a non-default port number for an IPv6
listen address, you will have to enclose the address part in square brackets, and then enclose the
entire string in double-quotes.
The structure of the listen option as a whole can take one of three basic forms. In its simplest
form, it is just a single listen-address specification as a string, such as:
options => { listen = 192.0.2.1 }
It can also take the form of an array of such addresses, as in:
options => {
listen = [
192.0.2.1,
192.0.2.2,
2001:DB8::1,
"[2001:DB8::1234]:5353",
]
}
It can also be a hash where the keys are listen addresses, and the values are per-address options, as
in:
options => {
listen => {
192.0.2.1 => {
tcp_timeout = 7
},
192.0.2.2:5353 => {
udp_threads = 5
},
}
}
The per-address options (which are identical to, and locally override, the global option of the same
name) are "tcp_threads", "tcp_timeout", "tcp_clients_per_thread", "udp_threads", "udp_recv_width",
"udp_rcvbuf", and "udp_sndbuf".
Finally, it can also be set to the special string value "any", as in:
options => { listen => any }
This is the default mode if no explicit "listen" option is provided. In this mode, the daemon will
listen on the "dns_port" port (default 53) on the IPv4 and IPv6 "ANY" addresses 0.0.0.0 and "::".
gdnsd's "ANY"-address sockets should correctly handle sending outgoing datagrams via the interface
they were received on with a source address matching the destination address of the request.
http_listen
Basically like listen above, but used for the HTTP listener (serving stats information), and
defaulting to port 3506. The hash form isn't supported as there are no per-address options, and the
any/all options don't exist here. The default is to listen on the IPv4 and IPv6 any-addresses
(0.0.0.0 and "::").
It makes common sense to restrict access to this service via firewall rules, as the data served leaks
information about the rate and nature of your DNS traffic. This is mostly intended for your own
internal monitoring purposes.
tcp_threads
Integer, default 1, min 0, max 1024. This is the number of separate TCP listening sockets and
corresponding listener threads that will be created for each DNS listener address. On a multi-core
host, increasing this parameter (up to at most a small multiple of the CPU core count) may increase
overall performance. Note that on hosts without SO_REUSEPORT support (notably Linux < 3.9, Solaris),
any setting greater than 1 will be forced to 1 with a warning, as support multiple sockets/threads
per-address are not supported without SO_REUSEPORT.
udp_threads
Exactly like "tcp_threads", but for UDP sockets per DNS listening address.
tcp_clients_per_thread
Integer, default 128, min 1, max 65535. This is maximum number of tcp DNS connections gdnsd will
allow to occur in parallel per listening tcp thread. Once this limit is reached by a given thread,
no new connections will be allowed to that thread until one of the existing ones closes or times out.
Note that sockets map 1:m to threads, and thus the total client limit for connecting to a given
socket address would be "tcp_clients_per_thread * tcp_threads".
tcp_timeout
Integer seconds, default 5, min 3, max 60. TCP DNS connections will be forcibly shut down if they go
idle without receiving and responding to a valid query for this many seconds. gdnsd(8) allows
multiple requests per connection, and this idle timeout applies to the time between requests as well.
udp_recv_width
Integer, default 8, min 1, max 64. On supported Linux kernels this setting tunes the use of more
efficient interfaces to receive and send multiple packets with a single syscall. Higher values
reduce syscall overhead and generally give the server higher throughput and better efficiency under
high loads.
I believe that this is basically always a win under load when supported, but values much larger than
necessary do have a chance to increase average response latency very slightly. The optimal setting
is highly dependent on local hardware, software configuration, and network load conditions.
Setting this to a value of 1 will completely disable this code, as if we were running on a platform
that didn't support it. On platforms that don't support it, this option has no effect and is
ignored. On Linux if we don't detect a 3.0 or higher kernel at runtime, we fall back to the same
code as other platforms that don't support it.
udp_rcvbuf
Integer, min 4096, max 1048576. If set, this value will be used to set the "SO_RCVBUF" socket option
on the UDP listening socket(s). Most users do not need to tune this value. If left unset, the code
takes a somewhat heuristic approach, trying to raise the value only if the OS-supplied default seems
too low, and multiplying it a bit in the case of "udp_recv_width" > 1.
udp_sndbuf
Integer, min 4096, max 1048576. If set, this value will be used to set the "SO_SNDBUF" socket option
on the UDP listening socket(s). Tuning advice mirrors the above.
max_http_clients
Integer, default 128, min 1, max 65535. Maximum number of HTTP connections to allow in parallel at
any given time. Once this number is reached, no more new connections will be answered until an
existing connection closes or times out.
http_timeout
Integer seconds, default 5, min 3, max 60. HTTP connections will be forcibly shut down if they go
idle for more than this many seconds.
zones_strict_data
Boolean, default "false"
If false (the default), reporting of many less-serious errors in zone data are emitted as mere logged
warnings, and the zone data is still loaded and served.
If this is set to true, such warnings will be upgraded and treated the same as the more-serious class
of zone data errors which prevent successful loading of zone data. The consequences of this are
variable: on initial startup or checkconf, this results in a failed zonefile, which may either be
ignored or abort execution, depending on "zones_strict_startup" below. During a runtime zone data
reload, any existing good copy of the zone would continue to be served until the error is corrected
in the source.
zones_strict_startup
Boolean, default "true"
If true (the default), on daemon startup (via "start" or "restart") if any zone fails to load
correctly, the daemon will abort. If false, the daemon will simply ignore the failed zone and
continue operations.
Runtime reloads via SIGUSR1 and/or periodic/inotify scanning always treat bad zone data non-fatally
(leaving any existing good copy intact in memory for lookups).
This also affects the "checkconf" action. It will only fail in terms of exit value on bad zonefiles
if this is true (although it will note any failures to stderr regardless).
zones_rfc1035_auto
Boolean, default "true".
If auto is enabled (the default), the daemon will detect changes to zone data automatically at
runtime and apply them as they appear. In the general case this is done by periodically scanning
"lstat()" data on the contents of the zones directory and looking for metadata changes since last
check.
On modern Linux systems, the daemon may also use "inotify()" to detect filesystem modifications in
realtime. In these cases it will not usually run the periodic "lstat()" scans.
Regardless of whether this setting is true or false, you can always manually trigger a rescan of the
zones directory for new data by sending the daemon a "SIGUSR1" (or executing the "reload-zones"
command, which sends SIGUSR1 for you).
zones_rfc1035_auto_interval
Integer seconds, default 31, min 10, max 600. Only applies when "zones_rfc1035_auto" is "true".
Sets the time interval for periodically checking the zonefile directory for changes. On systems
which support "inotify()", however, the automatic mode will almost always use that mechanism instead
for even faster detection with less overhead. In the "inotify()" case, the interval is used only
occasionally as a fallback mechanism to recover a consistent state after temporary "inotify()"
failures due to inotify queue overflows or the zones directory itself being moved/deleted, etc.
zones_rfc1035_quiesce
Floating-point seconds, default 3.0, min 1.02, max 60.0
Regardless of whether you're using "zones_rfc1035_auto" and/or explicit zone reloads, this interval
defines a quiescence delay timer that's commonly used to coalesce multiple updates to the same file,
avoid race conditions with zonefile writers, and potentially avoid filesystem timestamp issues. This
timer value is also used as the delay to retry loading a zonefile indefinitely if it fails to load
when we first detected a change due to e.g. permissions or locking issues (as opposed to parse
failure).
The timer doesn't generally apply in the "inotify()" case unless there are multiple nearly-
simultaneous events for the same file, or (usually) when the file is modified in-place, or again if
there's a filesystem-level rather than parser-level issue loading the zonefile.
It is highly recommended that whatever tools or scripts you use to manage zonefile updates use atomic
operations (in commandline terms: "mv", "rm" and "ln" (without "-s"!); in syscall terms: "rename()",
"unlink()", and "link()") to replace them regardless of whether your system supports "inotify()" and
regardless of whether you're using "zones_rfc1035_auto" or not. The scanner ignores subdirectories
and dotfiles; feel free to use those to write out the file initially before atomically putting data
into view.
Performing non-atomic operations (e.g. in-place writes) on an active zonefile is inherently racy,
especially if more than one update occurs in less time than the timestamp accuracy of the filesystem.
The daemon makes some accommodations for handling these races, but there will always be ugly corner
cases. It may help slightly if the in-place updater acquires an "fcntl()" advisory writelock. In-
place writes will be especially unreliable if you overwrite a file while the daemon is scanning the
directory during its initial startup, as no quiescence timers or other anti-race mechanisms are used
during startup (as these would necessarily delay service availability).
Note that in the general case if a zone file never goes the full quiescence period without having yet
another update applied to it, the new data may never actually be reloaded, as the daemon will
constantly be trying to wait for a full period of quiescence on the file before loading it.
lock_mem
Boolean, default false. Causes the daemon to do "mlockall(MCL_CURRENT|MCL_FUTURE)", which
effectively locks all daemon memory into RAM, unable to be swapped. Possibly helpful in some
production cases to ensure swap-in doesn't affect DNS latency.
When started as root with lock_mem set to true, the daemon will remove any ulimits on locked memory
before dropping privileges. When started as a regular user it may not be able to do so, and those
limits could cause the server to abort execution at any time if they are set too low.
priority
Signed integer, range -20 to +20, lower values are higher priority. If explicitly set, gdnsd will
attempt "setpriority()" to this value on startup. If left unset and gdnsd is started as a normal
user, no "setpriority()" call will be made. If left unset and gdnsd is started as root, it will
default to calling "setpriority()" with the value "-11".
disable_text_autosplit
Boolean, default false. On the wire, "TXT" records are encoded as discrete chunks of up to 255
characters per chunk. The relevant RFCs state that multiple chunks should be treated by clients as
if they are concatenated. That is to say, it should make no difference to a client whether the "TXT"
data is sent as two 16-byte chunks or one 32-byte chunk.
Ordinarily, you may specify chunk(s) of a "TXT" record in gdnsd zonefiles as a string of any size up
to the legal length (just short of 64K in practice), and gdnsd will auto-split the data into 255-byte
chunks for transmission over the DNS protocol correctly. If you choose to manually break up your TXT
record into multiple strings in the zonefile, gdnsd also honors these boundaries and will not attempt
to merge them into larger chunks where possible.
If you set this option to true, the auto-splitting behavior is disabled, and any single character
string specified in a zonefile as part of a "TXT" record which is larger than 255 bytes will be
considered a syntax error.
include_optional_ns
Boolean, default false. Causes the daemon to include the optional NS records in the Authority
section of simple authoritative responses containing actual response data. Leaving this option in
its default state results in smaller response packets and faster response packet generation in many
common cases. This is similar in nature to (but not exactly like) BIND's "minimal-responses" option,
except that we default to the minimal mode.
Regardless of this setting, all *necessary* Authority-section records are always included, such as
when they are necessary for delegation responses, NXDOMAIN responses, and NOERROR responses
containing no RRsets in the answer section.
plugin_search_path
A single string or an array of strings, default empty. Normally the daemon searches for plugins in
the fixed path "/usr/lib/x86_64-linux-gnu/gdnsd", using filenames of the form "plugin_${name}.so".
If you define this parameter, all paths in this list will be searched in the given order for plugins
*before* trying the default, fixed search path.
realtime_stats
Boolean, default false. Normally the daemon self-imposes a limit of not recalculating the daemon-
wide statistics more often than once per second. This improves efficiency in the case that the
polling traffic on our HTTP interface gets high.
For most uses the default should be fine. If you set this option to true, the stats will be
recalculated on the spot for every stats request. The test suite uses this so that it can double-
check statistics counters between every request it sends. I don't imagine anyone else will need to
use this option, and it could even be determinental to performance on SMP machines.
max_response
Integer, default 16384, min 4096, max 64000. This number is used to size the per-I/O-thread buffers
that we construct response packets in. For any sane, normal use of the DNS, the default value is far
more than enough. For embedded or other low memory hosts, you might even consider setting this
smaller than default to save a bunch of per-socket-context buffer space.
However, if you have strange DNS data that's very large (giant RRsets, giant blobs of data in TXT
records) which might generate response packets greater than the 16K default max here, you *must* set
this parameter large enough to accommodate them or random very bad things will happen. It should be
noted that the odds are high whatever you're trying to do is misguided in the first place. You can
size this by setting it to the max and running some test queries via "dig" (or a similar tool) to
find your limit.
This number does not need to take into account UDP, IP, or any lower-level headers. Typically when
probing your data for the largest response sizes you should do "ANY" queries and/or specific RR-type
queries against the first CNAME in any CNAME chains leading to large RR-sets. Keep in mind that the
"include_optional_ns" option will affect the sizing as well. Also keep in mind that wildcards and
delegations can match any child name, including ones of maximal overall length.
max_edns_response
Integer, default 1410, min 512, max 64000. This is the maximum size of a UDP edns response to a
client, acting as a cap on the edns buffer size advertised by the client in its request.
The default of 1410 is the largest size suggested in RFC 6891 when falling back from the inability to
deliver 4K-sized packets, and it seems very likely to be a successful size for unfragmented delivery
on most networks today even given IPv6 and some reasonable tunneling.
The option obviously has no pragmatic effect if you do not have large response datasets in your zones
in the first place.
This value will be capped at the configured (or default) value of "max_response" with a warning if
configured above that value.
max_addtl_rrsets
Integer, default 64, min 16, max 256. This is the maximum number of RR sets that will ever be added
to the Additional section of a response packet. This sets a hard limit on the number of delegation
glue NS records a subzone can have (which is checked at startup), and a runtime soft limit on other
Additional section RR sets. When the limit is reached at runtime, the remaining potential additional
RR sets are simply not added to the packet. Most users won't need to raise this value, and users on
low-memory/embedded hosts might want to lower it to save more memory.
max_cname_depth
Integer, default 16, min 4, max 24. How deep CNAME -> CNAME chains are allowed to recurse within
local data in a single zonefile. If a chain longer than this is detected between normal static CNAME
entries in the authoritative data of a single zonefile, an error will be thrown when loading the
zonefile.
If the limit is exceeded at runtime (due to "DYNC" dynamic CNAME responses) the code will halt
further recursive lookups for this request and return an empty NXDOMAIN response, and log a loud
message to syslog on every single request for this broken domainname.
Note that this is the only thing preventing infinite CNAME loops caused by bad DYNC plugin
configurations. Also note that even in the "DYNC" case, all of this applies only within a single
zone. The gdnsd code never crosses the boundary between two distinct local zonefiles when processing
queries.
edns_client_subnet
Boolean, default true. Enables support for the edns-client-subnet option. gdnsd only includes this
EDNS option in responses to queries which also contained the option. In the case of normal responses
from static zone data, the scope mask will be set to zero. Dynamic response plugins have access to
the query's EDNS client-subnet data, and have full control over the response scope mask.
If the option is set to false, gdnsd will ignore the option in queries, never set it in its
responses, and plugins will not have access to any data provided by any ignored edns-client-subnet
option in queries.
Of the included standard plugins only "reflect" and "geoip" make use of edns-client-subnet
information. The rest will leave the scope mask at zero as normal for client-location-agnostic
static data.
Relevant links documenting edns-client-subnet:
<http://www.afasterinternet.com/>
<http://tools.ietf.org/html/draft-vandergaast-edns-client-subnet-00>
chaos_response
String, default "gdnsd". When gdnsd receives any query with the class "CH" ("Chaos"), as opposed to
the normal "IN" ("Internet"), it will return a single response record of class "CH" and type "TXT",
which contains the string defined here. This is something like BIND's version reporting, which
responds to "version.bind" queries in the "CH" class, and is what a client will see if they use such
a query against a gdnsd server.
log_stats
Integer, default 3600, min 0, max 86400. The current stats counters will be emitted as log output
(e.g. to syslog) every "log_stats" seconds. If set to zero, periodic stats logging is disabled.
Regardless of this setting, stats counters are always emitted to the log once at the time of daemon
shutdown.
run_dir
String, defaults to /var/run/gdnsd. This is the directory which the daemon owns as its run
directory. It will create this directory and/or modify the permissions and ownership of it on
startup. If it does not exist and cannot be created, or the permissions and ownership cannot be set
to acceptable values, the daemon will not start.
The contents of this directory are private to the daemon and shouldn't be interfered with. This can
live on a filesystem that's volatile across reboots, and doesn't require much disk space.
state_dir
String, defaults to /var/lib/gdnsd. This is the directory which the daemon owns as its state
directory. It will create this directory and/or modify the permissions and ownership of it on
startup. If it does not exist and cannot be created, or the permissions and ownership cannot be set
to acceptable values, the daemon will not start.
The contents of this directory belong to the system administrator and are used to communicate
persistent, stateful information to the daemon. This should live on a filesystem which is preserved
across reboots.
any_mitigation
Boolean, default true. If true, the server will attempt to mitigate problems with ANY-query
reflection attacks over UDP. As ANY queries tend to have the largest response sizes, they are an
obvious target for amplified reflection attacks using gdnsd as the traffic source. ANY queries
aren't commonly used by legitimate clients; they're mostly for debugging.
Currently gdnsd's only mechanism for mitigation is forcing legitimate clients to use TCP for ANY
queries by sending a truncated UDP response. Truncation responses are a normal expectation
regardless, and supporting DNS over TCP is a requirement of the DNS. Therefore this should cause no
real-world performance or interoperability problems in exchange for the protection it offers.
In future releases, "any_mitigation" may behave differently and allow some ANY-over-UDP traffic to
succeed when it's safe to do so. For example, it may allow ANY over UDP up to a certain response
ratelimit, and/or it may allow ANY over UDP when the request source is weakly validated by an edns0
cookie.
SERVICE_TYPES
service_types is used in conjunction with certain gdnsd plugins. If you are not using such a plugin, you
can safely ignore this section and omit it from your configuration.
The service_types hash contains generic definitions for how to monitor a given types of service,
independently of any specific address or hostname for that service.
There are two trivial service_types internally defined as the names "up" and "down", which do no actual
monitoring and simply set the monitored state permanently "UP" or "DOWN". "up" is the default
service_type when no service_type is specified.
Within the definition of a service_type there are several generic parameters related to timing and anti-
flap, as well as plugin-specific parameters that vary per plugin.
A service type does not, however, specify a name or address for a specific instance of a service. Those
would occur on a per-address basis in a resolving plugin's configuration down in the "plugins" stanza,
and the plugin's configuration would then reference a named service type to be used when monitoring said
address.
A service monitored through these mechanisms is always in either the "UP" or "DOWN" state at runtime from
a monitoring perspective. The "UP" state is maintained in the face of intermittent or isolated failures
until the anti-flap thresholds are crossed and the state moves to "DOWN".
Any services monitored for plugins also have their state reported alongside the standard gdnsd statistics
report, served by the built-in HTTP server (default port is 3506).
The following are the generic parameters for all service_types:
up_thresh
Integer, default 20, min 1, max 65535. Number of monitoring requests which must succeed in a row
without any failures to transition a given resource from the "DOWN" state to the "UP" state.
ok_thresh
Integer, default 10, min 1, max 65535. See below.
down_thresh
Integer, default 10, min 1, max 65535. The "ok_thresh" and "down_thresh" parameters control the
transition from the "UP" state to the "DOWN" state while trying to prevent flappy behavior. Their
behavior is best described in terms of an internal failure counter for a resource which is currently
in the "UP" state. The failure counter starts at zero on state transition into the "UP" state.
Every state poll that results in a failed response, even if other successful responses are
interleaved between them, increments the failure counter. If the failure counter reaches
"down_thresh" the resource is transitioned to the "DOWN" state. However, if "ok_thresh" successes
occur in a row with no failures between them, the failure counter is reset back to zero.
So with the default values, the expected behavior is that if an "UP" resource experiences 10
(possibly isolated or intermittent) monitor-polling failures over any length of time, without a
string of 10 successes in a row somewhere within the sequence to reset the counter, it will
transition to the "DOWN" state. Once "DOWN", it will require 20 successes in a row before
transitioning back to the "UP" state.
interval
Integer seconds, default 10, min 1, max 255. Number of seconds between successive monitoring
requests for a given resource.
timeout
Integer seconds, default interval/2, min 1, max 255. Maximum time the monitoring code will wait for
a successful response before giving up and considering the request to be a failure. Defaults to half
of the "interval", and must be less than "interval".
plugin
String, required. This indicates which specific plugin to use to execute the monitoring requests.
Any parameters other than the generic ones listed here are consumed by the plugin.
There are six monitoring plugins included with gdnsd that can be used in a service_types definition, each
of which may have additional, plugin-specific configuration options in addition to the generic ones
above. Each of these is documented in detail in its own manpage e.g. "gdnsd-plugin-FOO":
tcp_connect
Checks TCP basic connectivity on a given port. Only supports address resources, not CNAMEs.
http_status
Checks HTTP connectivity, with options for the port, URL, and vhost to use in the request, and the
acceptable HTTP status codes in the response. Only supports address resources, not CNAMEs.
extmon
Periodically executes a custom external commandline program to poll for the status of a resource.
Supports both address and CNAME resources.
extfile
Reads the contents of a file on disk to import state monitoring data from another source. Supports
both address and CNAME resources.
static
Configures a static monitoring result, mostly for testing / example code. Supports both address and
CNAME resources.
null
Configures an always-down static result, mostly for testing / example code. Supports both address
and CNAME resources.
PLUGINS
The plugins hash is optional, and contains one key for every dynamic resolution plugin you wish to load
and use. The value must be a hash, and the contents of that hash are supplied to the plugin to use in
configuring itself. If the plugin requires no configuration, the empty hash "{}" will suffice. It is up
to the plugin to determine whether the supplied hash of configuration data is legal or not.
Monitoring-only plugins can also be given plugin-global level configuration here if the plugin author
deemed it necessary.
gdnsd ships with eight different monitoring plugins, all of which have their own separate manpage
documentation (e.g. "man gdnsd-plugin-FOO"):
reflect
Reflects DNS client source IP and/or edns-client-subnet information back to the requestor as address
data for debugging.
simplefo
Simple primary->secondary failover of monitored addresses
multifo
All-active failover of monitored round-robin address groups
weighted
Weighted-round-robin responses with a variety of behavioral flavors, for both monitored addresses and
CNAMEs.
metafo
Static-ordered address(-group) meta-failover between 'datacenters', which are resources defined in
terms of other plugins. Supports both address and CNAME data.
geoip
Combines metafo's functionality with MaxMind GeoIP databases to select different datacenter
address(-group) preference/failover orderings for different clients based on approximate geographic
location. Supports both address and CNAME data.
null
Returns all-zeros addresses or the CNAME "invalid." - mostly for testing and as simple example code.
static
Configures static mappings of resources names to IP addresses or CNAMEs - mostly for testing and as
simple example code.
A configuration example showing the trivial plugins, as well as demonstrating the service_types described
earlier:
service_types => {
corpwww_type => {
plugin => http_status
vhost => www.corp.example.com
url_path => /check_me
down_thresh => 5
interval => 5
}
}
plugins => {
null => {},
reflect => {},
static => {
foo = 192.0.2.2
bar = 192.0.2.123
somehost = somehost.example.net.
},
multifo => {
web-lb =>
service_types => [ corpwww_type, xmpp ],
lb01 => 192.0.2.200,
lb02 => 192.0.2.201,
lb03 => 192.0.2.202,
}
}
}
And then in your example.com zonefile, you could have (among your other RRs):
zeros 600 DYNA null
reflect 10 DYNA reflect
reflect-both 10 DYNA reflect!both
pointless 42 DYNA static!foo
acname 400 DYNC static!somehost
www 300/45 DYNA multifo!web-lb
LOW-LEVEL SYNTAX
At the lowest level, the syntax of gdnsd config files roughly resembles an anonymous Perl data structure
(using reference syntax). There are three basic data types for values: ordered hashes (associative
arrays mapping keys to values), ordered arrays of values, and simple strings. Hashes and arrays can be
nested to arbitrary depth. Generally speaking, whitespace is optional. Single-line comments in both
shell ("#") and DNS zonefile styles (";") are allowed. They run to the end of the current line and are
considered to be whitespace by the parser.
A hash is surrounded by curly braces ("{" and "}"). Keys are separated from their values by either "=>"
or "=" (at your stylistic discretion). Hash keys follow the same rules as simple string values. Hash
values can be simple strings, arrays, or hashes. Key/value pairs can optionally have a trailing comma
for stylistic clarity and separation.
An array is surrounded by square braces ("[" and "]"). Values can be simple strings, arrays, or hashes.
Values can optionally have a trailing comma for style.
Strings (and thus keys) can be written in both quoted and unquoted forms. In the quoted form, the string
is surrounded by double-quotes ("""), and can contain any literal byte value (even binary/utf-8 stuff, or
NUL) other than """ or "\". Those two characters must be escaped by "\", i.e. "\"" and "\\".
In the unquoted form, there are no surrounding quotes, and the allowed set of unescaped characters is
further restricted. The following are not allowed: "][}{;#,"=\" (that is, square brackets, curly
brackets, semicolons, octothorpes, commas, double quotes, equal signs, and backslashes). Additionally,
the first character cannot be a "$" (dollar sign).
Both forms use the same escaping rules, which are the same RFC-standard escaping rules used in zone
files. The escapes always start with "\". "\" followed by any single byte other than a digit (0 - 9) is
interepreted as that byte. "\" followed by exactly 3 digits interprets those digits as the unsigned
decimal integer value of the desired byte (the 3 digit value cannot exceed 255).
To illustrate the escaping and quoting, the following sets of example strings show different encodings of
the same parsed value:
example
"example"
ex\097mpl\e
"ex\097mpl\e"
internal\"doublequote
"internal\"doublequote"
white\ space
"white space"
"braces{every[where]oh}my"
braces\{every\[where\]oh\}my
"\\==="
"\092==="
"\092\=\=\="
\\\=\=\=
\092\=\=\=
The top level of the config file is an implicit hash with no bracing by default, but can also be an array
bounded by square brackets. This is not legal for the primary gdnsd configuration file, but could be
useful in includefiles (see below).
As a general rule, anywhere the higher-level syntax allows an array of values, you can substitute a
single value. The code will treat it as if it were an array of length 1.
When we refer in other sections above to a value as being an "Integer" (or other specific scalar type),
we're referring to constraints on the content of the character string value. All scalar values are
character strings. "Boolean" values are characters strings which have the value "true" or "false", in
any mix of upper or lower case.
The following 3 example configuration files are identical in their parsed meanings, and should clarify
anything miscommunicated above:
Example 1 (simple and clean):
options = {
listen = [ 192.0.2.1, 192.0.2.2 ],
http_listen = 127.0.0.1,
}
Example 2 (fat arrows, no commas, some arbitrary quoting):
"options" => {
listen => [ 192.0.2.1 192.0.2.2 ]
http_listen => "127.0.0.1"
}
Example 3 (compressed and ugly):
options={listen=[192.0.2.1 192.0.2.2]http_listen=127.0.0.1}
INCLUDING OTHER FILES
vscf now has a mechanism for config includefiles. The syntax is
$include{dir/file} # single file must exist
$include{dir/*} # not ok if no matching files
$include{dir} # ok if no files in dir
where the path can use the same kinds of escaping and/or double-quoting as normal scalar string data.
Whitespace between the path and the surrounding brackets is optional. Whitespace between $include and
the following "{" is not allowed. If the path is relative (does not begin with /), it is interpreted as
relative to the directory containing the parent file. Includes can nest other includes to arbitrary
depth.
The path is normally treated as a glob, allowing the inclusion of multiple files. When used as a glob,
there must be at least one match - it will be an error if there are no matching files. However, if
"path" is not a glob and names an existing directory explicitly, it will be treated like it was a glob of
all files within that directory by appending "/*", and it will not be an error if there are no files
within that directory (no matches for the glob).
Keep in mind that at the top level of any given vscf file (even include files), the file must
syntactically be either an implicit hash or an explicit, square-bracket-bounded, array.
The include statement can be used in two distinct contexts within the syntax structure of a config file:
Value Context
The include statement can replace any whole value (that is, the right hand side of a hash map entry
or a member of an array) with its own contents, which are either a hash or an array. Note that there
is no mechanism for flattening an include-file's array into the parent array (the whole included
array would be a single array item within the parent array). Also, including multiple files in a
single statement (directory name or glob pattern) are not allowed in value context. Examples:
main config:
options => { listen => $include{foo} }
foo:
[ 127.0.0.1, 127.0.0.2 ]
main config:
plugins => $include{ "bar" }
bar:
geoip => { ... }
extmon => { ... }
Hash-Merge Context
The include statement can also appear in a hash where a key would normally be expected. In this
case, the included file must be in hash (rather than array) form at the top level, and its contents
are merged into the parent hash. The merge is shallow, and conflicting keys are not allowed.
Example:
main config:
options => { ... },
plugins => {
extmon => { ... },
$include{geoip.cfg},
$include{plugins.d},
}
geoip.cfg:
geoip => { ... }
plugins.d/foo:
weighted => { ... }
simplefo => { ... }
plugins.d/bar:
metafo => { ... }
SEE ALSO
gdnsd(8), gdnsd.zonefile(5), gdnsd-plugin-simplefo(8), gdnsd-plugin-multifo(8), gdnsd-plugin-weighted(8),
gdnsd-plugin-metafo(8), gdnsd-plugin-geoip(8), gdnsd-plugin-extmon(8), gdnsd-plugin-extfile(8)
gdnsd-plugin-api(3)
The gdnsd manual.
COPYRIGHT AND LICENSE
Copyright (c) 2012 Brandon L Black <blblack@gmail.com>
This file is part of gdnsd.
gdnsd is free software: you can redistribute it and/or modify it under the terms of the GNU General
Public License as published by the Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
gdnsd is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
License for more details.
You should have received a copy of the GNU General Public License along with gdnsd. If not, see
<http://www.gnu.org/licenses/>.
gdnsd 2.4.2 2019-03-05 GDNSD.CONFIG(5)