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 configuration directory.  The default configuration directory is
       /usr/local/etc/gdnsd, but this can be overridden	by the "-c"
       commandline option.

       The lower-level syntax and structure of the configuration language is
       described in detail at the end of this document,	but it should be
       fairly intuitive	from the example above.	 It is effectively a generic
       data structure language allowing	arbitrarily-nested ordered hashes,
       ordered arrays, and scalar values.  Double-quotes are used to quote
       scalars containing whitespace or	various	ambiguous metacharacters.

       The top-level implicit hash of a	gdnsd configuration file allows	only 3
       legal keys: options, service_types, and plugins.

       Any of them which are present must have a Hash as their value.

       All of them are optional, as is the configuration file itself.  If
       you're happy with an all-default	configuration, you can simply not have
       a config	file at	all.

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
	   /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 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 /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 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/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
       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.0			  2025-04-13		       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+14.3.quarterly>

home | help