💾 Archived View for log.pfad.fr › 2023 › finally-reachable-over-ipv6 captured on 2023-09-28 at 15:32:33. Gemini links have been rewritten to link to archived content

View Raw

More Information

⬅️ Previous capture (2023-09-08)

➡️ Next capture (2023-11-04)

🚧 View Differences

-=-=-=-=-=-=-

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:

IPv6 support on sr.ht - sourcehut lists

Specifications

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

Additionally, I wanted to have:

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:

Alt-Svc header - MDN

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