summaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2020-12-28 22:09:00 +0000
committerLaurent Bercot <ska-skaware@skarnet.org>2020-12-28 22:09:00 +0000
commitfab29b78d87d0114ecbdfbcac3b0e7c0edb463ba (patch)
tree786d09f619fa7302851e02fa7d51f53151db518c /doc
downloaddnsfunnel-fab29b78d87d0114ecbdfbcac3b0e7c0edb463ba.tar.xz
Initial commit
Diffstat (limited to 'doc')
-rw-r--r--doc/dnsfunnel-daemon.html112
-rw-r--r--doc/dnsfunnel-translate.html70
-rw-r--r--doc/dnsfunneld.html160
-rw-r--r--doc/index.html116
-rw-r--r--doc/upgrade.html28
5 files changed, 486 insertions, 0 deletions
diff --git a/doc/dnsfunnel-daemon.html b/doc/dnsfunnel-daemon.html
new file mode 100644
index 0000000..d93d463
--- /dev/null
+++ b/doc/dnsfunnel-daemon.html
@@ -0,0 +1,112 @@
+<html>
+ <head>
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <meta http-equiv="Content-Language" content="en" />
+ <title>dnsfunnel: the dnsfunnel-daemon program</title>
+ <meta name="Description" content="dnsfunnel: the dnsfunnel-daemon program" />
+ <meta name="Keywords" content="dnsfunnel daemon /etc/resolv.conf local cache resolver 127.0.0.1" />
+ <!-- <link rel="stylesheet" type="text/css" href="//skarnet.org/default.css" /> -->
+ </head>
+<body>
+
+<p>
+<a href="index.html">dnsfunnel</a><br />
+<a href="//skarnet.org/software/">Software</a><br />
+<a href="//skarnet.org/">skarnet.org</a>
+</p>
+
+<h1> The <tt>dnsfunnel-daemon</tt> program </h1>
+
+<p>
+<tt>dnsfunnel-daemon</tt> binds to a local UDP socket, drops its
+privileges, then executes into <a href="dnsfunneld.html">dnsfunneld</a>.
+</p>
+
+<h2> Interface </h2>
+
+<pre>
+ dnsfunnel-daemon [ -v verbosity ] [ -d notif ] [ -U | -u uid -g gid ] [ -i ip:port ] [ -R root ] [ -b bufsize ] [ -f cachelist ] [ -T | -t ] [ -N | -n ]
+</pre>
+
+<ul>
+ <li> dnsfunnel-daemon creates a UDP inet domain socket and binds it
+to IPv4 address <em>ip</em> (normally 127.0.0.1) and port <em>port</em>
+(normally 53). </li>
+ <li> Depending on the options it has been given, it may chroot and lose
+privileges on its gid and uid. </li>
+ <li> It execs into <a href="dnsfunneld.html">dnsfunneld</a> with the
+UDP socket as its standard input. </li>
+</ul>
+
+<p>
+ The point of <tt>dnsfunnel-daemon</tt> is to separate the administrative
+operations of starting a daemon from the actual serving part, which is
+handled by <a href="dnsfunneld.html">dnsfunneld</a>.
+</p>
+
+<h2> Exit codes </h2>
+
+<ul>
+ <li> 100: wrong usage </li>
+ <li> 111: system call failed </li>
+ <li> 126: failed to exec <a href="dnsfunneld.html">dnsfunneld</a> </li>
+ <li> 127: could not find the <a href="dnsfunneld.html">dnsfunneld</a> executable </li>
+</ul>
+
+<h2> Options </h2>
+
+<ul>
+ <li> <tt>-v&nbsp;<em>verbosity</em></tt>&nbsp;: verbosity of the
+<a href="dnsfunneld.html">dnsfunneld</a> program. This option is passed as is
+to <a href="dnsfunneld.html">dnsfunneld</a>. Default is 1. 0 suppresses warning
+messages. Higher values may give more informational messages. </li>
+ <li> <tt>-d&nbsp;<em>notif</em></tt>&nbsp;: readiness notification. This option
+is passed as is to <a href="dnsfunneld.html">dnsfunneld</a>, which will print a
+newline to descriptor <em>notif</em> when it is ready. Default is no readiness
+notification. </li>
+ <li> <tt>-U</tt>&nbsp;: read an uid in the UID environment variable and a gid
+in the GID environment variable, and drop privileges to that uid/gid. </li>
+ <li> <tt>-u&nbsp;<em>uid</em></tt>&nbsp;: drop privileges to numerical uid
+<em>uid</em>. </li>
+ <li> <tt>-g&nbsp;<em>gid</em></tt>&nbsp;: drop privileges to numerical gid
+<em>gid</em>. </li>
+ <li> <tt>-i&nbsp;<em>ip</em>:<em>port</em></tt>&nbsp;: bind the socket to
+IPv4 <em>ip</em> and port <em>port</em>. Default for <em>ip</em> is
+<tt>127.0.0.1</tt>; default for <em>port</em> is 53. </li>
+ <li> <tt>-R&nbsp;<em>root</em></tt>&nbsp;: chroot to <em>root</em>. Note that
+this option only increases security if you also drop privileges. </li>
+ <li> <tt>-b&nbsp;<em>bufsize</em></tt>&nbsp;: try and reserve a kernel buffer
+size of <em>bufsize</em> bytes for the socket. Default is 131072. If the given
+<em>bufsize</em> is 0, then <tt>dnsfunnel-daemon</tt> will use whatever the
+default is for your kernel. </li>
+ <li> <tt>-f&nbsp;<em>cachelist</em></tt>&nbsp;: Use <em>cachelist</em> as the
+file that <a href="dnsfunneld.html">dnsfunneld</a> reads its cache addresses
+from. Default is <tt>/run/dnsfunnel-caches</tt>, or <em>file</em>
+if the <tt>--with-cachelist=<em>file</em></tt> option has been given to the
+configure script at build time. </li>
+</ul>
+
+<p>
+ The other options control the activation or deactivation of various
+<a href="dnsfunneld.html">dnsfunneld</a> features:
+</p>
+ <li> <tt>-T</tt>&nbsp;: Do not activate truncation of responses. This is
+the default. </li>
+ <li> <tt>-t</tt>&nbsp;: If a DNS response is bigger than 510 bytes,
+truncate its last resource records until it fits into 510 bytes and can
+be sent in a UDP packet. </li>
+ <li> <tt>-N</tt>&nbsp;: Do not activate nxdomain workaround. This is the
+default. </li>
+ <li> <tt>-n</tt>&nbsp;: Activate nxdomain workaround. When receiving an A
+(resp. AAAA) query to forward, also make an AAAA (resp. A) query, and adjust
+the response accordingly. Some DNS servers incorrectly answer NXDOMAIN when
+they should just answer NODATA, and querying for another, existing, record
+type for the same domain allows dnsfunneld to tell the difference between a
+real NXDOMAIN (in which case that response is forwarded to the client) and
+an incorrect one (in which case NODATA is answered to the client instead). </li>
+ <li> Other options may be added in the future. </li>
+</ul>
+
+</body>
+</html>
diff --git a/doc/dnsfunnel-translate.html b/doc/dnsfunnel-translate.html
new file mode 100644
index 0000000..9dde27d
--- /dev/null
+++ b/doc/dnsfunnel-translate.html
@@ -0,0 +1,70 @@
+<html>
+ <head>
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <meta http-equiv="Content-Language" content="en" />
+ <title>dnsfunnel: the dnsfunnel-translate program</title>
+ <meta name="Description" content="dnsfunnel: the dnsfunnel-translate program" />
+ <meta name="Keywords" content="dnsfunnel translate /etc/resolv.conf nameserver cache address" />
+ <!-- <link rel="stylesheet" type="text/css" href="//skarnet.org/default.css" /> -->
+ </head>
+<body>
+
+<p>
+<a href="index.html">dnsfunnel</a><br />
+<a href="//skarnet.org/software/">Software</a><br />
+<a href="//skarnet.org/">skarnet.org</a>
+</p>
+
+<h1> The <tt>dnsfunnel-translate</tt> program </h1>
+
+<p>
+<tt>dnsfunnel-translate</tt> translates a file in <tt>resolv.conf</tt>
+format to a file in <a href="dnsfunneld.html">dnsfunneld</a> format.
+</p>
+
+<h2> Interface </h2>
+
+<pre>
+ dnsfunnel-translate [ -i inputfile ] [ -o outputfile ] [ -x ignoredip ]
+</pre>
+
+<ul>
+ <li> dnsfunnel-translate opens <em>inputfile</em> and parses it. It reads
+and processes lines beginning with <tt>nameserver</tt> followed by an IP
+address (v4 or v6). It ignores other lines. </li>
+ <li> It writes the IP addresses, without the <tt>nameserver</tt> keyword,
+to <tt>outputfile</tt>, one per line. </li>
+ <li> If a <tt>nameserver</tt> address is <em>ignoredip</em>, it does not
+get printed to <tt>outputfile</tt>
+ <li> dnsfunnel-translate exits 0 when it has finished processing
+<em>inputfile</em>. </li>
+</ul>
+
+<h2> Exit codes </h2>
+
+<ul>
+ <li> 0: success </li>
+ <li> 1: no suitable IP found in the input file </li>
+ <li> 100: wrong usage </li>
+ <li> 111: system call failed </li>
+</ul>
+
+<h2> Options </h2>
+
+<ul>
+ <li> <tt>-i&nbsp;<em>inputfile</em></tt>&nbsp;: process <em>inputfile</em>.
+Default is <tt>/etc/resolv.conf</tt>. </li>
+ <li> <tt>-o&nbsp;<em>outputfile</em></tt>&nbsp;: write the result to
+<em>outputfile</em>. Default is <tt>/run/dnsfunnel-caches</tt>, or <em>file</em>
+if the <tt>--with-cachelist=<em>file</em></tt> option has been given to the
+configure script at build time. </li>
+ <li> <tt>-x&nbsp;<em>ignoredip</em></tt>&nbsp;: ignore the <em>ignoredip</em>
+IPv4 address if it shows up as a <tt>nameserver</tt> in <em>inputfile</em>.
+Default is <tt>127.0.0.1</tt>. The point of this option is to avoid copying
+to <tt>outputfile</tt> the IPv4 address that the
+<a href="dnsfunnel-daemon.html">dnsfunnel-daemon</a> daemon will be bound to. </li>
+</ul>
+
+</body>
+</html>
diff --git a/doc/dnsfunneld.html b/doc/dnsfunneld.html
new file mode 100644
index 0000000..006a6d6
--- /dev/null
+++ b/doc/dnsfunneld.html
@@ -0,0 +1,160 @@
+<html>
+ <head>
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <meta http-equiv="Content-Language" content="en" />
+ <title>dnsfunnel: the dnsfunnel-daemon program</title>
+ <meta name="Description" content="dnsfunnel: the dnsfunnel-daemon program" />
+ <meta name="Keywords" content="dnsfunnel daemon /etc/resolv.conf local cache resolver 127.0.0.1" />
+ <!-- <link rel="stylesheet" type="text/css" href="//skarnet.org/default.css" /> -->
+ </head>
+<body>
+
+<p>
+<a href="index.html">dnsfunnel</a><br />
+<a href="//skarnet.org/software/">Software</a><br />
+<a href="//skarnet.org/">skarnet.org</a>
+</p>
+
+<h1> The <tt>dnsfunneld</tt> program </h1>
+
+<p>
+<tt>dnsfunneld</tt> is a small DNS forwarder daemon. It receives
+DNS queries from clients, then forwards them to one or more DNS caches.
+It collects the responses and forwards them back to the clients. Depending
+on the options it is given, it may perform light processing on the
+queries, the responses, or both.
+</p>
+
+<h2> Interface </h2>
+
+<pre>
+ dnsfunneld [ -v verbosity ] [ -d notif ] [ -o ops ] cachelist
+</pre>
+
+<ul>
+ <li> dnsfunneld reads the <em>cachelist</em> file, expecting to find
+a list of IP (v4 or v6) addresses, one per line. These addresses are the
+DNS caches it will forward the queries to. </li>
+ <li> dnsfunneld expects to have a bound UDP inet domain socket as
+its standard input. It expects to receive packets no more than 512
+bytes long, only containing DNS normal queries (QUERY) for the IN
+class. </li>
+ <li> Depending on <em>ops</em>, dnsfunneld may send additional queries
+to the caches listed in <em>cachelist</em>. It handles the answers
+internally: the additional queries are invisible to clients. </li>
+ <li> dnsfunneld is a long-lived process. </li>
+</ul>
+
+<h2> Signals </h2>
+
+<ul>
+ <li> SIGHUP: read the <em>cachelist</em> file again, updating its
+in-memory cache list. In-flight queries are still handled by the old
+list; the new list will only apply for queries arriving after the SIGHUP. </li>
+ <li> SIGTERM: enter lame-duck mode, do not accept any more queries. When
+all in-flight queries have been answered, exit 0.
+</ul>
+
+<h2> Exit codes </h2>
+
+<ul>
+ <li> 0: SIGTERM received and all in-flight queries have been answered </li>
+ <li> 100: wrong usage </li>
+ <li> 111: system call failed </li>
+</ul>
+
+<h2> Options </h2>
+
+<ul>
+ <li> <tt>-v&nbsp;<em>verbosity</em></tt>&nbsp;: verbosity.
+Default is 1. 0 suppresses warning messages. Higher values may give more
+informational messages in the future. </li>
+ <li> <tt>-d&nbsp;<em>notif</em></tt>&nbsp;: readiness notification. When
+dnsfunneld is ready to process queries, write a newline to file descriptor
+<em>notif</em>. <em>notif</em> must be 3 or greater. Default is no notification
+at all. </li>
+ <li> <tt>-o&nbsp;<em>ops</em></tt>&nbsp;: perform various operations on
+queries. <em>ops</em> is a decimal integer that is treated as a bitfield.
+Default is 0. Operations are listed below. </li>
+</ul>
+
+<h2> DNS forwarding behaviour </h2>
+
+<ul>
+ <li> When it receives a query, dnsfunneld forwards it to the first DNS cache
+in the list it has read from the <em>cachelist</em> file. </li>
+ <li> If it receives a response with the TC bit, it resends the query over TCP. </li>
+ <li> If it receives a suitable response within a given time frame, it forwards
+it to the client. </li>
+ <li> On SERVFAIL, or after a timeout of 1 second, it gives up and sends the
+query to the next DNS cache in its list. (If the first cache answers after the time
+frame, the answer is dropped.)
+ <li> If dnsfunneld reaches the end of its cache list, it retries the whole
+procedure starting at the beginning of the list, but with a timeout of 3 seconds.
+Caches that returned a SERVFAIL are crossed off the list for that query. </li>
+ <li> If the second pass fails again, dnsfunneld tries again with a timeout of
+11 seconds, then with a timeout of 45 seconds. If all of this fails, it returns
+a SERVFAIL to the client. </li>
+ <li> A machine should not use a DNS cache that is too far away. In normal operation,
+a timeout of 1 second should be more than enough for a cache to answer, if it already
+has the answer. If the answer is absent from all caches and it takes them more than
+1 second to resolve the query, the answer will be obtained by dnsfunneld in the second
+pass. Realistically, the only cases when caches that are not at the top of the list
+are used are:
+ <ul>
+ <li> obscure DNS queries, not likely to be in the caches, and that will take
+time to resolve; </li>
+ <li> or the first cache has really gone to lunch. </li>
+ </ul>
+</ul>
+
+<h2> dnsfunneld operations </h2>
+
+<p>
+ <em>ops</em> is an integer used as a bitfield. Depending on which bits are set,
+various operations are performed on queries or answers, slightly modifying the
+behaviour described above.
+</p>
+
+<ul>
+ <li> bit 0: activate truncation. If a DNS response is more than 510 bytes
+long, dnsfunneld will truncate the <em>last</em> resource records in the response,
+until it fits into 510 bytes and can be given to the client in a UDP packet.
+The structure of a DNS packet makes it so the RRs are listed in order of
+decreasing importance, so keeping as many RRs as will fit in 510 bytes
+without reordering them is the natural way of truncating a response. </li>
+ <li> bit 1: activate workaround for some servers that incorrectly report
+NXDOMAIN when they're asked for an AAAA record, and no such record exists
+for the domain but an A record exists. When that bit is set in <em>ops</em>,
+for every A or AAAA query dnsfunneld receives and forwards, it also sends
+an additional AAAA or A query for the same domain. If the main query returns
+NXDOMAIN, dnsfunneld waits for the response to the auxiliary query: if this
+response is not NXDOMAIN, then dnsfunneld answers NODATA to the client instead
+of NXDOMAIN. Be aware that activating this workaround can practically double
+the number of queries sent to the DNS caches, and may cause additional delays
+before the clients get their answers. </li>
+</ul>
+
+<h2> Notes </h2>
+
+<ul>
+ <li> The point of dnsfunneld is to work around ill-designed or unreliable
+client setups with several motley <tt>nameserver</tt> entries in
+<tt>/etc/resolv.conf</tt>. By converting those entries to a cache list
+instead (via the <a href="dnsfunnel-translate.html">dnsfunnel-translate</a>
+program), running dnsfunneld on 127.0.0.1, and enforcing a policy of one
+single <tt>nameserver 127.0.0.1</tt> entry in <tt>/etc/resolv.conf</tt>,
+the setup can be made more reliable and more consistent. </li>
+ <li> Such a policy can be automated, for instance, by listening to
+changes on the <tt>/etc/resolv.conf</tt> file (via inotify or kqueue,
+depending on your system) and immediately calling
+<a href="dnsfunnel-translate.html">dnsfunnel-translate</a>, sending
+a SIGHUP to dnsfunneld, and forcefully overwriting <tt>/etc/resolv.conf</tt>. </li>
+ <li> It is easy to send a SIGHUP to dnsfunneld even without knowing its
+pid, if it is run under a process supervision system such as
+<a href="//skarnet.org/software/s6/">s6</a>. </li>
+</ul>
+
+</body>
+</html>
diff --git a/doc/index.html b/doc/index.html
new file mode 100644
index 0000000..fe8e8d4
--- /dev/null
+++ b/doc/index.html
@@ -0,0 +1,116 @@
+<html>
+ <head>
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <meta http-equiv="Content-Language" content="en" />
+ <title>dnsfunnel - A small local DNS cache daemon</title>
+ <meta name="Description" content="dnsfunnel - a small local DNS cache daemon" />
+ <meta name="Keywords" content="dnsfunnel DNS domain cache local /etc/resolv.conf resolver forwarder laurent bercot ska skarnet" />
+ <!-- <link rel="stylesheet" type="text/css" href="//skarnet.org/default.css" /> -->
+ </head>
+<body>
+
+<p>
+<a href="//skarnet.org/software/">Software</a><br />
+<a href="//skarnet.org/">skarnet.org</a>
+</p>
+
+<h1> dnsfunnel </h1>
+
+<h2> What is it&nbsp;? </h2>
+
+<p>
+ dnsfunnel is a small daemon listening to DNS client requests over UDP
+(typically from the libc's
+<a href="https://pubs.opengroup.org/onlinepubs/9699919799/functions/getaddrinfo.html">getaddrinfo()</a>
+function) and forwards them to a list of DNS caches. It provides the
+client with the first answer it gets, trimming the answer so it fits
+in an UDP packet.
+</p>
+
+<p>
+ dnsfunnel is especially useful for distributions using the
+<a href="https://musl-libc.org">musl</a> libc, which does not support
+TCP DNS transport. It was originally written to be used in the
+<a href="https://alpinelinux.org/">Alpine Linux</a> distribution.
+</p>
+
+<hr />
+
+<h2> Installation </h2>
+
+<h3> Requirements </h3>
+
+<ul>
+ <li> A POSIX-compliant system with a standard C development environment.
+The system must also support <tt>chroot()</tt> </li>
+ <li> GNU make, version 3.81 or later </li>
+ <li> <a href="//skarnet.org/software/skalibs/">skalibs</a> version
+2.10.0.0 or later. It's a build-time requirement. It's also a run-time
+requirement if you link against the shared version of the skalibs
+library. </li>
+ <li> <a href="//skarnet.org/software/s6-dns/">s6-dns</a> version
+2.3.3.0 or later. It's a build-time requirement. It's also a run-time
+requirement if you link against the shared version of the s6dns
+library. </li>
+
+</ul>
+
+<h3> Licensing </h3>
+
+<p>
+ dnsfunnel is free software. It is available under the
+<a href="https://opensource.org/licenses/ISC">ISC license</a>.
+</p>
+
+<h3> Download </h3>
+
+<ul>
+ <li> The current released version of dnsfunnel is
+<a href="dnsfunnel-0.0.1.0.tar.gz">0.0.1.0</a>.
+ (This is a lie.
+dnsfunnel is in alpha development at the moment, and only
+available through git.) </li>
+ <li> Alternatively, you can checkout a copy of the
+<a href="//git.skarnet.org/cgi-bin/cgit.cgi/dnsfunnel/">dnsfunnel
+git repository</a>:
+<pre> git clone git://git.skarnet.org/dnsfunnel </pre> </li>
+ <li> There's also a
+<a href="https://github.com/skarnet/dnsfunnel">GitHub mirror</a>
+of the dnsfunnel git repository. </li>
+</ul>
+
+<h3> Compilation </h3>
+
+<ul>
+ <li> See the enclosed INSTALL file for installation details. </li>
+</ul>
+
+<h3> Upgrade notes </h3>
+
+<ul>
+ <li> <a href="upgrade.html">This page</a> lists the differences to be aware of between
+the previous versions of dnsfunnel and the current one. </li>
+</ul>
+
+<hr />
+
+<h2> Reference </h2>
+
+<h3> Commands </h3>
+
+<ul>
+<li><a href="dnsfunnel-daemon.html">The <tt>dnsfunnel-daemon</tt> program</a></li>
+<li><a href="dnsfunneld.html">The <tt>dnsfunneld</tt> program</a></li>
+<li><a href="dnsfunnel-translate.html">The <tt>dnsfunnel-translate</tt> program</a></li>
+</ul>
+
+<h2> Related resources </h2>
+
+<ul>
+ <li> <tt>dnsfunnel</tt> is discussed on the
+<a href="//skarnet.org/lists.html#skaware">skaware</a> mailing-list. </li>
+</ul>
+
+</body>
+</html>
diff --git a/doc/upgrade.html b/doc/upgrade.html
new file mode 100644
index 0000000..6b46bde
--- /dev/null
+++ b/doc/upgrade.html
@@ -0,0 +1,28 @@
+<html>
+ <head>
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+ <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+ <meta http-equiv="Content-Language" content="en" />
+ <title>dnsfunnel: how to upgrade</title>
+ <meta name="Description" content="dnsfunnel: how to upgrade" />
+ <meta name="Keywords" content="dnsfunnel installation upgrade" />
+ <!-- <link rel="stylesheet" type="text/css" href="//skarnet.org/default.css" /> -->
+ </head>
+<body>
+
+<p>
+<a href="index.html">dnsfunnel</a><br />
+<a href="//skarnet.org/software/">Software</a><br />
+<a href="//skarnet.org/">skarnet.org</a>
+</p>
+
+<h1> What has changed in dnsfunnel </h1>
+
+<h2> in 0.0.1.0 </h2>
+
+<ul>
+ <li> Initial release. </li>
+</ul>
+
+</body>
+</html>