<?xml version="1.0" encoding="UTF-8"?>
<!-- **************************************************************************
.... For copyright and licensing terms, see the file named COPYING.
.... **************************************************************************
.-->
<?xml-stylesheet href="docbook-xml.css" type="text/css"?>

<refentry id="dnscache">

<refmeta xmlns:xi="http://www.w3.org/2001/XInclude">
<refentrytitle>dnscache</refentrytitle>
<manvolnum>1</manvolnum>
<refmiscinfo class="manual">user commands</refmiscinfo>
<refmiscinfo class="source">djbwares</refmiscinfo>
<xi:include href="version.xml" />
</refmeta>

<refnamediv>
<refname>dnscache</refname>
<refpurpose>a caching proxy DNS server</refpurpose>
</refnamediv>

<refsynopsisdiv>
<cmdsynopsis>
<command>dnscache</command>
</cmdsynopsis>
</refsynopsisdiv>

<refsection>
<title>Description</title>

<para>
<command>dnscache</command> is a proxy DNS server that speaks the DNS/UDP and DNS/TCP protocols.
It accepts DNS queries from local programs (clients such as web browsers and mail transfer agents with DNS client libraries in them), sends queries of its own to hosts around the Internet, takes the responses that it receives and combines them into answers that it then sends back to the local clients.
It caches the responses that it receieves, to save time later when it is asked the same or related questions again.
</para>

<para>
When it starts <command>dnscache</command> changes its root to the directory specified by the <envar>ROOT</envar> environment variable, and drops privileges to run as the user ID and group ID specified by the <envar>UID</envar> and <envar>GID</envar> environment variables.
The latter can be set up with <citerefentry><refentrytitle>envuidgid</refentrytitle><manvolnum>1</manvolnum></citerefentry>.
</para>

</refsection>

<refsection>
<title>Client-facing front end</title>

<refsection>
<title>Listening addresses</title>

<para>
Normally <command>dnscache</command> is run via server programs such as <command>udp-socket-listen</command> and <command>tcp-socket-listen</command> to listen for DNS/UDP and DNS/TCP queries on an appropriate IP address.
It understands the <envar>LISTEN_PID</envar> and <envar>LISTEN_FDS</envar> environment variable convention for having already-listening sockets passed to it by such programs, and uses the last open file descriptors in the list that refer to a UDP/IPv4 socket and a TCP/IPv4 socket.
If no such open file descriptors are provided it falls back to opening its own UDP/IPv4 and TCP/IPv4 sockets, bound to port 53 of the IP address given by the value of the <envar>IP</envar> environment variable. 
If just one is provided, it falls back for the other.
</para>

<para>
Typically the IP address is a non-routable machine-local or link-local one such as 127.0.0.1.
It can also be a public IP address, providing this service to other machines.
To control what other machines that is, there is an access control mechanism.
<command>dnscache</command> discards UDP packets or TCP connections from IP address 203.0.113.4 unless it sees a file named <filename>ip/203.0.113.4</filename> or <filename>ip/203.0.113</filename> or <filename>ip/203.0</filename> or <filename>ip/203</filename>.
A proper firewall is a more efficient mechanism for preventing client access, especially for DNS/TCP, however.
</para>
<caution>
This access control mechanism will change in a non-backwards compatible way when <command>dnscache</command> becomes capable of listening to IPv6 clients in a future release.
</caution>

</refsection>

<refsection>
<title>Responses to clients</title>

<para>
<command>dnscache</command>'s responses are generally much smaller than BIND's responses. 
They do not include authority records (NS records of the source name servers and <code>SOA</code> records for negative answers) or additional records (A records relevant to NS or MX records). 
When the answer section is truncated by UDP length limits, it is eliminated entirely.
</para>

<para>
<command>dnscache</command> tries to prevent local users from snooping on other local users. 
It discards non-recursive queries; it discards inverse queries; and it discards zone-transfer requests. 
It responds to <code>ANY</code> and <code>OPT</code> queries with a single synthesized <code>HINFO</code>  resource record set.
If the <envar>HIDETTL</envar> environment variable is set, <command>dnscache</command> always uses a TTL of 0 in its responses.
Normally, it preserves the (current remaining) TTL, so that other proxies can use it as an upstream server.
</para>

