tinydns 1 user commands djbwares
tinydns a general-purpose content DNS server using the UDP protocol
`tinydns`

## Description

`tinydns` is a content DNS server that speaks the DNS/UDP protocol. It accepts DNS queries from hosts around the Internet, and responds with locally configured information from a static database. It runs in a system-secured environment and requires no privileges nor any filesystem access other than read access to its static database. It logs a record of its operation simply to its standard error.

`tinydns` respects a location code system encoded in its database and differentiates amongst requesting clients according to their locations, determined by their IP addresses. It is designed to be Internet-facing; and its normal use is for answering Internet DNS queries from hosts around the Internet. It can also be employed locally on a LAN, or even locally within a single machine, for providing information to hosts on an intranet.

It is possible to run multiple entirely isolated instances on a single machine, each with their own static databases and listening on particular IP addresses for different purposes. It is conversely possible to run multiple instances on a single machine, each listening on particular IP addresses, all sharing a single database.

Normally `tinydns` is run via a server program such as `udp-socket-listen` to listen for DNS/UDP queries. It understands the `LISTEN_PID` and `LISTEN_FDS` environment variable convention for having an already-listening socket passed to it by such a program, and uses the last open file descriptor in the list that refers to a UDP/IPv4 socket. If no such open file descriptor is provided it falls back to opening its own UDP/IPv4 socket, bound to port 53 of the IP address given by the value of the `IP` environment variable. It does not handle DNS/TCP.

`tinydns` rejects (sending a reply with an error code) zone-transfer requests, inverse queries, and packets that contain anything other than a single query. It does not answer (single) non-Internet-class queries, or truncated packets.

### Answers

`tinydns` answers queries as specified by `data.cdb`, a binary file in its root directory created by tinydns-data 1. It does not write to this file, or attempt to create it.

`tinydns` supports clients that negotiate large DNS/UDP response packet sizes with EDNS0. When it has to truncate responses, when the conventional/EDNS0-negotiated response size is not large enough, it truncates all answer, authority, and additional section resource records.

`tinydns` includes `NS` records with answers to most queries. This increases DNS packet sizes, but it draws queries away from parent servers, and reduces the frequency of long DNS delays. With the default cache times, a client that uses a normal record at least once every day will always have the corresponding `NS` records cached and will never have to talk to parent servers.

If a record set has ending time ("time to die") for the information; `tinydns` dynamically adjusts the TTLs that it publishes so that the records are not cached for more than a few seconds past the ending time.

SOA resource records inform `tinydns` what requests to answer. It will only answer at all for domain names where there is a `SOA` resource record at or above that domain name in the namespace.

There can be many `SOA` resource records for a domain, as the result of many `.` lines in the source data file. `tinydns` will return only one `SOA` record per domain when the request is actually for a domain's `SOA` resource record set.

`NS` resource records inform `tinydns` about delegation points (when they are not accompanied by `SOA` resource records). It will always answer with a delegation response for domain names at or below a delegation point in the namespace.

`tinydns` returns IP addresses (i.e. `A` or `AAAA` records generated from `+` or `=` or `@` or `.` or `&` lines in the source data file) in a random order in the answer section. If there are more than 8 records, it returns a random list of 8. (People used to use this as a mechanism for spreading server load across multiple machines; albeit that this was highly flawed, for several reasons.)

### Wildcards

`tinydns` supports wildcards of the form `*.fqdn`. Information for `*.fqdn` is provided for every domain name ending with `.fqdn`, except names that have their own records and names that are covered by more specific wildcards.

For example, the lines (as written in the original database source file)

    +pink.floyd.u.heaven.af.example:203.0.113.4
    +*.u.heaven.af.example:203.0.113.200

have the same effect as

    +pink.floyd.u.heaven.af.example:203.0.113.4
    +joe.u.heaven.af.example:203.0.113.200
    +bill.u.heaven.af.example:203.0.113.200
    +floyd.u.heaven.af.example:203.0.113.200
    +ishtar.u.heaven.af.example:203.0.113.200
    +joe.bob.u.heaven.af.example:203.0.113.200
    +sally.floyd.u.heaven.af.example:203.0.113.200
    +post.pink.floyd.u.heaven.af.example:203.0.113.200

and so on.

