proxied-a.ech.jelle.devnot offered (no ECH extension)split (inner CH forwarded)TLS (HTTP/2)proxied-a.ech.jelle.devnot offered| Domain | :443 (h2 + h3) | :444 (h2 only) | :446 (h3 only) | Mode |
|---|---|---|---|---|
| proxied-a | visit | visit | visit | split-mode ECH |
| proxied-b | visit | visit | visit | split-mode ECH |
| direct | visit | visit | visit | passthrough ECH |
| noech | visit | visit | visit | no ECH (GREASE) |
| public | visit | visit | visit | outer SNI, no ECH |
:443 = TCP + UDP (browser upgrades to h3 via alt-svc) | :444 = TCP only (no QUIC) | :446 = QUIC only (no TCP fallback)
H3 notes: The :446 endpoints rely entirely on HTTPS DNS records. Your browser needs a resolver that supports them (e.g. DoH) or these links won't work. Even then, both Firefox and Chrome may fail to load the noech and public endpoints on :446, since their HTTPS records lack ECH configs and browsers tend to treat non-ECH records as optional. The ECH-enabled endpoints (proxied-a, proxied-b, direct) work most reliably over H3. On :443, both HTTPS records and alt-svc headers advertise H3, so upgrades are more likely, but your browser may still prefer H2.
All traffic enters through an ECH split-mode proxy on port :443 (TCP+UDP), :444 (TCP only), and :446 (QUIC only). The proxy peeks at the TLS/QUIC ClientHello, attempts ECH decryption, and routes by SNI:
AcceptedInnerDirect.Accepted).Ignored).Backend servers support HTTP/2 (via ALPN) and advertise alt-svc: h3 on :443 so browsers upgrade to QUIC/HTTP3. The :444 backends do not advertise alt-svc. The :446 port is QUIC-only (no TCP fallback) for testing H3 directly.
The proxy communicates metadata to backends via PROXY protocol v2 (TLS) or a metadata UDP datagram (QUIC), shown in the blue 'Proxy metadata' box above.
All components are built with rustls (TLS 1.3 + ECH), quinn (QUIC), and hickory-dns (DNS + DoH). Source: rustls-server-ech-demo.
Served by our own authoritative DNS + DoH server. Browsers query these via DoH to discover ECH configs and ALPN protocols.
ech.jelle.dev. 60 IN A 165.232.148.125 ech.jelle.dev. 60 IN AAAA 2604:a880:4:1d0:0:2:4b59:1000 ech.jelle.dev. 60 IN HTTPS 1 . alpn=h3,h2,http/1.1, _444._https.ech.jelle.dev. 60 IN HTTPS 1 ech.jelle.dev. alpn=h2,http/1.1, _446._https.ech.jelle.dev. 60 IN HTTPS 1 ech.jelle.dev. alpn=h3, direct.ech.jelle.dev. 60 IN A 165.232.148.125 direct.ech.jelle.dev. 60 IN AAAA 2604:a880:4:1d0:0:2:4b59:1000 direct.ech.jelle.dev. 60 IN HTTPS 1 . alpn=h3,h2,http/1.1, ech=[version=0xfe0d config_id=1 kem=X25519 public_name=public.ech.jelle.dev max_name_len=64] _444._https.direct.ech.jelle.dev. 60 IN HTTPS 1 direct.ech.jelle.dev. alpn=h2,http/1.1, ech=[version=0xfe0d config_id=1 kem=X25519 public_name=public.ech.jelle.dev max_name_len=64] _446._https.direct.ech.jelle.dev. 60 IN HTTPS 1 direct.ech.jelle.dev. alpn=h3, ech=[version=0xfe0d config_id=1 kem=X25519 public_name=public.ech.jelle.dev max_name_len=64] noech.ech.jelle.dev. 60 IN A 165.232.148.125 noech.ech.jelle.dev. 60 IN AAAA 2604:a880:4:1d0:0:2:4b59:1000 noech.ech.jelle.dev. 60 IN HTTPS 1 . alpn=h3,h2,http/1.1, _444._https.noech.ech.jelle.dev. 60 IN HTTPS 1 noech.ech.jelle.dev. alpn=h2,http/1.1, _446._https.noech.ech.jelle.dev. 60 IN HTTPS 1 noech.ech.jelle.dev. alpn=h3, proxied-a.ech.jelle.dev. 60 IN A 165.232.148.125 proxied-a.ech.jelle.dev. 60 IN AAAA 2604:a880:4:1d0:0:2:4b59:1000 proxied-a.ech.jelle.dev. 60 IN HTTPS 1 . alpn=h3,h2,http/1.1, ech=[version=0xfe0d config_id=1 kem=X25519 public_name=public.ech.jelle.dev max_name_len=64] _444._https.proxied-a.ech.jelle.dev. 60 IN HTTPS 1 proxied-a.ech.jelle.dev. alpn=h2,http/1.1, ech=[version=0xfe0d config_id=1 kem=X25519 public_name=public.ech.jelle.dev max_name_len=64] _446._https.proxied-a.ech.jelle.dev. 60 IN HTTPS 1 proxied-a.ech.jelle.dev. alpn=h3, ech=[version=0xfe0d config_id=1 kem=X25519 public_name=public.ech.jelle.dev max_name_len=64] proxied-b.ech.jelle.dev. 60 IN A 165.232.148.125 proxied-b.ech.jelle.dev. 60 IN AAAA 2604:a880:4:1d0:0:2:4b59:1000 proxied-b.ech.jelle.dev. 60 IN HTTPS 1 . alpn=h3,h2,http/1.1, ech=[version=0xfe0d config_id=1 kem=X25519 public_name=public.ech.jelle.dev max_name_len=64] _444._https.proxied-b.ech.jelle.dev. 60 IN HTTPS 1 proxied-b.ech.jelle.dev. alpn=h2,http/1.1, ech=[version=0xfe0d config_id=1 kem=X25519 public_name=public.ech.jelle.dev max_name_len=64] _446._https.proxied-b.ech.jelle.dev. 60 IN HTTPS 1 proxied-b.ech.jelle.dev. alpn=h3, ech=[version=0xfe0d config_id=1 kem=X25519 public_name=public.ech.jelle.dev max_name_len=64] public.ech.jelle.dev. 60 IN A 165.232.148.125 public.ech.jelle.dev. 60 IN AAAA 2604:a880:4:1d0:0:2:4b59:1000 public.ech.jelle.dev. 60 IN HTTPS 1 . alpn=h3,h2,http/1.1, _444._https.public.ech.jelle.dev. 60 IN HTTPS 1 public.ech.jelle.dev. alpn=h2,http/1.1, _446._https.public.ech.jelle.dev. 60 IN HTTPS 1 public.ech.jelle.dev. alpn=h3,
Port-prefix records (_444._https.*, _446._https.*) use the bare domain as TargetName (required for Chrome compatibility).