<para>
According to RFC 1035, the AA bit "specifies that the responding name server is an authority for the domain name in question section". 
<command>dnscache</command> is not an authority for any domain names. 
<command>dnscache</command> never sets the AA bit (except in NXDOMAIN responses, as required by RFC 2308, to work around a common client bug). 
</para>

</refsection>

</refsection>

<refsection>
<title>Resources, query resoution, and caching</title>

<refsection>
<title>Resource use limits</title>

<para>
<command>dnscache</command> uses a fixed-size table, under 256K, to keep track of as many as 200 simultaneous UDP queries and 20 simultaneous TCP connections. 
It also dynamically allocates memory, usually just a few bytes but occasionally much more, for each active query. 
If it runs out of memory handling a query, it discards that query.
</para>

<para>
<command>dnscache</command> asks the operating system to reserve a 128K buffer for bursts of incoming UDP queries. 
If a new UDP query arrives when <command>dnscache</command> is already handling 200 simultaneous UDP queries, <command>dnscache</command> drops the oldest query. 
If a new TCP connection arrives when <command>dnscache</command> is already handling 20 simultaneous TCP connections, <command>dnscache</command> drops the oldest connection.
</para>

<para>
<command>dnscache</command> uses a fixed-size cache, as controlled by the value of the <envar>CACHESIZE</envar> environment variable. 
Roughly 5% of the cache is used for a hash table. 
The rest is used for cache entries (including 8-byte Y2038-compliant expiration times):
<variablelist>
<varlistentry>
<term>A sets.</term><listitem><para>22 bytes plus 4 bytes per address plus the length of the owner name.</para></listitem>
</varlistentry>
<varlistentry>
<term>AAAA sets.</term><listitem><para>22 bytes plus 16 bytes per address plus the length of the owner name.</para></listitem>
</varlistentry>
<varlistentry>
<term>NS sets or PTR sets or CNAME sets.</term><listitem><para>22 bytes plus the length of the owner name and all the data names.</para></listitem>
</varlistentry>
<varlistentry>
<term>MX sets.</term><listitem><para>22 bytes plus 2 bytes per MX plus the length of all the names.</para></listitem>
</varlistentry>
<varlistentry>
<term>SOA sets.</term><listitem><para>22 bytes plus 20 bytes per SOA plus the length of all the names.</para></listitem>
</varlistentry>
<varlistentry>
<term>Other record sets.</term><listitem><para>22 bytes plus 2 bytes per record plus the length of all the data strings plus the length of the owner name.</para></listitem>
</varlistentry>
<varlistentry>
<term>Nonexistent domain or server failure.</term><listitem><para>22 bytes plus the length of the owner name.</para></listitem>
</varlistentry>
</variablelist>
</para>

<para>
Sets larger than 8192 bytes are not cached.
</para>

<para>
<command>dnscache</command> does not exit when it runs out of space in its cache; it simply removes the oldest entries to make more space.
</para>

</refsection>

<refsection>
<title>Resolution and caching policies</title>

<para>
<command>dnscache</command> relies on a configured list of root name servers. 
In contrast, some other servers start from a "hint file" listing (not necessarily root) name servers, and perform an intermediate extra step of asking those name servers where the root name servers are.
</para>

<para>
<command>dnscache</command> does not cache (or pass along) records outside the server's bailiwick; those records could be poisoned. 
Records for <filename>foo.dom</filename>, for example, are accepted only from the root servers, the <filename>dom</filename> servers, and the <filename>foo.dom</filename> servers.
</para>

<para>
<command>dnscache</command> does not bypass its cache to obtain glue from the additional section of a response. 
In particular, it will not use glue outside the server's bailiwick, or glue with TTL 0, or glue that violates other caching policies.
</para>

<para>
<command>dnscache</command> caches records for at most a fortnight.
It interprets TTLs above 2147483647 as 0, on the grounds that such excessive values are the results of unsigned arithmetic underflow.
</para>

<para>
<command>dnscache</command> does not cache <code>SOA</code> resource records when they are TTL carriers for the DNS protocol, although it will cache them if they are actual answers to queries.
It instead uses the TTL-carrying <code>SOA</code> record records to determine cache times (up to an hour) for zero-record responses and nonexistent domains.
</para>

