walldns

## Name

walldns — a database-less content DNS server using the UDP protocol

## Synopsis

`walldns`

## Description

walldns is a content DNS server that speaks the DNS/UDP protocol. It accepts DNS queries from hosts around the Internet, and responds with fixed information that it synthesizes on the spot. It does not have any database at all.

When it starts walldns 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).

Normally walldns is run via a server program such as udp-socket-listen to listen for DNS/UDP queries from hosts around the Internet. 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. However, none of its synthetic responses can ever exceed the non-EDNS0 DNS/UDP limit of 512 octets, meaning that there will never be occasion for DNS/TCP fallback.

### Purposes

walldns got its name from the idea of an opaque "wall" that hides private site information.

Its initial, and still major, use is queries that ask about various IP addresses, taking the form of a reverse lookup, to which it supplies generic responses that avoid revealing local host information. For this purpose, it should be run listening on a publicly-routable IP address and have the relevant subtree of `in-addr.arpa.` or `ip6.arpa.` delegated to that address.

A secondary use has developed where it responds for various well-known domain names with defined standard DNS resource record information. For this purpose, it should be run listening on a non-publicly-routable IP address and proxy DNS servers should be configured with prune-and-graft overrides for the well-known domain names. (A conventional choice for this IP address is 127.53.1.1, with walldns running on the same machine as the proxy DNS server.)

### Note

dnscache(1)also synthesizes data for some of these domain names, and some domain names are handled internally by the DNS client library (see djbdns-client(5)). 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.

This second purpose is in part to prevent burdening the public content DNS servers for various well-known "special-use domain names" with slow traffic asking for answers that could be more quickly synthesized locally, and in part to prevent test traffic and traffic containing information about hosts and devices on LANs, from being seen by the people who run these public servers.

## Responses

walldns rejects zone-transfer requests, inverse queries, non-Internet-class queries, truncated packets, and packets that contain anything other than a single query.

### Unanswered domains

RFCs 6761 and 8375 specify that `home.arpa.`, `example.`, `example.org.`, `example.com.`, `example.net.`, and their subdomains should be treated as any other public domain names. For these, walldns behaves as tinydns(1) would do when asked about domains that have no SOA record in its database: it does not respond to the query at all.

The same goes in general for any other domain names not covered here. But these specific domain names are covered by RFCs. It is an error to delegate or to prune-and-graft them to an instance of walldns, and walldns behaves as tinydns(1) would do in such a case (which in turn is motivated by minimizing "amplification" attacks and data sent to third parties by dint of falsified reply IP addresses).

### Non-existent domains

RFCs 6761, 7686, 8880, 9031, 9140, 9462, and 9476 specify that `test.`, `invalid.`, `alt.`, `onion.`, `local.`, `resolver.arpa.`, `6tisch.arpa.`, `eap-noob.com.`, and their subdomains, and subdomains of `ipv4only.arpa.`, should be non-existent on the global DNS. They are either looked up via other mechanisms, if they are looked up at all, and queries for them should never have reached walldns, or they are by their natures non-existent as far as the global DNS is concerned. For these, walldns returns a "no such domain" error response. For "no such domain" errors, it includes a synthetic `SOA` resource record that carries the TTL.

### Note

RFC 9476 actually contradicts itself. walldns goes with its several statements that `alt.` is a non-existent top-level-domain and content DNS servers for the public DNS always return "no such domain" responses rather than its one statement that content DNS servers should not synthesize "no such domain" responses.

### Well-known domains with fixed data

RFCs 6761 and 8880 specify that `localhost.` and its subdomains, and `ipv4only.arpa.` itself should exist on the global DNS, but have invariant standard data associated with them. `ANY` and `OPT` queries are answered with a single synthesized `HINFO` resource record set. Its value points people to RFC 8482 and RFC 6891, respectively. `A` and `AAAA` queries are answered with the standard data, which are 127.0.0.1 and ::1 for `localhost.` itself, 127.`a`.`b`.`c` and ::FFFF:127.`a`.`b`.`c` respectively for its ``c`.`b`.`a`.127.localhost.` subdomains, and 192.0.0.170 and 192.0.0.171 for `ipv4only.arpa.`. For any other query types, walldns responds with an empty resource record set. For empty resource record sets, it includes a synthetic `SOA` resource record that carries the TTL.

