Comments on 2018-01-10 Encrypted Gopher

Maybe we should use TLS after all.

First, I generated a server key and certificate using the following:

$ openssl req -new -x509 -days 365 -nodes -config gopher-server.cnf \
              -out gopher-server.pem -keyout gopher-server.pem

This saves both the private key and the certificate in the PEM file. The CNF file just holds a few defaults:

RANDFILE = ./openssl.rnd

[ req ]
default_bits = 2048
encrypt_key = yes
distinguished_name = req_dn
x509_extensions = cert_type
utf8 = yes

[ req_dn ]
countryName = Country Name (2 letter code)
countryName_default = CH

stateOrProvinceName             = State or Province Name (full name)
stateOrProvinceName_default     = Zürich

localityName                    = Locality Name (eg, city)
localityName_default            = Zürich

organizationName                = Organization Name (eg, company)
organizationName_default        = Alex Schroeder

organizationalUnitName          = Organizational Unit Name (eg, section)
organizationalUnitName_default  = Head Desk

commonName                      = Common Name (FQDN of your server)
commonName_default              = localhost

emailAddress                    = Email Address
emailAddress_default            = alex@gnu.org

[ cert_type ]
nsCertType = server

Be sure to change localhost to your real server’s domain name if you do the same!

I use the PEM file to start the Gopher server using Net::Server::Proto::SSL (this depends on IO::Socket::SSL):

OddMuse->run(
  proto => 'ssl',
  SSL_cert_file => 'stuff/gopher-server.pem',
  SSL_key_file  => 'stuff/gopher-server.pem',
);

When I start the server:

$ perl stuff/gopher-server.pl
Running ./wiki.pl
2018/01/19-10:39:49 OddMuse (type Net::Server::Fork) starting! pid(4418)
Resolved [*]:20203 to [0.0.0.0]:20203, IPv4
Binding to SSL port 20203 on host 0.0.0.0 with IPv4

This looks good.

Now to test it using a command line client. First, no TLS:

$ echo Alex | nc localhost 20203

This fails and that’s good. Now try without certificate validation:

