Provided by: gdnsd_3.8.2-2_amd64 bug

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

       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 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  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]:53035",
               ]
             }

           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 = 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
           datagrams  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 "listen" option, as the default could
           be subject to breaking changes in major 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,  increasing  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 address.

       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 possible.  The code is designed to be resilient  (at  least  answer
           one   legitimate   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 mechanisms like RFC 7828 EDNS TCP Keepalive or RFC 8490  DNS
           Stateful Operations (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  connections,  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-behaved client connections which  don't  stall  out  midway  through  a
           transaction  only  become  idle  connections  (subject  to  termination  for  idleness) during inter-
           transaction idle periods after their first transaction, 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 information 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 issues 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  features  like  "TCP_DEFER_ACCEPT"  and  "SO_ACCEPTFILTER".  If left at (or set to) the default
           value of zero, the compile-time constant "SOMAXCONN" from the operating system will  be  used,  which
           tends to be reasonable 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 multiple servers
           behind a loadbalancer or anycast pool, may also require administrative 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/download/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 request 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 requests 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 control 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  listen 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 explicit 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 operations 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 coordination 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 successful 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_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.

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

       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, especially in a private network where a larger path MTU (e.g.
           ~9K for ethernet 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 option from RFC 7871.  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.

       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.

       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 explicit TTL, to avoid cases of mixed TTLs when mixing static
           and dynamic records in server outputs.

       nsid
           String, 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 packets.  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 specific servers when
           multiple servers are part of an anycast or loadbalancer 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 specified.

       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 disable) in a  future  release.   If
           this  new  default behavior causes a problem, you can (for now!) set the option to false to revert to
           the traditional  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 subnet 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 configurable, it would significantly
           simplify the code and make lookups more efficient (these gains are not realized by  the  experimental
           optional 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 historically some older
           implementations implicitly relied on the authserver 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  parameter  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 contain 32 bytes of  binary  data.
           Failure to properly read a key file defined 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 generated 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 /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 future 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-generated key exists
           only in daemon memory and will not persist across future 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
           outstanding server cookies held by clients.

       run_dir
           String, defaults to /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  currently  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/lib/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 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 ],
         }

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

       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 3.8.2                                        2024-06-10                                    GDNSD.CONFIG(5)