Post Quantum Caddy

Hello guys,
thank for this nice project.

1. The problem I’m having:

I’m trying to compile caddy with support for PQC so X25519MLKEM768 or X25519Kyber768Draft00.

I tried multiple go version, because the behavior is different from what’s mentioned here:

I tried using sam-burns blog post steps.
And using caddy commit from july 2024, but failed also.

2. Error messages and/or full log output:

$ curl -vv -k https://localhost 2>&1  | grep "SSL connection"
* SSL connection using TLSv1.3 / TLS_AES_128_GCM_SHA256 / X25519 / id-ecPublicKey

3. Caddy version:

5c47c2f147e5bef44fc8cb48a655d31f5a2a817c (30 Aug 24 15:01 UTC)
Also tried a version from february.

4. How I installed and ran Caddy:

Compiled from source once: tried with:

a. System environment:

docker
Linux 9ddf86fd45ee 6.11.0-17-generic #17~24.04.2-Ubuntu SMP PREEMPT_DYNAMIC Mon Jan 20 22:48:29 UTC 2 x86_64 GNU/Linux

docker run --rm -p 443:443 -v ./share:/share -it golang:1.23 bash
docker run --rm -p 443:443 -v ./share:/share -it golang:1.24 bash

b. Command:

caddy file-server --root /var/www/html/public/ --domain localhost
caddy run --config Caddyfile

d. My complete Caddy config:

Tried this config from here: Revisions · Compile Caddy with support for post-quantum key agreement (X25519+Kyber) · GitHub

localhost {
    reverse_proxy https://pq.cloudflareresearch.com {
        header_up Host {upstream_hostport}
        transport http {
            tls_curves X25519Kyber768Draft00 x25519 secp256r1
        }
    }
}

Here it’s mentioned that somehow the curves config should be nil. So I tried using this commit also : 2bc1e11ce514d0e42dc240ed0bba397b1e7f8f23

If you have pointers about which, go version, the commit hash and the config, it would help a lot :slight_smile:

Thank you.

This commit adds PQC:

Build with Go 1.24.

Although, upon looking at that, I noticed a typo – it probably won’t affect you testing from that commit, but I fixed it in this commit:

i.e. just build from the latest commit on master with Go 1.24 and you should get PQC.

2 Likes

Hello Matt,

thank for the reply! Appreciate it.

It’s still not working on my side, maybe my Caddyfile is not correct.

Caddyfile

localhost {
    reverse_proxy https://pq.cloudflareresearch.com {
        header_up Host {upstream_hostport}
        transport http {
            tls_curves x25519mlkem768
        }
    }
}

Compilation with Go 1.24

docker run --rm -p 443:443 -v ./share:/share -it golang:1.24 bash
cd /root
git clone https://github.com/caddyserver/caddy
cd caddy/cmd/caddy/
go build
cp caddy /share/caddy_04_03_2025

Curl

curl -vv https://localhost/ 2>&1 | grep "connection"
* SSL connection using TLSv1.3 / TLS_AES_128_GCM_SHA256 / X25519 / id-ecPublicKey

Wireshark

Key Share Entry: Group: x25519, Key Exchange length: 32

Expected

I’m kind of expecting x25519mlkem768 instead of x25519, correct ?

Run

sudo ./caddy_04_03_2025 run --config Caddyfile
2025/03/04 12:34:36.859	INFO	maxprocs: Leaving GOMAXPROCS=8: CPU quota undefined
2025/03/04 12:34:36.859	INFO	GOMEMLIMIT is updated	{"package": "github.com/KimMachineGun/automemlimit/memlimit", "GOMEMLIMIT": 14910695424, "previous": 9223372036854775807}
2025/03/04 12:34:36.860	INFO	using config from file	{"file": "Caddyfile"}
2025/03/04 12:34:36.860	INFO	adapted config to JSON	{"adapter": "caddyfile"}
2025/03/04 12:34:36.860	WARN	Caddyfile input is not formatted; run 'caddy fmt --overwrite' to fix inconsistencies	{"adapter": "caddyfile", "file": "Caddyfile", "line": 2}
2025/03/04 12:34:36.861	INFO	admin	admin endpoint started	{"address": "localhost:2019", "enforce_origin": false, "origins": ["//[::1]:2019", "//127.0.0.1:2019", "//localhost:2019"]}
2025/03/04 12:34:36.861	INFO	http.auto_https	server is listening only on the HTTPS port but has no TLS connection policies; adding one to enable TLS	{"server_name": "srv0", "https_port": 443}
2025/03/04 12:34:36.861	INFO	http.auto_https	enabling automatic HTTP->HTTPS redirects	{"server_name": "srv0"}
2025/03/04 12:34:36.861	INFO	tls.cache.maintenance	started background certificate maintenance	{"cache": "0xc0001b3100"}
2025/03/04 12:34:36.862	INFO	http	enabling HTTP/3 listener	{"addr": ":443"}
2025/03/04 12:34:36.862	INFO	http.log	server running	{"name": "srv0", "protocols": ["h1", "h2", "h3"]}
2025/03/04 12:34:36.862	WARN	http	HTTP/2 skipped because it requires TLS	{"network": "tcp", "addr": ":80"}
2025/03/04 12:34:36.862	WARN	http	HTTP/3 skipped because it requires TLS	{"network": "tcp", "addr": ":80"}
2025/03/04 12:34:36.862	INFO	http.log	server running	{"name": "remaining_auto_https_redirects", "protocols": ["h1", "h2", "h3"]}
2025/03/04 12:34:36.862	INFO	http	enabling automatic TLS certificate management	{"domains": ["localhost"]}
2025/03/04 12:34:36.862	INFO	pki.ca.local	root certificate is already trusted by system	{"path": "storage:pki/authorities/local/root.crt"}
2025/03/04 12:34:36.862	WARN	tls	unable to get instance ID; storage clean stamps will be incomplete	{"error": "invalid UUID length: 0"}
2025/03/04 12:34:36.862	INFO	autosaved config (load with --resume flag)	{"file": "/root/.config/caddy/autosave.json"}
2025/03/04 12:34:36.862	INFO	serving initial configuration
2025/03/04 12:34:36.874	INFO	tls	storage cleaning happened too recently; skipping for now	{"storage": "FileStorage:/root/.local/share/caddy", "instance": "00000000-0000-0000-0000-000000000000", "try_again": "2025/03/05 12:34:36.874", "try_again_in": 86399.999999378}
2025/03/04 12:34:36.874	INFO	tls	finished cleaning storage units

Thank you :slight_smile:

Up :slight_smile:

Honestly, I don’t know – I’m not sure how individual clients are configured. Many may not even enable PQC yet, I dunno. (I’ve been very busy lately, sorry.)

If someone wants to dive deep to answer the question, that’d be welcomed!