-- Leo's gemini proxy

-- Connecting to log.pfad.fr:1965...

-- Connected

-- Sending request

-- Meta line: 20 text/gemini; charset=utf-8

Finally reachable over IPv6


Up until now, this site has been hosted on sourcehut pages. It was quite easy to get started since it integrates very well into the sourcehut ecosystem: the build gets triggered automatically on git push and it automatically gets the permission to publish the page.


However, sourcehut pages have a couple of shortcomings:


they are only reachable over IPv4

they only support HTTP/1.1

deploy tokens cannot be scoped to only one site/domain


IPv6 support on sr.ht - sourcehut lists


Specifications


I aimed at replacing sourcehut pages, so my server needed the following features:


automatic HTTPS

gemini support

deployment of a site in one curl command


Additionally, I wanted to have:


reachability over IPv6

HTTP/2 (and eventually HTTP/3) support

deployment token limited to a given site


So I opened my IDE and developed my pages server:


pages: {gemini, https, http3} multi-host server


Operating System setup


The system is a bare-bone Debian hosted on the cheapest Hetzner Cloud instance (an arm64 virtual machine). Its initial setup is made with cloud-init. I deploy my software by creating a .deb file (using nFPM) and running: dpkg -i pages.deb (the deb contains the binary as well as the systemd units).


nFPM - simple, 0-dependencies, deb, rpm, apk, and Arch Linux packager


I choose to treat IPv6 as a first-class citizen and I set up snid as a fallback for IPv4. So my pages server is only listening on an IPv6 address, port 443. When an IPv4 connection comes on port 443, snid peaks at the server name (SNI), looks up the corresponding IPv6 and make a bridge between the pages server and the IPv4 client.


SNI Proxying over IPv6 to Share Port 443 - Andrews Ayer


Playing with HTTP/3


As an additional challenge, I took a look at HTTP/3. It required quite a lot of work because it communicates over UDP. So snid cannot help here. I don't think that an equivalent of snid is possible for UDP connections, so I simply choose to only serve HTTP/3 over IPv6 (yes, IPv4 is second-class). To advertise that the server accepts HTTP/3 connection, there are currently two possibilities:


add an Alt-Svc header to HTTP/2 requests, to inform the client of the alternative service endpoints

Alt-Svc header - MDN


create an "HTTPS DNS record" (the name is awfully bad for indexing: searching for it returns mainly results for DNS-over-HTTPS)

Service binding and parameter specification via the DNS (DNS SVCB and HTTPS RRs) - IETF


The bad news is that my DNS provider does not support HTTPS records (I even contacted the support, who confirmed the lack of support). So I must use Alt-Svc headers. Since HTTP/3 is only reachable of IPv6, the Alt-Svc header looks like this: h3="[2a01:4f8:c17:f026::1]:443"; ma=2592000


I did some tests and found that curl didn't properly understand this header (it accepted either an IPv4 or a hostname). I opened an issue that was addressed within 3 days (I take the lack of comments on my initial issue as a good sign: my original message was sufficiently documented).


https://github.com/curl/curl/issues/11737


Conclusion


This was a fun project. Feel free to have a look at the source code, which contains the server as well as the systemd unit files.


pages: {gemini, https, http3} multi-host server


The license is "AGPL-3.0-or-later WITH GPL-3.0-linking-source-exception". As long as you don't make any changes to this library, you can import it as you want without having to release your work under a compatible license (you just need to mention this library, its license and a link to the sources of the version your are using).


> Post-mortem: my gemlog was not accessible over IPv4 just after the "upgrade" because I forgot to forward port 1965 in the snid configuration. This prevented gemini://warmedal.se/~antenna/ from fetching it. This has now been fixed (anyway you should switch to IPv6 :)


📅 2023-09-06


Back to the index


Send me a comment or feedback

-- Response ended

-- Page fetched on Tue May 14 02:01:52 2024