<para>
A server that returns a delegation response that (directly or indirectly) delegates back to itself is considered "lame".
Responses from "lame" servers are logged, and what useful information they may contain, aside from the delegation, is cached (subject to the caching policies).
</para>
</refsection>

<refsection>
<title>Special names</title>

<para>
<command>dnscache</command> handles several things internally, synthesizing data for them directly instead of issuing back-end transactions.
</para>

<note>
<citerefentry><refentrytitle>walldns</refentrytitle><manvolnum>1</manvolnum></citerefentry> <emphasis>also</emphasis> synthesizes data for some of these domain names, and some domain names are handled internally by the DNS client library (see <citerefentry><refentrytitle>djbdns-client</refentrytitle><manvolnum>5</manvolnum></citerefentry>).
But what answers a proxy DNS server can synthesize are different to what answers a content DNS server can synthesize and different to what answers a DNS client library can synthesize.
Many "special-use domain names" have different rules for all three.
</note>

<para>
Several well-known domain names such as <filename>test.</filename> and <filename>home.arpa.</filename> and <filename>10.in-addr.arpa.</filename> are <emphasis>not</emphasis> answered synthetically.
These domain names are supposed to be prune-and-graft points handled by the the IP address selection mechanisms in the <filename>servers/test</filename> and <filename>servers/home.arpa</filename> and <filename>servers/10.in-addr.arpa</filename> files discussed later, switchable amongst <citerefentry><refentrytitle>walldns</refentrytitle><manvolnum>1</manvolnum></citerefentry>, <citerefentry><refentrytitle>tinydns</refentrytitle><manvolnum>1</manvolnum></citerefentry>, or a forwarded-to proxy DNS server.
</para>

<refsection>
<title>bare minima for loopback and link-local networking</title>

<para>
<command>dnscache</command> provides bare minima for loopback and link-local networking with fixed well-known and universal values, in line with RFC 6761 and RFC 6762.
</para>

<variablelist>
<varlistentry>
<term><filename>localhost.</filename> and its subdomains</term>
<listitem><para>
It gives <filename>localhost.</filename> itself an <code>A</code> record of 127.0.0.1 and an <code>AAAA</code> record of ::1.
All other types of resource record set are empty sets.
</para><para>
Its subdomains are treated likewise with the exception of subdomains of the form <filename><replaceable>d</replaceable>.<replaceable>c</replaceable>.<replaceable>b</replaceable>.<replaceable>127</replaceable>.localhost.</filename>.
It gives these an <code>A</code> record of 127.<replaceable>b</replaceable>.<replaceable>c</replaceable>.<replaceable>d</replaceable>, and an <code>AAAA</code> record of ::FFFF:127.<replaceable>b</replaceable>.<replaceable>c</replaceable>.<replaceable>d</replaceable>.
</para></listitem>
</varlistentry>
<varlistentry>
<term><filename>127.in-addr.arpa.</filename> subdomains</term>
<listitem><para>
To subdomains of the form <filename><replaceable>d</replaceable>.<replaceable>c</replaceable>.<replaceable>b</replaceable>.127.in-addr.arpa.</filename> it gives a <code>PTR</code> record of <filename><replaceable>d</replaceable>.<replaceable>c</replaceable>.<replaceable>b</replaceable>.127.localhost.</filename>, with the exception of the 127.0.0.1 reverse mapping.
It gives all other subdomains, including the 127.0.0.1 reverse mapping, a <code>PTR</code> record of <filename>localhost.</filename>.
All other types of resource record set are empty sets.
</para></listitem>
</varlistentry>
<varlistentry>
<term><filename>254.169.in-addr.arpa.</filename>, <filename>8.e.f.ip6.arpa.</filename>, and <filename>9.e.f.ip6.arpa.</filename> subdomains</term>
<listitem><para>
To subdomains of the form <filename><replaceable>c</replaceable>.<replaceable>b</replaceable>.254.169.in-addr.arpa.</filename>, <filename><replaceable>29hexlabels</replaceable>.8.e.f.ip6.arpa.</filename>, or <filename><replaceable>29hexlabels</replaceable>.9.e.f.ip6.arpa.</filename>, which are the reverse lookup names used to map link-local IP addresses, it gives all query types empty resource record sets.
</para></listitem>
</varlistentry>
<varlistentry>
<term><filename>1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa.</filename></term>
<listitem><para>
It gives this a <code>PTR</code> record of <filename>localhost.</filename>.
All other types of resource record set are empty sets.
</para></listitem>
</varlistentry>
</variablelist>