As another example, the lines

    +pink.floyd.u.heaven.af.example:203.0.113.4
    @*.u.heaven.af.example::mail.heaven.af.example

have the same effect as

    +pink.floyd.u.heaven.af.example:203.0.113.4
    @joe.u.heaven.af.example::mail.heaven.af.example
    @bill.u.heaven.af.example::mail.heaven.af.example
    @floyd.u.heaven.af.example::mail.heaven.af.example
    @ishtar.u.heaven.af.example::mail.heaven.af.example
    @joe.bob.u.heaven.af.example::mail.heaven.af.example
    @sally.floyd.u.heaven.af.example::mail.heaven.af.example
    @post.pink.floyd.u.heaven.af.example::mail.heaven.af.example

and so on.

Notice that the wildcard does not apply to `pink.floyd.u.heaven.af.example`, because that name has its own records.

## Security and privacy

When it starts `tinydns` changes its root to the directory specified by the `ROOT` environment variable, and drops privileges to run as the user ID and group ID specified by the `UID` and `GID` environment variables. The latter can be set up with envuidgid 1.

`ANY` queries used to be used by a few mail systems as a shortcut for performing `A` and `MX` queries in one go, although were never guaranteed to work that way, it just being an accident of implementation of ISC BIND in the 1990s. They are nowadays, instead, a common attack on the Domain Name System; as documented in RFC8482 in January 2019. `tinydns` does not return any data other than `CNAME`s from the data file in response to an `ANY` query. If the domain name exists and has no `CNAME`s, they are answered with a single synthesized `HINFO` record.

`tinydns` has always minimized other "amplification" attacks, where a client falsifies its reply IP address to direct responses to a third party, or asks about third parties in order to generate back-end query resolution traffic to those third parties. When there is no `SOA` resource record at or above a queried domain name, `tinydns` simply sends no response at all. And it neither does query resolution, nor has a back end where it performs any kind of transaction with another server.

Sending no response at all to non-Internet-class queries is a privacy measure. ISC's BIND made this into a way to fingerprint DNS servers by responding with synthetic internal program version information to `TXT` type queries in the CHAOS class domain names such as `version.bind`. Others even extended this into a more generic `version.server` domain name. `tinydns` never imitated this; and has never given out internal version information.

ChaosNet was a short-lived Local Area Network protocol at MIT in the 1970s; and BIND simply repurposed what had by the late 1980s become a defunct query class. The only other actually assigned non-Internet query class, in the 21st century, is Hesiod. The only use of non-Internet query classes in the wild is for fingerprinting people's versions of ISC's BIND, Microsoft's DNS server, Knot DNS, PowerDNS, et al..

`tinydns` can be used for providing a private copy of the DNS "root", or indeed any other, data for reducing query traffic that goes off-organization, off-LAN, or even off-machine. This is just a matter of obtaining those data, which are officially published for such use by several domain owners including the ICANN root, removing any overlaps/duplications of other data, and incorporating them into the static database file. It is in fact the very same process as providing "secondary" service for a domain, sans the step of listing the `tinydns` instance as one of the servers for the domain in a `.` record in the database.

For best results, such data should be tagged with a location code that limits their visibility to only hosts within the organization/LAN, or to the local machine; or the instance of `tinydns` should not be listening on an Internet-routable IP address. `tinydns` does not leak location-tagged data. Answers given to clients in one location are not affected by the presence of data tagged for another location.

More specifically: If `tinydns` has a location-tagged copy of the DNS "root" for on-intranet/LAN/machine use, this will not cause it to therefore answer all queries from off-intranet/LAN/machine clients just because there is a SOA resource record set for the `.` domain name in the database. A single instance of `tinydns` can serve a private "root" to one set of locations whilst still being Internet-facing.

## History

`tinydns` was originally part of Daniel J. Bernstein's djbdns toolset in 1999. It incorporated the functionality of pickdns 1, rendering that obsolete, in 2001.

`tinydns` ceased responding in the old style to `ANY` queries in March 2019. It ceased similarly treating the `ANY` class (as opposed to type) as a wildcard in July 2025. It ceased responding to non-Internet-class queries in August 2025; prior to which it replied with an error response.

`tinydns` gained EDNS0 capability in 2025.

## Author

Original code and documentation by Daniel J. Bernstein. Documentation modernizations by Jonathan de Boyne Pollard.