Ensure BoringSSL (bssl) or OpenSSL (with ECH/HPKE support) is installed in your environment.
Create a directory and generate the Encrypted Client Hello (ECH) keys using bssl.
mkdir -p /etc/sdproxy/ech
cd /etc/sdproxy/ech
bssl generate-ech \
-out-ech-config-list ech_config_list.bin \
-out-ech-config ech_config.bin \
-out-private-key ech.key \
-public-name "dns.home.arpa" \
-config-id 1ech_config_list.bin: The public configuration payload advertised to clients via DDR (SVCB/HTTPS records) and HTTP.well-knownendpoints.ech.key: The private key used by sdproxy to decrypt incoming TLS client hellos (supports both raw 32-byte X25519 seeds frombssland PEM-encoded PKCS#8 private keys).ech_config.bin: The single ECH config (unused directly, as the list format is required for DNS records).
Edit your config.yaml to include the absolute paths to the generated ECH files under the server: block.
server:
# ... existing server configuration ...
# Encrypted Client Hello (ECH) — Inbound Listeners (DoT, DoH, DoH3, DoQ)
ech_config_list: "/etc/sdproxy/ech/ech_config_list.bin"
ech_key: "/etc/sdproxy/ech/ech.key"When configured, sdproxy automatically:
- Binds the ECH keys to all TLS/QUIC listeners (DoT, DoH, DoH3, DoQ).
- Advertises the
ech=parameter in_dns.resolver.arpaand resolver-hostname DDR responses. - Serves the public ECH configuration over HTTPS at
/.well-known/origin-svcb(JSON perdraft-ietf-tls-wkech) and/.well-known/ech(application/echconfig-list).
To enable ECH when sdproxy connects to upstream encrypted resolvers:
server:
# Options: "disable" (default), "try" (fallback to plaintext SNI on failure), "strict"
use_upstream_ech: "try"
# SVCB target validation mode: "strict" (default), "loose", "apex", "any"
hostname_ech: "strict"Restart sdproxy to load the credentials.