</refsection>

<refsection>
<title>common mis-use of IP address strings</title>

<para>
<command>dnscache</command> handles a common error where an application expects a domain name but its user supplies it with a human-readable form of an IPv4 address, and this is not caught by a DNS client library and handled internally but a request has reached <command>dnscache</command>; or where a content DNS server has erroneously entered an IP address instead of a domain name in an <code>NS</code> resource record in a content DNS server's database.
</para>

<para>
It gives dotted-decimal domain names an <code>A</code> record corresponding to the IP address whose human-readable form is the domain name (e.g. <filename>192.48.96.2.</filename> is given an <code>A</code> record of 192.48.96.2) and an <code>AAAA</code> record corresponding to the IPv4-mapped IPv6 equivalent address.
All other types of resource record set are empty sets.
</para>

<note>
For opaque and bijective address-to-name-to-address mapping where, rather, the proper mechanisms are employed by applications, use the <filename>servers/in-addr.arpa</filename> and <filename>servers/ip6.arpa</filename> files to point to a content DNS server running <citerefentry><refentrytitle>walldns</refentrytitle><manvolnum>1</manvolnum></citerefentry>.
</note>

</refsection>

<refsection>
<title>Non-existent domains</title>

<para>
RFCs 6761, 7686, 8880, 9462, and 9476 specify that <filename>invalid.</filename>, <filename>alt.</filename>, <filename>onion.</filename>, <filename>local.</filename>, <filename>resolver.arpa.</filename>, and their subdomains, should not query content DNS servers.
They are either looked up via other mechanisms, if they are looked up at all, and queries for them should never have reached <command>dnscache</command>, or they are by their natures non-existent as far as the global DNS is concerned.
For these, <command>dnscache</command> returns a "no such domain" error response.
</para>

</refsection>

<para>
For empty resource record sets and "no such domain" errors, <command>dnscache</command> includes a synthetic <code>SOA</code> resource record that carries the TTL.
As <command>dnscache</command> does not cache such <code>SOA</code> resource records when they are TTL carriers for the DNS protocol, properly operating caches in front of <command>dnscache</command> will not cache these records.
</para>

</refsection>

</refsection>

<refsection>
<title>Back end</title>

<refsection>
<title>IP addresses and ports</title>

<para>
<command>dnscache</command> sends outgoing requests from high ports of the IP address given by the value of the <envar>IPSEND</envar> environment variable. 
If <envar>IPSEND</envar> is not set then the default is either 0.0.0.0 or 0:0:0:0:0:0:0:0, allowing the operating system to pick an IP version 4 or version 6 address suitable for reaching the target servers.
The ports are picked at random, as are the message IDs in the requests.
The random number generator is seeded from a seed value, up to 128 bytes, that <command>dnscache</command> reads from its standard input at startup.
The seed does not need to be preserved across successive incarnations of <command>dnscache</command>, and merely needs to be unknown and unpredictable outwith the <command>dnscache</command> process.
It can just be a 128-byte snapshot of the system's random number generator read with the <citerefentry><refentrytitle>dd</refentrytitle><manvolnum>1</manvolnum></citerefentry> program.
</para>

<para>
At startup, <command>dnscache</command> reads a list of dotted-decimal root server IP addresses, one address per line, from <filename>servers/@</filename>. 
It also scans the <filename>servers/</filename> directory for server IP addresses for other domains. 
If there are addresses listed in <filename>servers/moon.af.example</filename>, for example, then <command>dnscache</command> will send queries for <filename><replaceable>anything</replaceable>.moon.af.example</filename> to those addresses, and will not cache records for <filename><replaceable>anything</replaceable>.moon.af.example</filename> from outside servers such as the root servers.
The list is capped at 16 IP addresses; the 17th and subsequent IP addresses being read, but discarded.
</para>

