 |
|
| |
GDNSD.CONFIG(5) |
gdnsd |
GDNSD.CONFIG(5) |
gdnsd.config - gdnsd configuration file
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 => {}
}
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 /usr/local/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.
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/local/lib/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/db/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 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.
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
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}
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 => { ... }
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 (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/>.
Visit the GSP FreeBSD Man Page Interface. Output converted with ManDoc.
|