Let a caller drop status_request, and stop hard-coding Proxy-Connection - #45
Merged
Merged
Conversation
Two more places where an identity could be described but not presented. **`tls.omitExtensions`** is the subtractive counterpart to `extraExtensions`. `status_request` (5) is what it exists for: that is the one extension this package sends which curl does not, so a sample without it could not be matched at all. Ordering cannot help — orderExtensions arranges what was built — and there was no other way to unbuild it. Dropping it gives up OCSP stapling, which is the only revocation signal this package consumes. With `trust.revocation: 'require-staple'` that combination is not a stricter policy, it is one that can never be satisfied: no staple is requested, so none arrives, so every connection fails on a certificate that was never asked to carry one. Refused at configuration time, where both settings are visible, rather than at handshake time where it looks like a server problem. **`proxy.proxyConnection`** replaces a hard-coded `Proxy-Connection: keep-alive` on the CONNECT request. The header is pre-standard and never reached a spec; clients disagree about it, some sending keep-alive, some close, some nothing. The origin never sees it — the proxy always does — so for anyone matching a client's behaviour AT THE PROXY it is part of the fingerprint. The default is unchanged, since keep-alive avoids a class of proxy that closes the tunnel after one request. `null` omits the header, which is not the same as sending `close`. That one nearly repeated a bug this repo has now fixed twice. `normalise()` REBUILDS the proxy config rather than copying it, so a field not named in its return literal is dropped without a word — exactly how `http2ConnectionWindow` came to be declared in a profile and read by nothing. The field is listed explicitly and the reason is written next to it. Both omissions are reproduced on a HelloRetryRequest retry, for the same reason the extension order is: a second hello that changed its extension set would be malformed under RFC 8446 s4.1.2 and a signal in itself. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Two more places where an identity could be described but not presented.
tls.omitExtensionsThe subtractive counterpart to
extraExtensions.status_request(5) is what it exists for —the one extension this package sends that curl does not, so a sample without it could not be matched
at all. Ordering cannot help (
orderExtensionsarranges what was built), and there was no otherway to unbuild it.
Dropping it gives up OCSP stapling, the only revocation signal this package consumes. With
trust.revocation: 'require-staple'that combination is not a stricter policy — it is one that cannever be satisfied: no staple is requested, so none arrives, so every connection fails on a
certificate never asked to carry one. Refused at configuration time, where both settings are
visible, rather than at handshake time where it looks like a server problem.
proxy.proxyConnectionReplaces a hard-coded
Proxy-Connection: keep-aliveon the CONNECT request. The header ispre-standard and never reached a spec; clients disagree — some send
keep-alive, someclose, somenothing. The origin never sees it; the proxy always does, so for anyone matching a client's
behaviour at the proxy it is part of the fingerprint.
Default unchanged (
keep-aliveavoids a class of proxy that closes the tunnel after one request).nullomits the header, which is not the same as sendingclose.This nearly repeated a bug fixed twice already
normalise()rebuilds the proxy config rather than copying it, so a field not named in itsreturn literal is dropped without a word — exactly how
http2ConnectionWindowcame to be declaredin a profile and read by nothing. The field is listed explicitly with the reason written next to it.
Both omissions are reproduced on a HelloRetryRequest retry, for the same reason the extension order
is: a second hello that changed its extension set would be malformed under RFC 8446 §4.1.2 and a
signal in itself.
Version → 1.11.0. 1260 offline tests pass.
🤖 Generated with Claude Code