<h1 id="inetd-the-internet-super-server">Inetd, the internet
super-server</h1>
<p>Inetd is slowly becoming one of my favorite daemons. It makes writing
programs that talk over the network super easy. Inetd handles all of the
hard socket stuff and allows admins to write simple UNIX-ey programs.
Inetd is useful because it allows us to write services that only run
when they are requested in order to reduce total system load.</p>
<h1 id="how-inetd-works">How inetd works</h1>
<p>Inetd can be conceptualized as a sort of "wrapper daemon". Inetd is
always running <em>despite the fact that many of it's sub-services are
not always running</em>.</p>
<p>Inetd listens on a specific port. When it gets a request, it handles
all of the hard socket parts. This request is then passed to one of our
<em>inetd services</em></p>
<p>We will use a simple server that echoes the request back to the user
as an example. We will call this <em>inetd service</em>
<code>echod</code></p>
<p>Inetd passes requests to <code>echod</code> as text.
<code>echod</code> will read from stdin and write to stdout. Everything
written to stdout is passed to the client. <code>echod</code> will then
exit.</p>
<h2 id="echo-server-example">echo server example</h2>
<p>I use OpenBSD on my webserver. Sadly, systemd sockets have replaced
inetd on many linux systems. systemd sockets are entirely painful to
use. I can't verify that these examples will work on non-OpenBSD systems
but the <code>openbsd-inetd</code> package is available on a wide
variety of debianoiads.</p>
<p>Let's write out out <code>echod</code> service and the configuration
files required to get it working.</p>
<p>Edit <code>/etc/inetd.conf</code></p>
<pre><code># port  socket type protocol    wait/nowait user    server program      server arguments(optional)
9999    stream      tcp         nowait      daemon  /opt/echod/echod.sh</code></pre>
<p>And our <code>echod</code> service file, located at
<code>/opt/echod/echod.sh</code>:</p>
<pre><code>#!/bin/sh
while read l; do
        echo $l;
done;

exit 0;</code></pre>
<p>Be sure to <code>chmod +x echod.sh</code> and
<code>rcctl enable inetd &amp;&amp; rcctl start inetd</code> or it won't
run.</p>
<h3 id="testing">Testing</h3>
<p>Sometimes you can use curl to test a service but I will use netcat
instead because it doesn't assume http.</p>
<pre><code>$ echo &quot;foobar&quot; | nc -N localhost 9999
foobar
$</code></pre>
<p>You can also use telnet to test the service:</p>
<pre><code>$ telnet localhost 9999
Trying 127.0.0.1...
Connected to localhost.
Escape character is &#39;^]&#39;.
foo
foo
foobar
foobar
echo back
echo back
^]
telnet&gt; Connection closed.
$</code></pre>
<h2 id="finger-server-example">Finger server example</h2>
<p>Many months ago, I wrote a finger server to learn more about how
inetd works (and to write a finger daemon that doesn't allow for
enumerating non-regular users). <a
href="https://gitlab.com/binrc/fingerd/">You can download the source
code for my finger server from my gitlab</a>.</p>
<p>This finger server only allows information from users who have a home
directory in <code>/home/</code> to be displayed. It also has hard-coded
filenames it looks for. Example output looks something like:</p>
<pre><code>$ finger binrc@localhost
[localhost/127.0.0.1]
binrc@openbsd.my.domain

https://0x19.org

Working on an HPR episode

binrc.nospam@nospam.protonmail.com

No .pgpkey

$</code></pre>
<h2 id="gopher-server-example">Gopher server example</h2>
<p>Currently, I am working on a gopher server that runs through inetd to
learn more about how gopher works (and to write a gopher server that
doesn't allow for path traversal). I have yet to add autoindex support
but I thought it would be good to include anyway because it really
demonstrates how simple it can be to write an inetd service. <a
href="https://gitlab.com/binrc/pika">You can download the source code
for my gopher server from my gitlab</a>.</p>
<p>This gopher server reads input from standard in and prints the
requested file to standard out. Writing an inetd service can be as easy
as writing an application specific version of <code>cat(1)</code>.</p>
<h1 id="giving-the-service-ssl">Giving the service SSL</h1>
<p>You can pair inetd with relayd to make any inetd service use ssl. In
this example, I am symlinking my existing httpd certs obtained with <a
href="https://acme.sh">acme.sh</a></p>
<pre><code># ln -s /etc/ssl/example.com.fullchain.pem /etc/ssl/example.com\:9998.crt
# ln -s /etc/ssl/private/example.com.key /etc/ssl/private/example.com\:9998.key</code></pre>
<p>A sample relayd configuration looks like:</p>
<pre><code>log connection

tcp protocol &quot;echod&quot; {
        tls keypair &quot;example.com:9998&quot;
}

relay &quot;echod&quot; {
        listen on example.com port 9998 tls
        protocol &quot;echod&quot;
        forward to 127.0.0.1 port 9999
}</code></pre>
<p>After enabling and starting relayd, it will now be listening on port
<code>9998</code>. When it receives traffic on <code>9998</code>, it
will perform all of the fancy cryptography stuff and pass the request to
<code>localhost:9999</code>. Since relayd is listening on
<code>9999</code> and passing requests on <code>9999</code> to the echo
server, we are now running an echo server with ssl.</p>
<h1 id="conclusion">Conclusion</h1>
<p>Do I run inetd in production? No, not really. I have in the past but
I haven't needed it seeing as finger, echo, and gopher are dead
protocols. Even if inetd is largely useless in the modern era, it's
still fun to play with.</p>