For any domain that has the form of a human-readable IP version 4 address, even a denormalized one with leading zeroes in the labels, walldns answers `A` queries with that IP address. `ANY` and `OPT` queries are answered with a single synthesized `HINFO` resource record set as before, and for any other query types, including `AAAA`, walldns responds with an empty resource record set. For empty resource record sets, it includes a synthetic `SOA` resource record that carries the TTL.

For the special-use domains `ip6.arpa.` and `in-addr.arpa.`, walldns answers `A`, `AAAA`, and `PTR` queries with data. `ANY` and `OPT` queries are answered with a single synthesized `HINFO` resource record set as before, and for any other query types walldns responds with an empty resource record set. For empty resource record sets, it includes a synthetic `SOA` resource record that carries the TTL.

It creates a bidirectional mapping with these two special-use domains that maps IP addresses to domain names that map back to those same IP addresses.

- For IP version 4, reverse lookup domain names take the form ``d`.`c`.`b`.`a`.in-addr.arpa`, where ``a`.`b`.`c`.`d`` is the IP address being looked up. walldns publishes `PTR` responses mapping the domain name back to itself. It publishes `A` responses mapping the domain name to the IP address ``a`.`b`.`c`.`d``. It returns "no such domain" errors for subdomains not in the standard form. For "no such domain" errors, it includes a synthetic `SOA` resource record that carries the TTL.

  As special cases, reverse lookups for 127.0.0.1 map to `localhost.`, which is then mapped in the other direction as earlier, and reverse lookups for other 127.`a`.`b`.`c` IPv4 addresses map to ``c`.`b`.`a`.127.localhost.`, which is then mapped in the other direction as earlier.

  ### Note

  It does not publish any `AAAA` data for any IP version 4 lookups. A "double reverse lookup" of an IP version 4 address will not end up at an IP version 6 address.

- For IP version 6, reverse lookup domain names take the form `5.4.3.2.1.0.z.y.x.w.v.u.t.s.r.q.p.o.n.m.l.k.j.i.h.g.f.e.d.c.b.a.ip6.arpa`, where `abcd:efgh:ijkl:mnop:qrst:uvwx:yz01:2345` is the IP address being looked up. walldns publishes `PTR` responses mapping the domain name back to itself. It publishes `AAAA` responses mapping the domain name to the IP address `abcd:efgh:ijkl:mnop:qrst:uvwx:yz01:2345`. It returns "no such domain" errors for subdomains not in the standard form. For "no such domain" errors, it includes a synthetic `SOA` resource record that carries the TTL.

  As a special case, reverse lookups for ::1/128 map to `localhost.`, which is then mapped in the other direction as earlier.

  ### Note

  It does not publish any `A` data for any IP version 6 lookups, even for IP version 4 "mapped" IP version 6 addresses. A "double reverse lookup" of an IP version 6 address will not end up at an IP version 4 address.

walldns does not include any `NS` resource records in its responses; and uses TTLs of a fortnight for all synthetic resource records, including the `SOA` resource record that is the DNS protocol's way of giving a TTL to "no such domain" errors and empty resource record sets. Caches will normally cap this TTL and end up re-querying walldns more than once per fortnight for the same information. But apart from the special-use domains `ip6.arpa.` and `in-addr.arpa.` the TTLs of these invariant data are effectively measured in years. (Changes would have to pass IANA/IETF review processes.) A fortnight is actually a conservative value.

### Note

Properly operating caches will not cache the `SOA` resource records, as they are a protocol bodge rather than actual record data. All of the other fields in the `SOA` resource record are effectively meaningless as they involve DNS databases that walldns does not have. They are set to sane values, but otherwise convey no information.

## History

walldns was originally part of Daniel J. Bernstein's djbdns toolset in 2000. None of the aforementioned RFCs existed at the time, and the invention of many of the "special-use domain names" was years in the future.

walldns gained IP version 6 support in 2019. It does not use the `ip6.int.` superdomain and never has. The `ip6.int.` superdomain was deprecated by RFC3152 in 2001 and obsoleted by RFC4159 in 2005. It was removed from other tools in the toolset in 2016.

Support for the "special-use domain names" other than `ip6.arpa.` and the original `in-addr.arpa.` was added in August 2025.

Until 2025, walldns sent "Refused" error responses for domains that it did not handle. It now does not reply to such queries, intentionally mimicking what tinydns(1) would do.

## Author

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