Skip site navigation (1)Skip section navigation (2)

FreeBSD Manual Pages

  
 
  

home | help
GDNSD.CONFIG(5) 		      gdnsd			 GDNSD.CONFIG(5)

NAME
     gdnsd.config - gdnsd configuration file

SYNOPSIS
       options => {
	 tcp_timeout => 15 ; zonefile-style comment
	 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 configu-
     ration directory.	The default configuration directory is /usr/lo-
     cal/etc/gdnsd, but this can be overridden by the "-c" commandline option.

     The lower-level syntax and structure of the configuration language is de-
     scribed in detail at the end of this document, but it should be fairly in-
     tuitive 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 white-
     space or various ambiguous metacharacters.

     The top-level implicit hash of a gdnsd configuration file allows only 3 le-
     gal 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).

     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 di-
	 rective (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 ar-
	 guably the most stable records in the whole system.  It's hard to imag-
	 ine good reasons to raise this value in practice.

     min_ttl
	 Integer seconds, default 5, range 0 - 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.

     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 getad-
	 drinfo() 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-de-
	 fault 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 ba-
	 sic 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]:53035",
	     ]
	   }

	 It can also be a hash where the keys are listen addresses, and the val-
	 ues are per-address options, as in:

	   options => {
	     listen => {
	       192.0.2.1 => {
		 tcp_timeout = 15
	       },
	       192.0.2.2:53035 => {
		 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", "tcp_fastopen", "udp_threads", "udp_rcvbuf",
	 and "udp_sndbuf".

	 Finally, it can also be set to the special string value "any", as in:

	   options => { listen => any }

	 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 data-
	 grams via the interface they were received on with a source address
	 matching the destination address of the request.

	 Production configurations should always explicitly define their "lis-
	 ten" option, as the default could be subject to breaking changes in ma-
	 jor version upgrades.	The current default is the "any" behavior above.

     tcp_threads
	 Integer, default 2, min 1, 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, increas-
	 ing this parameter (up to at most a very small multiple of the CPU core
	 count) may increase overall performance.

     udp_threads
	 Exactly like "tcp_threads", but for UDP sockets per DNS listening ad-
	 dress.

     tcp_clients_per_thread
	 Integer, default 256, min 16, max 65535.  This is maximum number of tcp
	 DNS connections gdnsd will allow to occur in parallel per listening tcp
	 thread.  When this limit is reached by a new incoming connection, the
	 longest-idle of the existing connections will be closed immediately in
	 exchange for it.

	 You can monitor the "tcp.close_s_kill" stat to see if such closes are
	 happening due to reaching the limit, which should be avoided if possi-
	 ble.  The code is designed to be resilient (at least answer one legiti-
	 mate request per legitimate connection) even in the face of misbehaving
	 (e.g. slow-read/write) connection overloads on Linux, and on BSDs with
	 "SO_ACCEPTFILTER" and the appropriate kernel modules ("accf_dataready"
	 and/or "accf_dns") loaded (there will be a non-fatal error log output
	 on startup if they aren't).

	 Note that socket addresses map 1:m to threads (that is, each thread
	 gets a separate "SO_REUSEPORT" instantiation of a given logical
	 socket), and thus the total client limit for connecting to a given
	 socket address would be "tcp_clients_per_thread * tcp_threads", but
	 it's up to the operating system to balance connections, and it may use
	 simple connection tuple hashing or simple round-robin, neither of which
	 may guarantee very even distribution.

     tcp_timeout
	 Integer seconds, default 37, min 5, max 1800.

	 This determines the client-side idle timeout for TCP connections, which
	 is sent by the server to applicable clients supporting signalling mech-
	 anisms like RFC 7828 EDNS TCP Keepalive or RFC 8490 DNS Stateful Opera-
	 tions (DSO).

	 There is a corresponding server-side timeout which determines when
	 gdnsd will give up on a client it believes to be delinquent (one that
	 keeps a connection open too long without honoring any signalled
	 client-side idle timeout).  The server-side timeout is double the
	 client timeout (which equates to a default of 74, min 10, max 3600).

	 Note that in the common/typical case of well-behaved clients and con-
	 nections, on a Linux server (where we use TCP_DEFER_ACCEPT) or a BSD
	 server supporting the "dnsready" or "dataready" accept filters, when a
	 new connection arrives we immediately receive the first request and
	 fire back the response without any opportunity for delays that count as
	 idle time, without re-entering the general eventloop where idle time is
	 processed or other new connections could arrive.

	 The idleness of a client is only reset after it completes each full
	 transaction (send us a full request, and our full response makes it
	 into at least the local write buffer).  Inability to immediately write
	 a full response into the server's local TCP buffers (generally because
	 the client has a too-small receive window and/or is not ACKing several
	 previous replies) causes immediate connection termination.  Well-be-
	 haved client connections which don't stall out midway through a trans-
	 action only become idle connections (subject to termination for idle-
	 ness) during inter-transaction idle periods after their first transac-
	 tion, and for not-so-well-behaved clients the idle timer helps control
	 the impact of patterns similar to slow-read/write attacks.

	 The server will send edns TCP keepalive information to clients with all
	 responses where it is legal (request used EDNS over TCP, and DSO is not
	 yet established).  The timeout value will be sent with the fixed value
	 that is configured here until the server begins shutting down, at which
	 point the zero value is sent in such responses in an attempt to get
	 clients to cleanly close.

	 Clients which establish DSO via the Keepalive TLV will get the same
	 client-side timeout sent to them as the DSO Inactivity timeout, with
	 the DSO KeepAlive interval set to Infinite (this means we don't request
	 the client to ever send artificial keepalive pings, and our client-side
	 timeout applies to the interval between real DNS request transactions
	 in the session).  DSO clients will also get better and more-timely in-
	 formation when the server is shutting down or being replaced (we can
	 push immediate DSO unidirectional messages towards them asking that
	 they close their session gracefully).

     disable_tcp_dso
	 Boolean, default false.  This disables RFC 8490 DNS Stateful Operations
	 (DSO) support for TCP threads.

	 Probably the only good reasons to disable would be finding interop is-
	 sues or misbehaviors in this new code and/or standard, as otherwise it
	 offers a superior mechanism for managing stateful client connections
	 versus the previous best available solution (RFC 7828 EDNS TCP
	 Keepalive).

     tcp_backlog
	 Integer, min 0, default 0, max 65535.	This sets the "backlog" argument
	 of the listen() call for TCP listening sockets.  The exact effects of
	 this varies by OS implementation, and it can also interact with fea-
	 tures like "TCP_DEFER_ACCEPT" and "SO_ACCEPTFILTER".  If left at (or
	 set to) the default value of zero, the compile-time constant "SOMAX-
	 CONN" from the operating system will be used, which tends to be reason-
	 able for most use-cases.

     tcp_fastopen
	 Integer, default 256, min 0, max 1048576.  If set to a non-zero value,
	 declares a TCP Fastopen queue size and enables the feature.  TCP
	 Fastopen allows clients who have connected to the server at least once
	 before to send initial data (in our case, their first DNS request) at
	 the same time as their initial SYN, shaving off the round trip delays
	 of the handshake on reconnect.  This is recommended, but may require
	 OS-level support and/or configuration tuning, and in the case of multi-
	 ple servers behind a loadbalancer or anycast pool, may also require ad-
	 ministrative coordination of the server-side secret TFO key.

     tcp_proxy
	 Boolean, default false.  This TCP option is only supported inside the
	 per-address options of a specific listener address in the hash form of
	 the "listen" option, not as a global option.

	 Addresses for which the option is enabled only accept PROXY requests,
	 cannot use port number 53, do not spawn corresponding UDP listeners,
	 and do not accept UDP-related options.  We support both version 1 and 2
	 of the PROXY protocol as defined in <https://www.haproxy.org/down-
	 load/1.8/doc/proxy-protocol.txt>, and only accept TCPv4, TCPv6, and
	 PROXYv2's "LOCAL".

	 The source IP passed to gdnsd over the PROXY protocol will be used as
	 the connection source address for all logical purposes, including e.g.
	 GeoIP lookup fallbacks in the absence of edns-client-subnet.  Once the
	 initial PROXY header is parsed successfully, the connection is treated
	 exactly as any other TCP connection for the remainder of its life.

	 It is not recommended to expose PROXY listeners to public traffic; they
	 should be confined to localhost or to addresses which are not reachable
	 outside of your infrastructure due to firewalling, etc.  This option is
	 primarily intended to test encrypted transports using external daemons
	 proxying into gdnsd.  If using it for some other generic loadbalancing
	 without crypto, padding should be disabled via "tcp_pad" below.

	 PROXY connections increment all of the same stat counters as regular
	 TCP connections, and also add two new proxy-specific ones:

	     tcp.proxy: count of received connections on PROXY listeners (also
			increments the normal tcp.conns stat).
	     tcp.proxy_fail: count of received PROXY connections which are
			     closed early for failing to send a PROXY header
			     the server parses and likes (also increments
			     tcp.close_s_err)

	 Example listen config:

	       options => {
		 listen => {
		   0.0.0.0 => { ... } # normal UDP+TCP on port 53
		   :: => { ... } # normal UDP+TCP on port 53 for IPv6
		   127.0.0.1:53035 => { tcp_proxy => true, ... }
		 }
	       }

     tcp_pad
	 Boolean, default false for normal TCP listeners, default true for
	 "tcp_proxy" listeners (see above).  This TCP option is only supported
	 inside the per-address options of a specific listener address in the
	 hash form of the "listen" option, not as a global option.

	 If enabled (by default for the "tcp_proxy" case), a response to any re-
	 quest which carries an EDNS OPT RR will be padded using the EDNS
	 Padding option to a multiple of 468 bytes as recommended in RFC 8467.
	 This should only be enabled if the TCP connections to a listener are
	 encrypted by a proxy, which is the intended use-case for "tcp_proxy"
	 above.  You may wish to enable this manually if proxying encrypted re-
	 quests via a daemon that doesn't do the PROXY protocol, and you may
	 wish to disable it on "tcp_proxy" listeners if the other daemon isn't
	 providing a crypto wrapper.

     udp_rcvbuf
	 Integer, min 4096, max 1048576, default 0.  If set to a non-zero value,
	 this value will be used to set the "SO_RCVBUF" socket option on the UDP
	 listening socket(s), otherwise we leave the OS defaults alone.

     udp_sndbuf
	 Integer, min 4096, max 1048576, default 0.  If set to a non-zero value,
	 this value will be used to set the "SO_SNDBUF" socket option on the UDP
	 listening socket(s), otherwise we leave the OS defaults alone.

     tcp_control
	 DANGER - Exposing the control socket over TCP is dangerous.  The con-
	 trol socket server code is not designed to be robust against arbitrary
	 attack traffic, and does not have any authentication or encryption.
	 Listen addresses defined here should be well-protected and confined by
	 network firewall policies to internal, privileged clients, and should
	 definitely not be exposed on the public Internet.

	 This specifies one or more secondary TCP listen addresses for control
	 socket connections (alongside the required primary UNIX domain socket),
	 which must be explicitly configured if desired.  It is similar to lis-
	 ten above in that it accepts either a single address spec, an array of
	 address specs, or a hash whose keys are address specs and whose values
	 are address-specific options.	All address specs must include an ex-
	 plicit address and non-zero port number.

	 The only two address-specific options are "chal_ok" and "ctl_ok", which
	 are booleans defaulting to false.  By default, a TCP control socket is
	 restricted to read-only operations ("gdnsdctl status", "gdnsdctl
	 stats", and "gdnsdctl states").  "chal_ok" allows ACME Challenge opera-
	 tions on the socket ("gdnsdctl acme-dns-01" and "gdnsdctl
	 acme-dns-01-flush").  "ctl_ok" allows daemon control commands on the
	 socket ("gdnsdctl reload-zones" and "gdnsdctl replace").  The "gdnsdctl
	 stop" command isn't allowed over TCP at all.

	 The standard unix control socket is also used for some inter-daemon co-
	 ordination and resource handoff during replacements, which cannot be
	 supported over the TCP variant.

	 Examples:

	     options => { tcp_control => 127.0.0.1:885 } # read-only ops only

	     options => { tcp_control => [ 127.0.0.1:885, 127.0.0.2:885 ] } # ditto

	     options => { tcp_control => {
		 127.0.0.1:885 => {} # readonly
		 127.0.0.1:886 => { chal_ok => true } # allows challenge stuff
		 127.0.0.1:887 => { ctl_ok => true } # allows daemon control
		 127.0.0.1:888 => { chal_ok => true, ctl_ok => true } # allows both
	     }}

	 The "gdnsdctl" client has an option "-s" for specifying a TCP socket to
	 connect to for use with "tcp_control" sockets, in which case it does
	 not even attempt to parse the server configuration to find the normal
	 unix socket path.

     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 suc-
	 cessful loading of zone data.

     zones_rfc1035_threads
	 Integer, default 2, min 1, max 1024.  When the standard RFC1035 zone
	 files are (re-)loaded, up to this many ephemeral threads will be
	 spawned in parallel to help load and parse them faster.

	 The way the work is divided among the threads is relatively naive: As
	 the zones directory on the filesystem is scanned for zone filenames,
	 the names are divided evenly into N separate work lists (one per
	 thread), and then the threads are all spawned and work on their own
	 fixed lists in parallel, with the final splicing of the zone data into
	 the root tree happening serially in the main zones thread as each
	 worker thread finishes.  In the case that the total count of zonefiles
	 is less than the configured thread count, the excess threads are not
	 spawned.

	 This simple strategy tends to work well for large counts of zonefiles
	 where the per-zonefile parsing costs are roughly even, but in cases
	 where a minority of zonefiles take much longer to parse than others, it
	 will not always result in a very "fair" outcome (some threads may run
	 much longer than others).

	 Note that in general, improving the I/O performance of reading the
	 zonefiles from disk (e.g. put them on an SSD) tends to help more than
	 the parallelization here does, although both together is even better!

     lock_mem
	 Boolean, default false.  Causes the daemon to do mlockall(MCL_CUR-
	 RENT|MCL_FUTURE), which effectively locks all daemon memory into RAM,
	 unable to be swapped.	Possibly helpful in some production cases to en-
	 sure swap-in doesn't affect DNS latency.

	 You'll need to ensure the ulimit for locked memory is sufficient large
	 (e.g.	"infinity") to avoid process death.

     disable_text_autosplit
	 Boolean, default false.  On the wire, "TXT" records are encoded as dis-
	 crete 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 zone-
	 files as a string of any size up to the legal length (just short of 16K
	 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 zone-
	 file, 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 dis-
	 abled, 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.

     max_edns_response
	 Integer, default 1232, min 512, max 16384.  This is the maximum size of
	 a UDP edns response to a client over IPv4, acting as a cap on the edns
	 buffer size advertised by the client in its request.

	 It is recommended that you do not raise this value from the default for
	 a server facing the public Internet.

	 Setting this in the ~4-16K range might be desirable if you have large
	 response RR-sets and are willing to tolerate some fragmentation, espe-
	 cially in a private network where a larger path MTU (e.g. ~9K for eth-
	 ernet jumbo frames) can be guaranteed.

	 The option obviously has no pragmatic effect if you do not have large
	 response datasets in your zones in the first place.

     max_edns_response_v6
	 Integer, default 1232, min 512, max 16384.

	 As above for UDP edns responses over IPv6.  Once again, raising this
	 above its default value is not recommended for a public-facing server.

     edns_client_subnet
	 Boolean, default true.  Enables support for the edns-client-subnet op-
	 tion from RFC 7871.  gdnsd only includes this EDNS option in responses
	 to queries which also contained the option.  In the case of normal re-
	 sponses from static zone data, the scope mask will be set to zero.  Dy-
	 namic 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.

     chaos_response
	 String, default "gdnsd".  When gdnsd receives any query with the class
	 "CH" ("Chaos"), as opposed to the normal "IN" ("Internet"), it will re-
	 turn a single response record of class "CH" and type "TXT", which con-
	 tains 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.

     acme_challenge_ttl
	 Integer seconds, range 60-3600, default 600.  For temporary ACME DNS-01
	 challenge data added via "gdnsdctl acme-dns-01 ...", this sets the time
	 until the TXT records auto-expire from the server and disappear.

	 See the gdnsdctl(8) documentation about "acme-dns-01" for more details.

     acme_challenge_dns_ttl
	 Integer seconds, range 0-3600, default 0.  For temporary ACME DNS-01
	 challenge data added via "gdnsdctl acme-dns-01 ...", this sets the DNS
	 TTL value which is used in response TXT RRs.

	 In previous versions, the DNS TTL value mirrored the expiry TTL from
	 "acme_challenge_ttl" above.  However, this (non-zero DNS TTLs for these
	 records in general) has lead to confusing issues in the real world with
	 ACME servers under certain conditions.

	 Note that static zonefile RRs with "_acme-challenge" as their leading
	 label are also forced to this TTL regardless of the zonefile-level ex-
	 plicit TTL, to avoid cases of mixed TTLs when mixing static and dynamic
	 records in server outputs.

     nsidString, no default, 2-256 chars in length.  Character count must be
	 even, and all characters must be ASCII hex digits.  This encodes up to
	 128 bytes of arbitrary binary data chosen by the administrator and
	 serves it in the EDNS NSID (RFC 5001) option data of all response pack-
	 ets.  The NSID is obviously not emitted to clients unless they request
	 it via EDNS, and is not emitted at all unless this option is specified
	 explicitly.  This is intended to help with the identification of spe-
	 cific servers when multiple servers are part of an anycast or loadbal-
	 ancer pool.

     nsid_ascii
	 String, no default, 1-128 chars of printable ASCII characters.  This is
	 an convenience alternative to "nsid" above, allowing the binary NSID
	 data to be configured with the bytes of a printable ASCII string up to
	 128 bytes in length.  Only one of "nsid" or "nsid_ascii" may be speci-
	 fied.

     experimental_no_chain
	 Boolean, default true.

	 If set to true (the default), when a query for any RR type encounters a
	 "CNAME" RR in the zone data, the behavior of the server will be as if
	 the queried type was "CNAME".	This implies no chasing of the target
	 (right-hand-side) name to emit any further answer-section records or
	 delegations related to the target, even if they exist in the local data
	 of the same zone.

	 This option is likely to become the fixed behavior (no option to dis-
	 able) in a future release.  If this new default behavior causes a prob-
	 lem, you can (for now!) set the option to false to revert to the tradi-
	 tional behavior of emitting chained multi-RR responses for zone-local
	 CNAMEs as a workaround.  Please file a bug report if so, otherwise
	 we'll have no feedback to go on!

	 This behavior is desirable for a few reasons:

	 RFC 7871 (edns-client-subnet) actually recommends it for at least sub-
	 net differentiated responses, because otherwise it's ambiguous which of
	 the multiple answer-section records the subnet scoping applies to, and
	 caches invariably have to take a pessimistic view and subnet-fragment
	 cache entries pointlessly.  This is the most-compelling rationale, and
	 it has impact on what kind of efficient geodns setups can work at all
	 for certain use-cases.

	 It also adheres to the general principle of minimal responses we adhere
	 to elsewhere (caches may have the target cached already anyways), and
	 it helps minimize response sizes (reduce reflection, and esp helpful
	 for DNSSEC in the future).

	 Also, if this were the fixed behavior of the server, rather than con-
	 figurable, it would significantly simplify the code and make lookups
	 more efficient (these gains are not realized by the experimental op-
	 tional version).

	 However, it's also RFC-questionable.  The original RFC1034 algorithms
	 ask that authoritative servers complete local CNAME chains from local
	 data (which this violates), but also requires recursors to complete
	 them remotely (which makes this work, and which most do now, but his-
	 torically some older implementations implicitly relied on the auth-
	 server doing it).  RFC 2308 also touches on this topic, and the TL;DR
	 there is that recursors can tell our incomplete responses from actual
	 negative "No Data" responses about the next name in the chain by the
	 fact that we don't emit an SOA record in the auth section.

	 Update 2020-11: this has now been tested pretty widely on the Internet
	 (by a major site with a global audience of millions), for a very long
	 time (nearly two years), and there has been no evidence so far of
	 breakage or failure reports from real users.

     disable_cookies
	 Boolean, default false.  Disables support for RFC 7873 EDNS Cookies.
	 Not recommended, as these cookies provide a layer of defense against
	 both off-path response forgery and amplification attacks.  One possible
	 legitimate reason to disable cookies would be if gdnsd is operating in
	 a mixed set of loadbalanced/anycasted auth servers and some of the
	 other servers do not support cookies, or use different algorithms than
	 gdnsd.  Our cookie support is fairly efficient; there shouldn't be any
	 major performance reason to disable it.

     max_nocookie_response
	 Integer bytes, default zero (disabled), range 128-1024.  If this para-
	 meter is set to a non-zero value, all UDP responses will be limited to
	 this many bytes unless the query presents a valid EDNS Cookie that the
	 server recognizes as its own.	Responses which fail this check (UDP
	 with no valid cookie and larger than this length) will be truncated
	 fully (no response RRs) and the TC-bit will be set, asking the client
	 to retry over TCP.

	 This is intended to limit the ability of attackers to use your server
	 as a reflection source for amplification attacks, as valid cookies give
	 some reasonable guarantee that the query packet source address wasn't
	 forged.  It should be pretty safe to set this at least as low as 512,
	 and that may become the default setting in some future version.

     cookie_key_file
	 String, default undefined.  When this is defined, the file's contents
	 are read as the persistent primary key value for generating EDNS Cookie
	 responses.

	 If the file exists, it must be readable by the daemon, and it must con-
	 tain 32 bytes of binary data.	Failure to properly read a key file de-
	 fined here is fatal at startup.  Permissions should be set with care,
	 so that other unprivileged users of the system cannot read the key.

	 Note that the contents are considered binary data and are used directly
	 as secret key input to crypto algorithms, and thus they should be gen-
	 erated securely with high entropy and indistinguishable from random
	 bytes.  It is recommended the file's contents be generated with an RNG
	 outputting 32 random binary bytes, e.g.: "dd if=/dev/urandom
	 of=cookie.key bs=32 count=1".

	 The keyfile's contents don't have to be changed on any sort of fixed or
	 frequent schedule to maintain security.  Treat it like any other
	 long-term secret value and make new ones once in a blue moon just out
	 of an abundance of caution, or if you believe the previous key material
	 may be compromised.  The daemon must be replaced or restarted to put
	 the new key into effect, and this will abruptly invalidate outstanding
	 cookies clients may be holding that were generated with previous keys.

	 The primary reason to define "cookie_key_file" to your own pathname and
	 key contents is to have synchronized cookie keys across an anycasted or
	 otherwise loadbalanced set of servers, so that they all agree on server
	 cookies.

	 If this file is not defined, then the daemon manages the cookie primary
	 key value automatically.  Under automatic management of the key, it
	 will attempt to read a key from /var/run/gdnsd/cookie.autokey at
	 startup.  If that doesn't work, it will generate a new random key in
	 memory and attempt to write it to the same path for consumption by fu-
	 ture daemons.	If both reading an old automatic key and writing the new
	 one fail, a non-fatal error will be logged, and the new randomly-gener-
	 ated key exists only in daemon memory and will not persist across fu-
	 ture daemon replace or restart cycles.

	 Note that in common Linux/systemd installations, the run directory will
	 be wiped on OS reboots and a fresh key will be generated on the next
	 daemon startup.  As with a manually-defined "cookie_key_file", any time
	 the automatic key must be regenerated, this will invalidate all out-
	 standing server cookies held by clients.

     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 or modify the permissions of an existng
	 one on startup.  If it does not exist and cannot be created, or the
	 permissions cannot be set to acceptable values (possibly because the
	 existing directory is owned by a different uid than the daemon is cur-
	 rently running as), 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.

	 The daemon's control socket and lock files live here.

     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 if necessary at startup.  If it does not
	 exist and cannot be created, 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.

	 The admin_state file lives here.

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 parame-
     ters 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 re-
     solving plugin's configuration down in the "plugins" stanza, and the plu-
     gin'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 behav-
	 ior is best described in terms of an internal failure counter for a re-
	 source 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 suc-
	 cessful 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) moni-
	 tor-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 exe-
	 cute 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-spe-
     cific 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 re-
	 sponse.  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.

     nullConfigures 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 reso-
     lution 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 it-
     self.  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.

     nullReturns all-zeros addresses or the CNAME "invalid." - mostly for test-
	 ing 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 demonstrat-
     ing 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 consid-
     ered 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 sim-
     ple 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 al-
     lowed: "][}{;#,"=\" (that is, square brackets, curly brackets, semicolons,
     octothorpes, commas, double quotes, equal signs, and backslashes).  Addi-
     tionally, the first character cannot be a "$" (dollar sign).

     Both forms use the same escaping rules, which are the same RFC-standard es-
     caping 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 can-
     not 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 de-
     fault, 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 in-
     cludefiles (see below).

     As a general rule, anywhere the higher-level syntax allows an array of val-
     ues, 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 ],
       }

     Example 2 (fat arrows, no commas, some arbitrary quoting):

       "options" => {
	 listen => [ 192.0.2.1 192.0.2.2 ]
       }

     Example 3 (compressed and ugly):

       options={listen=[192.0.2.1 192.0.2.2]}

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 inter-
     preted 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 ex-
     plicit, square-bracket-bounded, array.

     The include statement can be used in two distinct contexts within the syn-
     tax 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 par-
	 ent array).  Also, including multiple files in a single statement (di-
	 rectory name or glob pattern) are not allowed in value context.  Exam-
	 ples:

	   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 nor-
	 mally 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-mul-
     tifo(8), gdnsd-plugin-weighted(8), gdnsd-plugin-metafo(8), gdnsd-plu-
     gin-geoip(8), gdnsd-plugin-extmon(8), gdnsd-plugin-extfile(8)

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

     You should have received a copy of the GNU General Public License along
     with gdnsd.  If not, see <http://www.gnu.org/licenses/>.

gdnsd 3.8.0			   2026-08-01			 GDNSD.CONFIG(5)

Want to link to this manual page? Use this URL:
<https://man.freebsd.org/cgi/man.cgi?query=gdnsd.config&sektion=5&manpath=FreeBSD+Ports+15.1.quarterly>

home | help