$ echo Alex | gnutls-cli --no-ca-verification localhost:20203
|<1>| There was a non-CA certificate in the trusted list: O=Entrust.net,OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.),OU=(c) 1999 Entrust.net Limited,CN=Entrust.net Certification Authority (2048).
Processed 172 CA certificate(s).
Resolving 'localhost:20203'...
Connecting to '127.0.0.1:20203'...
- Certificate type: X.509
- Got a certificate list of 1 certificates.
- Certificate[0] info:
 - subject `EMAIL=alex@gnu.org,CN=localhost,OU=Head Desk,O=Alex Schroeder,L=Zürich,ST=Zürich,C=CH', issuer `EMAIL=alex@gnu.org,CN=localhost,OU=Head Desk,O=Alex Schroeder,L=Zürich,ST=Zürich,C=CH', serial 0x00e44cda1d0cfffee5, RSA key 2048 bits, signed using RSA-SHA256, activated `2018-01-19 10:10:02 UTC', expires `2019-01-19 10:10:02 UTC', pin-sha256="n29iQd9rKSopyBka++t4zPflTD0EnPB67ix90SPZuNA="
	Public Key ID:
		sha1:89599664e456cdbcfb5041e8586f2305f3f8856a
		sha256:9f6f6241df6b292a29c8191afbeb78ccf7e54c3d049cf07aee2c7dd123d9b8d0
	Public Key PIN:
		pin-sha256:n29iQd9rKSopyBka++t4zPflTD0EnPB67ix90SPZuNA=
	Public key's random art:
		+--[ RSA 2048]----+
		|       .+ .+o+.  |
		|       + o  *+o. |
		|        *  +.+o..|
		|       * .. +o=. |
		|      o S   E=.. |
		|           .o    |
		|             o   |
		|              .  |
		|                 |
		+-----------------+

- Description: (TLS1.2)-(ECDHE-RSA-SECP256R1)-(AES-128-GCM)
- Session ID: B6:26:85:D2:49:20:EC:9F:50:D2:A7:97:AA:0F:18:A9:1B:F3:11:AB:CB:3A:9B:79:0F:61:9E:4A:F4:A9:2B:C7
- Ephemeral EC Diffie-Hellman parameters
 - Using curve: SECP256R1
 - Curve size: 256 bits
- Version: TLS1.2
- Key Exchange: ECDHE-RSA
- Server Signature: RSA-SHA512
- Cipher: AES-128-GCM
- MAC: AEAD
- Compression: NULL
- Options: safe renegotiation,
- Handshake was completed

- Simple Client Mode:

My best friend is [[Berta]].

Tags: [[tag:Friends]]

OK, at the end of the output, there is the text of our page!

Now let’s see whether we can get get rid of --no-ca-validation. First, we save the certificate to a local file and then we use it in our request:

$ gnutls-cli --save-cert=server.pem localhost:20203
$ echo Alex | gnutls-cli --x509cafile=server.pem localhost:20203

This works!

So, in theory at least, we have all the ingredients for gophers://alexschroeder.ch – except there is no standard port to use for gopher over TLS. Oh well. I might as well use 7443.

OK, done. Let’s test it!

$ gnutls-cli --save-cert=server.pem alexschroeder.ch:7443
$ echo Alex | gnutls-cli --x509cafile=server.pem alexschroeder.ch:7443

This works as well!

Here’s the TOFU variant, Trust On First Use. “This option will, in addition to certificate authentication, perform authentication based on previously seen public keys, a model similar to SSH authentication.”

First, send no request at all:

$ gnutls-cli --tofu alexschroeder.ch:7443

Answer y to the question of whether you want trust it. You’re then left hanging as the server waits for your selector. Type “Alex” + Return and you should get an answer. If you don’t, you will get a timeout after 15 seconds.

This stores the server in ~/.gnutls/known_hosts and from then on, no extra options are required:

$ echo Alex | gnutls-cli alexschroeder.ch:7443

All right, server is done!

– Alex Schroeder 2018-01-19 11:00 MEZ


And if you want a real client to go along with it, try my SSL branch of gopher.el which does only SSL, so I guess it will only work for alexschroeder:7443.

– Alex 2018-01-19 13:07 UTC


I added this to my SSL branch of VF-1 and this branch was later merged into Solderpunk’s VF-1.

Here’s how I start it:

$ vf1 --tls alexschroeder.ch:7443

I love it.

– Alex 2018-01-19 13:17 UTC


And here’s how to run a server with encryption, if you have the certificate with all the other certificates in its chain in one file and the private key in another file. This is how I just tested it to make sure the Gopher server uses the same certificate as my website. The certificates from my website are from Let's Encrypt using an older version of dehydrated called letsencrypt.sh.

/home/alex/perl5/perlbrew/perls/perl-5.24.0/bin/perl \
  /home/alex/farm/gopher-server2.pl \
  --setsid --user=alex --group=alex \
  --host=alexschroeder.ch --port=7443 --log_level=3 \
  --log_file=/home/alex/farm/gopher-server2-ssl.log \
  --pid_file=/home/alex/farm/gopher-server2-ssl.pid \
  --wiki=/home/alex/farm/wiki.pl \
  --wiki_dir=/home/alex/alexschroeder \
  --wiki_pages=SiteMap \
  --wiki_pages=About \
  --wiki_pages=Gopher \
  --wiki_cert_file=/etc/letsencrypt.sh/certs/alexschroeder.ch/fullchain.pem \
  --wiki_key_file=/etc/letsencrypt.sh/certs/alexschroeder.ch/privkey.pem

– Alex 2018-01-21 18:42 UTC


hello!

please don’t do it this way

use of .onion addresses gets you all the nice features like authentication, confidentiality etc. without any of the complexity that is https.

let gopher stay simple

– anonymous 2018-04-11 19:40 UTC


From a developer perspective, implementing TLS was extremely easy. Plop standard library into client and server, done. Adding TLS is not adding HTTPS.

– Alex Schroeder 2018-04-11 22:22 UTC


Tor uses TLS, therefore only adds complexity on top of TLS.

– Anonymous 2018-05-11 12:56 UTC


Please make sure you contribute only your own work, or work licensed under the GNU Free Documentation License. Note: in order to facilitate peer review and fight vandalism, we will store your IP number for a number of days. See Privacy Policy for more information. See Info for text formatting rules. You can edit this page if you need to fix typos. You can subscribe to updates by email without leaving a comment.

To save this page you must answer this question:

Please say HELLO.