Title: Add a TLS layer to your Gopher server
       Author: Solène
       Date: 07 March 2019
       Tags: gopher openbsd
       Description: 
       
       Hi,
       
       In this article I will explain how to setup a gopher server supporting
       TLS. Gopher TLS support is not "official" as there is currently no RFC
       to define it. It has been recently chose by the community how to make
       it work, while keeping compatibility with old servers / clients.
       
       The way to do it is really simple. 
       
       Client A tries to connects to Server B, Client A tries TLS handshake,
       if Server B answers correctly to the TLS handshakes, then Client A
       sends the gopher request and Server B answers the gopher requests. If
       Server B doesn't understand the TLS handshakes, then it will probably
       output a regular gopher page, then this is throwed and Client A
       retries the connection using plaintext gopher and Server B answers the
       gopher request.
       
       This is easy to achieve because gopher protocol doesn't require the
       server to send anything to the client before the client sends its
       request.
       
       The way to add the TLS layer and the dispatching can be achieved using
       **sslh** and **relayd**. You could use haproxy instead of relayd, but
       the latter is in OpenBSD base system so I will use it. Thanks parazyd
       for sharing about sslh for this use case.
       
       **sslh** is a protocol demultiplexer, it listens on a port, and
       depending on what it receives, it will try to guess the protocol used
       by the client and send it to the according backend. It's first purpose
       was to make ssh available on port 443 while still having https daemon
       working on that server.
       
       Here is a schema of the setup
       
                                   +→ relayd for TLS + forwarding
                                   ↑                        ↓
                                   ↑ tls?                   ↓
           client -> sslh TCP 70 → +                        ↓
                                   ↓ not tls                ↓
                                   ↓                        ↓
                                   +→ → → → → → → gopher daemon
       on localhost
       
       
       This method allows to wrap any server to make it TLS compatible. The
       best case would be to have TLS compatibles servers which do all the
       work without requiring sslh and something to add the TLS. But it's
       currently a way to show TLS for gopher is real.
       
       
       ## Relayd
       
       The relayd(1) part is easy, you first need a x509 certificate for the
       TLS part, I will not explain here how to get one, there are already
       plenty of how-to and one can use let's encrypt with acme-client(1) to
       get one on OpenBSD.
       
       We will write our configuration in **/etc/relayd.conf**
       
           log connection
           relay "gopher" {
               listen on 127.0.0.1 port 7000 tls
               forward to 127.0.0.1 port 7070
           }
       
       In this example, relayd listens on port 7000 and our gopher daemon
       listens on port 7070. According to relayd.conf(5), relayd will look
       for the certificate at the following places:
       `/etc/ssl/private/$LISTEN_ADDRESS:$PORT.key` and
       `/etc/ssl/$LISTEN_ADDRESS:$PORT.crt`, with the current example you
       will need the files: /etc/ssl/private/127.0.0.1:7000.key and
       /etc/ssl/127.0.0.1:7000.crt
       
       relayd can be enabled and started using rcctl:
       
           # rcctl enable relayd
           # rcctl start relayd
       
       
       ## Gopher daemon
       
       Choose your favorite gopher daemon, I recommend geomyidae but any
       other valid daemon will work, just make it listening on the correct
       address and port combination.
       
           # pkg_add geomyidae
           # rcctl enable geomyidae
           # rcctl set geomyidae flags -p 7070
           # rcctl start geomyidae
       
       
       ## SSLH
       
       We will use sslh_fork (but sslh_select would be valid too, they have
       differents pros/cons). The `--tls` parameters tells where to forward a
       TLS connection while `--ssh` will forward to the gopher daemon. This
       is so because the protocol ssh is already configured within sslh and
       acts exactly like a gopher daemon: the client doesn't expect the
       server to be the first sending data.
       
           # pkg_add sslh
           # rcctl enable sslh_fork
           # rcctl set sslh_fork flags --tls 127.0.0.1:7000 --ssh
       127.0.0.1:7070 -p 0.0.0.0:70
           # rcctl start sslh_fork
       
       
       ## Client
       
       You can easily test if this works using openssl to connect by hand to
       the port 70
       
           $ openssl s_client -connect 127.0.0.1:7000
       
       can send a gopher request like "/" and you should get a result. Using
       telnet on the same address and port should give the same result.
       
       My gopher client **clic** already supports gopher TLS and is available
       at git://bitreich.org/clic and only requires the ecl common lisp
       interpreter to compile.