<caution>
If the <filename>servers/test</filename> and <filename>servers/home.arpa</filename> and <filename>servers/10.in-addr.arpa</filename> (and similar) files are missing, and it is not in forward-first or forward-only mode (more on which later) or those prune-and-graft points are not in turn handled by the forwarded-to proxy DNS servers <emphasis>either</emphasis>, <command>dnscache</command> is not correctly configured.
This is not a condition that is detectable by the software unaided.
</caution>

</refsection>

<refsection>
<title>Forward only mode</title>

<para>
If the <envar>FORWARDONLY</envar> environment variable is set, <command>dnscache</command> treats <filename>servers/@</filename> as a list of IP addresses for other caching proxies, not for content servers. 
It forwards queries to those caches the same way that a client does, rather than contacting a chain of servers according to <code>NS</code> records.
In this mode, it ignores referral responses, which it should never receive from a caching proxy in the first place and which the world at large has an unfortunate habit of making refer to IP addresses such as 127.0.0.1, which would cause a proxy loop if they were to be followed.
It logs such occurrences.
</para>

<para>
For similar reasons, for correct operation the list in a <filename>servers/<replaceable>*</replaceable></filename> file should not include:
<itemizedlist>
<listitem><para>the IP address on which <command>dnscache</command> is itself listening;</para></listitem>
<listitem><para>the IP address on which another proxy DNS server is listening; or</para></listitem>
<listitem><para>any IP addresses equivalent to those.</para></listitem>
</itemizedlist> 
</para>

</refsection>

<refsection>
<title>Forward first mode</title>

<para>
If the <envar>FORWARDFIRST</envar> environment variable is set, <command>dnscache</command> permits back-end services that it contacts to be either caching proxies or content servers. 
It behaves exactly as in normal mode, except that back-end queries have the "recursion desired" bit set to on instead of to off.
This causes caching proxies to respond with fully resolved responses, whilst still performing query resolution locally if they are content servers.
</para>

<para>
Forward first mode is overridden by forward only mode.
</para>

</refsection>

<refsection>
<title>Repeated IP addresses</title>

<para>
If a server sends <command>dnscache</command> a repeated IP address, <command>dnscache</command> passes the repeated IP address along to the client. 
The server's behavior violates RFC 2181, section 5.5, but there are reasonable uses of repeated IP addresses for load balancing, so <command>dnscache</command> does not go out of its way to remove repetitions when they occur.
A previously widespread server bug used to unintentionally produce repeated IP addresses. 
Here is an example (since fixed):
<informalexample><literallayout><computeroutput>% </computeroutput><userinput>dnsq a ns-ext.vix.com ns-ext.vix.com</userinput>
<computeroutput>1 ns-ext.vix.com:
117 bytes, 1+1+2+2 records, response, authoritative, noerror
query: 1 ns-ext.vix.com
answer: ns-ext.vix.com 3600 A 204.152.184.64
authority: vix.com 3600 NS ns-ext.vix.com
authority: vix.com 3600 NS ns1.gnac.com
additional: ns-ext.vix.com 3600 A 204.152.184.64
additional: ns1.gnac.com 130768 A 209.182.195.77</computeroutput></literallayout></informalexample>
</para>

<para>
This bug is the most common reason for users to see repeated IP addresses from <command>dnscache</command>.
</para>

</refsection>

</refsection>

<refsection>
<title>History</title>
<para>
<command>dnscache</command> was originally part of <personname><firstname>Daniel</firstname> <othername>J.</othername> <surname>Bernstein</surname></personname>'s djbdns toolset in 2000.
</para>
<para>
Special handling of <filename>localhost.</filename>, reverse lookup of 127.0.0.1, and dotted-decimal domain names were in the Bernstein original.
This special handling was significantly expanded in 2025.
</para>
<para>
<command>dnscache</command> ceased special-casing the <filename>ip6.int.</filename> superdomain in 2016.
The <filename>ip6.int.</filename> superdomain was deprecated by RFC3152 in 2001 and obsoleted by RFC4159 in 2005.
</para>
</refsection>

<refsection>
<title>Author</title>
<para>
Original code and documentation by <personname><firstname>Daniel</firstname> <othername>J.</othername> <surname>Bernstein</surname></personname>.
Documentation modernizations by <personname><firstname>Jonathan</firstname> <surname>de Boyne Pollard</surname></personname>.
</para>
</refsection>

</refentry>
