What ECH Status Information Is Available in CFnew Response Headers
CFnew exposes Encrypted Client Hello (ECH) status through the custom HTTP headers X-ECH-Status and X-ECH-Config-Length, which are added to responses when ECH is enabled and a configuration is successfully retrieved.
The byJoey/cfnew repository implements ECH support within its Cloudflare Worker architecture, providing real-time visibility into TLS handshake encryption states via response metadata. These headers allow client applications, monitoring tools, and the built-in UI to verify whether ECH protection is active and validate the size of the cryptographic configuration fetched from DNS-over-HTTPS (DoH) resolvers.
Available ECH Response Headers
CFnew conditionally injects ECH-related headers based on the global enableECH flag and the presence of a valid echConfig object. The current implementation emits two functional headers, with a third documented but inactive.
X-ECH-Status Header
The X-ECH-Status header appears only when the enableECH configuration option is set to true. Its value is always the string ENABLED, serving as a boolean indicator that the Encrypted Client Hello feature is active for the current request. When ECH is disabled or the feature flag is off, this header is omitted entirely rather than returning a negative value.
X-ECH-Config-Length Header
The X-ECH-Config-Length header contains the length of the binary ECH configuration as a decimal string (e.g., "32"). This header is injected only when both enableECH is true and a valid echConfig has been successfully retrieved from the DoH resolver. The length value corresponds to echConfig.length in the Worker source, providing a quick sanity check that configuration data was actually fetched and parsed.
X-ECH-Debug Header (Documented but Not Implemented)
While the README references a X-ECH-Debug header intended to carry detailed troubleshooting strings (such as "SUCCESS" or "FAILED"), the current source code in the main branch does not emit this header. It remains a planned feature in the documented contract but should not be expected in production responses.
How CFnew Injects ECH Headers
The header injection logic resides in the main Worker script (明文源吗), specifically within the response construction block. The code builds a headers object dynamically, appending ECH metadata only when the prerequisite conditions are met:
// In src/明文源吗 (lines 2769-2774)
const responseHeaders = {
'Content-Type': contentType,
'Cache-Control': 'no-store, no-cache, must-revalidate, max-age=0',
};
if (enableECH) {
responseHeaders['X-ECH-Status'] = 'ENABLED';
if (echConfig) {
responseHeaders['X-ECH-Config-Length'] = String(echConfig.length);
}
}
This implementation ensures that header consumers can rely on the presence of X-ECH-Config-Length as a secondary confirmation that ECH configuration retrieval succeeded, not just that the feature flag is enabled.
Consuming ECH Headers in Client Applications
Front-end and programmatic clients can read these headers to conditionally handle ECH-enabled connections or display status indicators.
Fetching ECH Status with Node.js
Use the standard fetch API to inspect headers before processing the subscription payload:
fetch('https://your-worker.example.com/sub')
.then(response => {
const echStatus = response.headers.get('X-ECH-Status');
const configLength = response.headers.get('X-ECH-Config-Length');
console.log('ECH Enabled:', echStatus === 'ENABLED');
console.log('Config Size:', configLength ? `${configLength} bytes` : 'N/A');
return response.text();
})
.then(data => console.log('Subscription:', data))
.catch(err => console.error('Request failed:', err));
Using Headers in Downstream Cloudflare Workers
When chaining CFnew behind another Worker, inspect the headers to implement conditional routing or logging:
addEventListener('fetch', event => {
event.respondWith(handleRequest(event.request));
});
async function handleRequest(request) {
const resp = await fetchSubscription(request);
const echStatus = resp.headers.get('X-ECH-Status');
if (echStatus === 'ENABLED') {
const configSize = resp.headers.get('X-ECH-Config-Length');
console.log(`ECH active with ${configSize} bytes of config`);
// Implement ECH-specific logic here
}
return resp;
}
Displaying Status in Browser Applications
The built-in UI in 明文源吗 (lines 6310-6315) demonstrates client-side header consumption:
const echStatusHeader = response.headers.get('X-ECH-Status');
const echConfigLength = response.headers.get('X-ECH-Config-Length');
if (echStatusHeader === 'ENABLED') {
echStatusEl.innerHTML = `ECH状态: <span style="color:#00ff9d;">✅ 已启用${echConfigLength ? ' (配置长度: ' + echConfigLength + ')' : ''}</span>`;
} else {
echStatusEl.innerHTML = 'ECH状态: <span style="color:#ffb400;">⚠️ 未启用</span>';
}
A minimal standalone implementation:
<!DOCTYPE html>
<html>
<body>
<pre id="echInfo">Loading…</pre>
<script>
fetch('/sub')
.then(r => {
const status = r.headers.get('X-ECH-Status') || 'DISABLED';
const length = r.headers.get('X-ECH-Config-Length') || '-';
document.getElementById('echInfo').textContent =
`ECH status: ${status}\nECH config length: ${length}`;
})
.catch(err => console.error(err));
</script>
</body>
</html>
Summary
- CFnew emits two functional ECH headers:
X-ECH-Status(value:ENABLED) andX-ECH-Config-Length(decimal string of byte count). - Headers are conditional: They appear only when
enableECHis true and, for the length header, whenechConfigis successfully populated. - Source location: Header injection occurs in
明文源吗around lines 2769-2774, with UI consumption logic at lines 6310-6315. - X-ECH-Debug is placeholder: Documented in the README but not currently implemented in the Worker code.
- Consumption pattern: Check for header presence using
headers.get(), as omitted headers indicate disabled or unconfigured ECH states.
Frequently Asked Questions
What value does the X-ECH-Status header return when ECH is disabled?
When ECH is disabled, the X-ECH-Status header is omitted entirely from the response. The code only adds this header inside the if (enableECH) block, so its absence indicates that the global ECH flag is false or the feature is not configured.
How can I verify that the ECH configuration was actually fetched?
Check for the presence of the X-ECH-Config-Length header. This header is only added when the echConfig variable contains data, meaning the DNS-over-HTTPS lookup succeeded and returned valid ECH configuration bytes. If only X-ECH-Status appears without the length header, ECH is enabled but configuration retrieval failed.
Why doesn't the X-ECH-Debug header appear in my responses?
The X-ECH-Debug header is documented in the README as part of the design specification but is not emitted by the current implementation in 明文源吗. The active code only generates X-ECH-Status and X-ECH-Config-Length, making debug information currently unavailable in standard responses.
Which file contains the logic for adding ECH headers to responses?
The header injection logic is located in the 明文源吗 file (the main Worker script) at approximately lines 2769-2774, where the response headers object is constructed conditionally based on the enableECH flag and echConfig availability.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →