DEADWOOD(1)
π DEADWOOD(1) β Deadwood reference π
okay bestie, sit DOWN, because this is the manual page for Deadwood, and she's a whole queen. This is the top-level reference for the Deadwood command, page one of the (1) section, from the Deadwood reference fam. Grab a snack, we're going deep π
β¨ NAME β¨
Deadwood β a fully recursive caching DNS resolver. that's it, that's the girl π
πΈ DESCRIPTION πΈ
Deadwood is a fully recursive DNS cache. Like, a DNS server, but make it iconic. Here's the full vibe list of what she does:
- Full support for both DNS recursion and DNS forwarding caching β¨
- Small size and memory footprint suitable for embedded systems π§ (tiny but mighty)
- Simple and clean codebase (no cap, the code is a clean girl)
- Secure design π
- Spoof protection: strong cryptography used to determine the Query ID and source port π
- Ability to read and write the cache to a file
- Dynamic cache that deletes entries not recently used (she's not a hoarder)
- Ability to use expired entries in the cache when it is impossible to contact upstream DNS servers π (emergency backup energy)
- IPv6 support can be compiled in if desired
- Both DNS-over-UDP and DNS-over-TCP are handled by the same daemon
- Built-in dnswall functionality
- The ability to assign names to IPv4 IPs as specified in one's
dwood3rcfile - The ability to quickly load and use a large blocklist of names to not resolve π«
π COMMAND LINE ARGUMENTS π
Deadwood has a single optional command line argument: the location of the configuration file that Deadwood uses, specified with the -f flag. If this is not defined, Deadwood uses the file /etc/dwood3rc as the configuration file.
In other words, bestie, it works like this:
Deadwood
β uses /etc/dwood3rc as the config file.
Deadwood -f foobar
β uses the file "foobar" in the current working directory (aka the directory one is in when starting Deadwood) as the configuration file. slay.
π¦ CONFIGURATION FILE FORMAT π¦
The Deadwood configuration file is modeled after Python 2's syntax. BUT β plot twist β since Python 2 is no longer supported by the Python Software Foundation, and since Deadwood configuration files can sometimes fail to parse in Python 3, Deadwood does not strictly follow Python 2 syntax.
In particular: leading whitespace is allowed in Deadwood configuration files. (yes, go ahead and indent, she won't judge)
π PARAMETER TYPES π
Deadwood has three different parameter types, and you gotta know the difference or the config file will simply not eat:
- Numeric parameters. Numeric parameters must not be surrounded by quotes, like this:
filter_rfc1918 = 0
If a numeric parameter is surrounded by quotes, the error message "Unknown dwood3rc string parameter" will appear. π
- String parameters. String parameters must be surrounded by quotes, such as in this example:
bind_address = "127.0.0.1"
- Dictionary parameters. All dictionary parameters must be initialized before use, and dictionary parameters must have both the dictionary index and the value for said index surrounded by quotes, such as in this example:
upstream_servers = {}
upstream_servers["."]="8.8.8.8, 8.8.4.4"
Now, listen closely π β all dwood3rc parameters except the following are numeric parameters:
bind_address(string)blocked_hosts_hash_file(string)cache_file(string)chroot_dir(string)ip4(dictionary)ip6(dictionary)ip_blacklist(string)ip_blocklist(string)ipv4_bind_addresses(string)random_seed_file(string)recursive_acl(string)root_servers(dictionary)source_ip4(string)upstream_servers(dictionary)
π SUPPORTED PARAMETERS π
The Deadwood configuration file supports the following parameters. buckle up, there's a lot, and every single one is getting her moment π
β¨ allow_block_hash_zero_key β¨
If this numeric parameter has a value of 1, we allow a blocked hosts hash file to have a key which is 0. Otherwise, if a blocked hosts file has a 0 key, Deadwood will terminate when loading the blocked hosts file with the error message:
Zero key block hash not allowed by default
There is a security risk if we allow a blocked hosts file to have a 0 key: an attacker with access to a recursive instance of Deadwood could have Deadwood use more resources than necessary if they know the block hash file being used. Since the block hash file is read only, hash flooding attacks are not possible, but an attacker could form queries which use more resources to resolve as not being present in the block hash.
Deadwood should never be an open recursor and this attack is limited in scope. But be aware of the risks before setting this parameter to 1. π
bestie. read that twice. risk acknowledged, okay? π«Ά
β¨ bind_address β¨
This is the IP (or possibly IPv6) address we bind to.
β¨ blocked_hosts_hash_file β¨
A blocked hosts hash file lets Deadwood block a large number of host names while using relatively little memory. the receipts: while using a list of over 200,000 hosts to block in a dwood3rc file uses over 200 megabytes of memory, the same list in a block hash file uses only 7 megabytes of memory. that's the difference, and it's not subtle π
The block hash file is in a special binary format so that a large number of host names can be blocked quickly using little memory.
This parameter, if set, is the filename for a block hash file. The file will be located in the directory set by chroot_dir (usually, /etc/deadwood). The file name can have lower case letters, the - character (dash), the _ character (underscore), the . character (dot or period), and the / character (slash). If the file name has the . character (dot/period) in it, it can not have a / (slash) after the . (dot).
The blockHashMake program generates the block hash file. The contents of a block hash file can be looked at and read using the blockHashRead program. See the man pages blockHashMake (1) and blockHashRead (1) for more details.
Block hash files have wildcard support π For example, if "example.com" is in the block hash file, then deadwood will block "example.com", "anyname.example.com", "anything.else.example.com", "12345.example.com", and so on.
Note that wildcards only work for domain names which are one, two, or three labels long in the database. If "really.bad.example.com" is in the database, "buzz.really.bad.example.com" will not match, since "really.bad.example.com" has four (i.e. more than three) labels. the math is mathing π
One usable block hash file is available at the repo at https://github.com/samboy/BlockHash
β¨ cache_file β¨
This is the filename of the file used for reading and writing the cache to disk; this string can have lowercase letters, the - symbol, the _ symbol, and the / symbol (for putting the cache in a subdirectory). All other symbols become a _ symbol.
This file is read and written as the user Deadwood runs as.
β¨ chroot_dir β¨
This is the directory the program will run from.
β¨ deliver_all β¨
This affects behavior in Deadwood 2.3, but has no effect in Deadwood 3. This variable is only here so Deadwood 2 rc files can run in Deadwood 3. (legacy queen, she stays for compatibility π )
β¨ dns_port β¨
This is the port Deadwood binds to and listens on for incoming connections. The default value for this is the standard DNS port:
53
β¨ filter_rfc1918 β¨
When this has a value of 1, a number of different IP ranges are not allowed to be in DNS A replies:
192.168.x.x172.[16-31].x.x10.x.x.x127.x.x.x169.254.x.x224.x.x.x0.0.x.x
If one of the above IPs is detected in a DNS reply, and filter_rfc1918 has a value of 1, Deadwood will return a synthetic "this host does not reply" response (a SOA record in the NS section) instead of the A record.
The reason for this is to provide a "dnswall" that protects users from some kinds of attacks, as described at http://crypto.stanford.edu/dns/
Please note that Deadwood only provides IPv4 "dnswall" functionality and does not help protect against IPv6 answers. If protection against certain IPv6 AAAA records is needed, either disable all AAAA answers by setting reject_aaaa to have a value of 1, or use an external program to filter undesired IPv4 answers (such as the dnswall program).
The default value for this is 1.
β¨ handle_noreply β¨
When this is set to 0, Deadwood sends no reply back to the client (when the client is a TCP client, Deadwood closes the TCP connection) when a UDP query is sent upstream and the upstream DNS never sends a reply. π
When this is set to 1, Deadwood sends a SERVER FAIL back to the client when a UDP query is sent upstream and the upstream DNS never sends a reply.
The default value for this is 1.
β¨ handle_overload β¨
When this has a value of 0, Deadwood sends no reply when a UDP query is sent and the server is overloaded (has too many pending connections); when it has a value of 1, Deadwood sends a SERVER FAIL packet back to the sender of the UDP query. The default value for this is 1.
β¨ hash_magic_number β¨
This used to be used for Deadwood's internal hash generator to keep the hash generator somewhat random and immune to certain types of attacks. In Deadwood 3.0, entropy for the hash function is created by looking at the contents of /dev/urandom (CryptGenRandom on Windows machines) and the current timestamp. This parameter is only here so older configuration files do not break in Deadwood 3.0. (she's a nostalgic little ghost π)
β¨ ip4 β¨
This is a dictionary variable which allows us to have given names resolve to bogus IPv4 addresses. Here, we have the name "maradns.foo" resolve to "10.10.10.10" and "kabah.foo" resolve to "10.11.11.11", regardless of what real values these DNS records may have:
ip4 = {}
ip4["maradns.foo."] = "10.10.10.10"
ip4["kabah.foo."] = "10.11.11.11"
Note that a given name can only resolve to a single IP, and that the records have a fixed TTL of 30 seconds.
It is also possible to use ip4 to set up a blocklist by using "X" for the IP. When this is done, an IPv4 request for a given hostname results in a synthetic "this name does not exist" response. In addition, the corresponding IPv6 request will also return that "name does not exist" reply. For example:
ip4 = {}
ip4["evil.example.com."] = "X"
Here, both the IPv4 and the IPv6 query for "evil.example.com" will not resolve in Deadwood. bye felicia π
β¨ ip6 β¨
Like ip4, ip6 uses a similar syntax to have bogus IPv6 addresses. We don't use standard notation for IPv6 addresses. Instead, we use 32-character hex addresses (case insensitive); to make it easier to count long strings of "0"s, the "_" acts like a 0; we also ignore "-" (dash) and " " (space) in ip6 strings. Here is an example:
ip6 = {}
ip6["maradns.foo."] = "20010db84d617261444e530000001234"
ip6["kabah.foo."] = "2001-0DB8-4D61-7261 444E-5300-__00-2345"
β¨ ip_blocklist β¨
This is a list of IPs that we do not allow to be in the answer to a DNS request. The reason for this is to counteract the practice some ISPs have of converting a "this site does not exist" DNS answer in to a page controlled by the ISP; this results in possible security issues. π€
This parameter only accepts individual IPs, and does not use netmasks.
Note that this parameter used to be called ip_blacklist; while the ip_blacklist name still works as before, ip_blocklist is the current name. (glow-up moment β¨)
β¨ maradns_uid β¨
(this one continues in part 2, bestie β don't go anywhere π)
Okay so here's the deal: this is the user-id Deadwood runs as, and it can be any number between 10 and 16777216. Default? 707 (a system UID which should be unused, so like, nobody's turf π). Oh and heads up β this value is not used on Windows systems.
maradns_gidβ the group-id Deadwood runs as (yes bestie they're a matched set π ). Any number between10and16777216works, and the default is707. Same deal as above: not used on Windows systems.max_ar_chainβ the "are we doing resource record rotation" switch. If it's1, rotation is on. Anything else and it's off.
Rotation is usually what you want, because it lets DNS act like a crude little load balancer, which is honestly kind of iconic. But on heavily loaded systems it may be desirable to disable it, just to reduce CPU usage. Trade-offs, bestie. π
Why is the name so weird? Because it's kept that way for compatibility with MaraDNS mararc files. Blame history. π«Ά
Default value: 1 β resource record rotation enabled.
max_inflightsβ the maximum number of simultaneous clients we process at the same time for the same query.
Here's the vibe: if, while processing a query for, say, "example.com.", another DNS client sends Deadwood another query for example.com, instead of creating a new query to process example.com, Deadwood will attach the new client to the same query that is already "in flight", and send a reply to both clients once we have an answer for example.com. Teamwork!! π€
So this is the number of simultaneous clients a given query can have. Exceed the limit and subsequent clients with the same query are refused until an answer is found. If this has a value of 1, we do not merge multiple requests for the same query, but give each request its own connection.
Default value: 8.
max_ttlβ the maximum amount of time we will keep an entry in the cache, in seconds. Also called "Maximum TTL". This is the longest we will keep an entry cached.
Default value: 86400 (one day πΈ). Minimum value: 300 (5 minutes). Maximum value this can have: 7776000 (90 days).
Why is this parameter here? To protect Deadwood from attacks which exploit there being stale data in the cache, like the "Ghost Domain Names" attack. π» Not today.
maximum_cache_elementsβ the maximum number of elements our cache is allowed to have. A number between32and16,777,216, with a default value of1024. Note that, if writing the cache to disk or reading the cache from disk, higher values of this will slow down cache reading/writing. Just so you know.
The amount of memory each cache entry uses is variable, depending on the operating system used and the size of memory allocation pages assigned. In Windows XP, for example, each entry uses approximately four kilobytes of memory and Deadwood has an overhead of approximately 512 kilobytes. So, if there are 512 cache elements, Deadwood uses approximately 2.5 megabytes of memory; if there are 1024 cache elements, Deadwood uses approximately 4.5 megabytes of memory. Again, these numbers are for Windows XP and other operating systems will have different memory allocation numbers.
Also: as of Deadwood 3.5.0004, it is no longer needed to increase maximum_cache_elements to store upstream_server and root_server entries. Growth! β¨
maxprocsβ the maximum number of pending remote UDP connections Deadwood can have. Default value:1024.max_tcp_procsβ the number of allowed open TCP connections. Default value:8.min_ttlβ the minimum amount of time we will keep an entry in the cache, in seconds. Also called "Minimum TTL". Short entry, short TTL, it's giving symmetry. πnum_retriesβ the number of times we retry to send a query upstream before giving up. If this is0, we only try once; if this is1, we try twice, and so on, up to32retries. Note that each retry takestimeout_secondsseconds before we retry again. Default value:5.ns_glueless_typeβ the RR type we send to resolve glueless records. This should always be1(A; i.e. IPv4 DNS servers). This should never beANY, see RFC8482. And it should not be any other value either, since only A glueless NS referrals have ever been tested with Deadwood. π¨
Why does this exist? Because, often times in DNS, we get a reply like "The name server for this foo.example.com and no I do not have the IP for foo.example.com" when recursively solving an answer. So the question is this: is foo.example.com an IPv4 DNS server, an IPv6 server, or both?
On today's internet (mid-2020, during the COVID-19 crisis), the answer is that the name server in question is only on the IPv4 Internet. IPv6 is now mainstream (e.g. my ISP gives me a /64 and I no longer have to tunnel through he.net to try out IPv6), but most servers are still IPv4 only (e.g. my domains are only on IPv4, and amazon.com does not have an IPv6 address).
The reason this parameter exists is because, when I was writing the recursive code for Deadwood, I was thinking of a future where IPv6 is prevalent enough that we would have DNS servers with only IPv6 addresses, and glueless NS referrals (the "foo.example.com" case above) would point to servers with IPv6, but not IPv4, addresses.
That day may yet come, but preparing Deadwood to still be a viable DNS server when that day comes will require more than changing the RR type sent when it gets a glueless NS referral.
random_seed_fileβ this is a file that contains random numbers, and it's used as a seed for the cryptographically strong random number generator. Deadwood will try to read256bytes from this file (the RNG Deadwood uses can accept a stream of any arbitrary length).
Note that the hash compression function obtains some of its entropy before parsing the mararc file, and is hard-coded to get entropy from /dev/urandom (CryptGenRandom on Windows systems). Most other entropy used by Deadwood comes from the file pointed to by random_seed_file. Randomness sourcing is a whole thing. π²
recurse_min_bind_portβ the lowest numbered port Deadwood is allowed to bind to; this is a random port number used for the source port of outgoing queries, and it is not53(seedns_portabove). It's a number between1025and32767, and the default value is15000. This is used to make DNS spoofing attacks more difficult. π₯recurse_number_portsβ the number of ports Deadwood binds to for the source port for outgoing connections; this is a power of 2 between256and32768. Also used to make DNS spoofing attacks more difficult. Default value:4096.recursive_aclβ a list of who is allowed to use Deadwood to perform DNS recursion, in"ip/mask"format. Mask must be a number between0and32(for IPv6, between0and128). For example,"127.0.0.1/8"allows local connections. πreject_aaaaβ if this has a value of1, a bogus SOA "not there" reply is sent whenever an AAAA query is sent to Deadwood. In other words, every time a program asks Deadwood for an IPv6 IP address, instead of trying to process the request, Deadwood pretends the host name in question does not have an IPv6 address. π
This is useful for people who aren't using IPv6 but use applications (usually *NIX command like applications like "telnet") which slow things down trying to find an IPv6 address.
Default value: 0. In other words, AAAA queries are processed normally unless this is set.
reject_mxβ when this has the default value of1, MX queries are silently dropped with their IP logged. A MX query is a query that is only done by a machine if it wishes to be its own mail server sending mail to machines on the internet. This is a query an average desktop machine (including one that uses Outlook or another mail user agent to read and send email) will never make.
Most likely, if a machine is trying to make a MX query, the machine is being controlled by a remote source to send out undesired "spam" email. This in mind, Deadwood will not allow MX queries to be made unless reject_mx is explicitly set with a value of 0.
Before disabling this, please keep in mind that Deadwood is optimized to be used for web surfing, not as a DNS server for a mail hub. In particular, the IPs for MX records are removed from Deadwood's replies and Deadwood needs to perform additional DNS queries to get the IPs corresponding to MX records, and Deadwood's testing is more geared for web surfing (almost 100% A record lookup) and not for mail delivery (extensive MX record lookup).
reject_ptrβ if this has a value of1, a bogus SOA "not there" reply is sent whenever a PTR query is sent to Deadwood. In other words, every time a program asks Deadwood for "reverse DNS lookup" β the hostname for a given IP address β instead of trying to process the request, when this is set to1, Deadwood pretends the IP address in question does not have a hostname.
This is useful for people who are getting slow DNS timeouts when trying to perform a reverse DNS lookups on IPs.
Default value: 0. In other words, PTR queries are processed normally unless this is set.
resurrectionsβ if this is set to1, Deadwood will try to send an expired record to the user before giving up. If it is0, we don't. Default value:1. Zombie records, we love a comeback. πrfc8482β if this is set to1, Deadwood will not allowANYorHINFOqueries, sending a RFC8482 response if one is given to Deadwood. If this is0,ANYandHINFOqueries are allowed. Default value:1.
Oh, and if ANY queries are enabled: since Deadwood does not support EDNS nor DNS-over-TCP for upstream queries, Deadwood may not get meaningful replies from upstream servers. So like... good luck with that. π
root_serversβ > β οΈ this parameter is deprecated, bestie. There are no plans to remove it, but Deadwood is no longer being updated to resolve DNS resolution issues when usingroot_serversto resolve names on the internet. In addition, Deadwood's recursive resolver uses only IPv4 and doesn't use IPv6 (or DNS-over-TCP nor EDNS) to solve names recursively. Please useupstream_serversinstead.
This is a list of root servers; its syntax is identical to upstream_servers (see below). This is the type of DNS service ICANN, for example, runs. These are servers used that do not give us complete answers to DNS questions, but merely tell us which DNS servers to connect to to get an answer closer to our desired answer.
As of Deadwood 3.5.0004, it is no longer needed to increase maximum_cache_elements to store root_server entries.
source_ip4β with certain complicated networks, it may be desirable to set the source IP of queries sent to upstream or root DNS servers. If so, set this parameter to have the dotted decimal IPv4 address to use when sending IPv4 queries to an upstream DNS server.
Use this parameter with caution; Deadwood can very well become non-functional if one uses a source IPv4 address which Deadwood is not bound to. π« You have been warned.
tcp_listen
To turn DNS-over-TCP on, this variable has to be set, and it has to have a value of 1. Default value: 0. Periodt. π
timeout_seconds β³
This is how long Deadwood will sit there waiting before it gives up and discards a pending UDP DNS reply. The default value for this is 1, as in one whole second, unless Deadwood was compiled with FALLBACK_TIME enabled.
timeout_seconds_tcp π’
How long to wait on an idle TCP connection before dropping it. The default value for this is 4, as in 4 seconds.
ttl_age π
Whether TTL aging is enabled β like, whether entries in the cache get their TTLs set to be the amount of time the entries have left in the cache.
If this has a value of 1, TTL entries are aged. Otherwise, they are not. The default value for this is 1.
upstream_port πͺ
This is the port Deadwood uses to connect or send packets to the upstream servers. The default value for this is 53; the standard DNS port.
upstream_servers πΊοΈ
This is a list of DNS servers that the load balancer will try to contact. Heads up bestie: this is a dictionary variable (an array indexed by a string instead of by a number) instead of a simple variable. And since upstream_servers is a dictionary variable, it needs to be initialized before being used.
Deadwood will look at the name of the host that it is trying to find the upstream server for, and will match against the longest suffix it can find. π
For example, if someone sends a query for "www.foo.example.com" to Deadwood, Deadwood will first see if there is an upstream_servers variable for "www.foo.example.com.", then look for "foo.example.com.", then look for "example.com.", then "com.", and finally ".".
Here is an example of upstream_servers:
upstream_servers = {} # Initialize dictionary variable
upstream_servers["foo.example.com."] = "192.168.42.1"
upstream_servers["example.com."] = "192.168.99.254"
upstream_servers["."] = "10.1.2.3, 10.1.2.4"
In this example, anything ending in "foo.example.com" is resolved by the DNS server at 192.168.42.1; anything else ending in "example.com" is resolved by 192.168.99.254; and anything not ending in "example.com" is resolved by either 10.1.2.3 or 10.1.2.4.
Important: the domain nameupstream_serverspoints to must end in a"."character. π
This is OK:
upstream_servers["example.com."] = "192.168.42.1"
But this is not OK:
upstream_servers["example.com"] = "192.168.42.1"
The reason for this is because BIND engages in unexpected behavior when a host name doesn't end in a dot, and by forcing a dot at the end of a hostname, Deadwood doesn't have to guess whether the user wants BIND's behavior or the "normal" behavior.
If neither root_servers nor upstream_servers are set, Deadwood sets upstream_servers to use the https://quad9.net servers, as follows:
9.9.9.9
149.112.112.112
Please note that, as of Deadwood 3.5.0004, it is no longer needed to increase maximum_cache_elements to store upstream_server entries. β¨
verbose_level π’
This determines how many messages are logged on standard output; larger values log more messages. The default value for this is 3.
πΈ ip/mask format of IPs πΈ
Deadwood uses a standard ip/netmask format to specify IPs. An ip is in dotted-decimal format, e.g. "10.1.2.3" (or in IPv6 format when IPv6 support is compiled in).
The netmask is used to specify a range of IPs. The netmask is a single number between 1 and 32 (128 when IPv6 support is compiled in), which indicates the number of leading "1" bits in the netmask.
10.1.1.1/24indicates that any ip from10.1.1.0to10.1.1.255will match. β¨10.2.3.4/16indicates that any ip from10.2.0.0to10.2.255.255will match. β¨127.0.0.0/8indicates that any ip with "127" as the first octet (number) will match. β¨
The netmask is optional, and, if not present, indicates that only a single IP will match.
π¦ DNS over TCP π¦
DNS-over-TCP needs to be explicitly enabled by setting tcp_listen to 1.
Deadwood extracts useful information from UDP DNS packets marked truncated which almost always removes the need to have DNS-over-TCP. However, Deadwood does not cache DNS packets larger than 512 bytes in size that need to be sent using TCP. In addition, DNS-over-TCP packets which are "incomplete" DNS replies (replies which a stub resolver can not use, which can be either a NS referral or an incomplete CNAME reply) are not handled correctly by Deadwood.
Deadwood has support for both DNS-over-UDP and DNS-over-TCP; the same daemon listens on both the UDP and TCP DNS port.
Only UDP DNS queries are cached. Deadwood does not support caching over TCP; it handles TCP to resolve the rare truncated reply without any useful information or to work with very uncommon non-RFC-compliant TCP-only DNS resolvers. In the real world, DNS-over-TCP is almost never used. π
π Parsing other files π
It is possible to have Deadwood, while parsing the dwood3rc file, read other files and parse them as if they were dwood3rc files.
This is done using execfile. To use execfile, place a line like this in the dwood3rc file:
execfile("path/to/filename")
Where path/to/filename is the path to the file to be parsed like a dwood3rc file.
All files must be in or under the directory /etc/deadwood/execfile. Filenames can only have lower-case letters and the underscore character ("_"). Absolute paths are not allowed as the argument to execfile; the filename can not start with a slash ("/") character.
If there is a parse error in the file pointed to by execfile, Deadwood will report the error as being on the line with the execfile command in the main dwood3rc file. To find where a parse error is in the sub-file, use something like "Deadwood -f /etc/deadwood/execfile/filename" to find the parse error in the offending file, where "filename" is the file to be parsed via execfile. π΅οΈ
π IPV6 support π
This server can also be optionally compiled to have IPv6 support. In order to enable IPv6 support, add '-DIPV6' to the compile-time flags. For example, to compile this to make a small binary, and to have IPv6 support:
export FLAGS='-Os -DIPV6'
make
π SECURITY π
Deadwood is a program written with security in mind. π«Ά
In addition to use a buffer-overflow resistant string library and a coding style and SQA process that checks for buffer overflows and memory leaks, Deadwood uses a strong pseudo-random number generator (The 32-bit version of RadioGatun) to generate both the query ID and source port. For the random number generator to be secure, Deadwood needs a good source of entropy; by default Deadwood will use /dev/urandom (CryptGenRandom in Windows) to get this entropy. If you are on a system without /dev/urandom support, it is important to make sure that Deadwood has a good source of entropy so that the query ID and source port are hard to guess (otherwise it is possible to forge DNS packets). π
Note that Deadwood is not protected from someone on the same network viewing packets sent by Deadwood and sending forged packets as a reply.
To protect Deadwood from certain possible denial-of-service attacks, it is best if Deadwood's prime number used for hashing elements in the cache is a random 31-bit prime number. The program RandomPrime.c generates a random prime that is placed in the file DwRandPrime.h that is regenerated whenever either the program is compiled or things are cleaned up with make clean. This program uses /dev/urandom for its entropy; the file DwRandPrime.h will not be regenerated on systems without /dev/urandom.
On systems without direct /dev/urandom support, it is suggested to see if there is a possible way to give the system a working /dev/urandom. This way, when Deadwood is compiled, the hash magic number will be suitably random. β¨
If using a precompiled binary of Deadwood, please ensure that the system has /dev/urandom support (on Windows system, please ensure that the file with the name secret.txt is generated by the included mkSecretTxt.exe program); Deadwood, at runtime, uses /dev/urandom (secret.txt in Windows) as a hardcoded path to get entropy (along with the timestamp) for the hash algorithm.
π¬ COMMENTS π¬
Deadwood's configuration file format supports two kinds of comments:
# This is a comment
Here, a comment starts with the # character and continues until the end of the line. In some circumstances, a comment can start after a variable is set, for example:
bind_address="127.0.0.1" # IP we bind to
The second comment type supports multi-line comments. For example:
_rem={}
_rem={ #_rem --[=[
"""
We are now in a multi-line comment.
This allows a long explanation to be
in a Deadwood configuration file
""" # ]=]
}
The actual format is _rem={ at the start of a line, which begins a multi-line comment. The comment continues until a } is seen. The reason for this unusual format is that it allows a Deadwood configuration file to have multi-line comments in a form which are compatible with both Lua and Python, as can be seen in the above example. π
π΄ DAEMONIZATION π΄
Deadwood does not have any built-in daemonization facilities; this is handled by the external program Duende or any other daemonizer.
π Example configuration file π
bestie, nothing makes a config file click like seeing one fully written out, so here's a whole example dwood3rc file π read it top to bottom and you've basically absorbed the entire format, no cap:
# This is an example deadwood rc file
# Note that comments are started by the hash symbol
bind_address="127.0.0.1" # IP we bind to
# The following line is disabled by being commented out
#bind_address="::1" # We have optional IPv6 support
# Directory we run program from (not used in Win32)
chroot_dir = "/etc/deadwood"
# The following upstream DNS servers are Google's
# (as of 2026) public DNS servers. For
# more information, see the page at
# https://developers.google.com/speed/public-dns/
#upstream_servers = {}
#upstream_servers["."]="8.8.8.8, 8.8.4.4"
# If neither root_servers nor upstream_servers are set,
# Deadwood will use the Quad Nine upstream servers, as
# per https://quad9.net/
#upstream_servers = {}
#upstream_servers["."]="9.9.9.9, 149.112.112.112"
# Who is allowed to use the cache. This line
# allows anyone with "127.0" as the first two
# digits of their IP to use Deadwood
recursive_acl = "127.0.0.1/16"
# Maximum number of pending requests
maxprocs = 2048
# Send SERVER FAIL when overloaded
handle_overload = 1
maradns_uid = 99 # UID Deadwood runs as
maradns_gid = 99 # GID Deadwood runs as
maximum_cache_elements = 60000
# If you want to read and write the cache from disk,
# make sure chroot_dir above is readable and writable
# by the maradns_uid/gid above, and uncomment the
# following line.
#cache_file = "dw_cache"
# If your upstream DNS server converts "not there" DNS replies
# in to IPs, this parameter allows Deadwood to convert any reply
# with a given IP back in to a "not there" IP. If any of the IPs
# listed below are in a DNS answer, Deadwood converts the answer
# in to a "not there"
#ip_blocklist = "10.222.33.44, 10.222.3.55"
# By default, for security reasons, Deadwood does not allow IPs in
# the 192.168.x.x, 172.[16-31].x.x, 10.x.x.x, 127.x.x.x,
# 169.254.x.x, 224.x.x.x, or 0.0.x.x range. If using Deadwood
# to resolve names on an internal network, uncomment the
# following line:
#filter_rfc1918 = 0
π BUGS π
okay so this is the part where Deadwood is honest about its little quirks π«Ά no shame, just facts. every single one of these is canon:
- The TC (truncated) bit thing β Deadwood does not follow RFC2181's advice to ignore DNS responses with the TC (truncated) bit set. Instead it extracts the first RR. if that's not the vibe you want, set the undocumented parameter
truncation_hackto0β but fr fr, go read the DNS over TCP section of this man page first π. - Record types numbered
65392through65407? nope, Deadwood can not process those. These RR types are marked by the IANA for "private use", and Deadwood reserves these record types for internal use. honestly? it's only 16 record types out of the 65536 possible DNS record types (and only 71 have actually been assigned by IANA, so this is a non-issue in the real world π). ANYandHINFOrequests β by default, Deadwood will respond to both of them with a RFC8482 compliant packet instead of trying to resolve the record. iconic, tbh β¨.- ASCII control characters in DNS names β it is not clear whether the DNS RFCs even allow ASCII control characters in DNS names. Even if they were allowed, Deadwood does not allow ASCII control characters (bytes with a value less then 32) in DNS names. Other characters (UTF-8, etc.) are allowed π .
- CNAME + other records, the messy one β combining a CNAME record with other records is prohibited in RFC1034 section 3.6.2 and RFC1912 section 2.4; it makes an answer ambiguous π. Deadwood handles this ambiguity differently than some other DNS servers.
βοΈ LEGAL DISCLAIMER βοΈ
bestie I am not paraphrasing this one. lawyers are the ultimate vibe check, so here it is word-for-word, no edits, no flourishes:
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
π AUTHORS π
- Sam Trenholme (
http://www.samiam.org) is responsible for this program and this man page. yes, both. main character energy, lowkey deserved ππ - and he appreciates all of Jean-Jacques Sarton's help giving this program IPv6 support. every single bit of it π¦
and that's the whole page, bestie π«Ά this was DEADWOOD(1), source DEADWOOD, dated August 2009. go forth and resolve responsibly π
β¨πΈ
π¦ where this page comes from
- fedora 44: maradns 3.5.0039-1.fc44 Β· BSD-2-Clause
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms