Match real Codex CLI TLS fingerprint for OpenAI OAuth forwarding - #6300
Open
JnyRoad wants to merge 2 commits into
Open
Match real Codex CLI TLS fingerprint for OpenAI OAuth forwarding#6300JnyRoad wants to merge 2 commits into
JnyRoad wants to merge 2 commits into
Conversation
Codex OAuth traffic was going out over Go's default crypto/tls ClientHello, which is trivially distinguishable from the real Codex CLI (reqwest 0.12 + rustls 0.23, aws_lc_rs provider, no http2 feature): the cipher suite table, supported_groups, and extension set all differ, and real Codex CLI never sends ALPN. Add a Profile matching the real client's cipher suites / groups / point formats / extension set, sourced from the official openai/codex source (codex-rs/http-client) cross-checked against three independent packet captures. Real rustls clients also reshuffle their ClientHello extension order on every connection; a permanently fixed order is itself a distinguishing signal. Give tlsfingerprint.Profile a RandomizeExtensionOrder switch that shuffles the extension list once per TLS connection, off by default so the existing Claude Code / Node.js profile is unaffected, and turn it on for the new Codex profile. Wire the profile into doOpenAIUpstream: an account's explicitly configured TLS fingerprint (if any) still wins, otherwise Codex OAuth accounts get the new profile automatically rather than requiring a manual per-account opt-in. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Contributor
|
All contributors have signed the CLA. ✅ |
Author
I have read the CLA Document and I hereby sign the CLA |
Author
|
recheck |
doOpenAIUpstream now always calls DoWithTLS instead of Do (needed to thread the Codex TLS fingerprint profile through). Three more service.HTTPUpstream test fakes used by Grok credential-failover, Responses failover-cancel, and Images failover tests embedded the interface without overriding DoWithTLS, so calls fell through to the embedded nil interface and were silently swallowed upstream, leaving recorded account IDs empty instead of failing loudly. Mirrors the same passthrough-to-Do pattern already applied to the other three fakes in openai_gateway_handler_test.go. Verified: go test -tags unit ./... and go vet -tags integration ./... both clean. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Author
|
I have read the CLA Document and I hereby sign the CLA |
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.
Summary
crypto/tlsClientHello, which is trivially distinguishable from the real Codex CLI: cipher suite table,supported_groups, and extension set all differ, and real Codex CLI (reqwest 0.12 + rustls 0.23,aws_lc_rsprovider, compiled without thehttp2feature — confirmed from the officialopenai/codexsource,codex-rs/http-client) never sends ALPN at all.tlsfingerprint.Profilematching the real client's cipher suites /supported_groups/ec_point_formats/ extension set, cross-checked against three independent packet captures of a realcodex-tuisession (seespecs/002-codex-tls-fingerprint/research.mdfor the full evidence trail — this doc isn't part of the diff, kept locally).RandomizeExtensionOrderswitch totlsfingerprint.Profilethat shuffles the extension list once per TLS connection; off by default so the existing Claude Code / Node.js profile is unaffected, on for the new Codex profile.doOpenAIUpstream: an account's explicitly configured TLS fingerprint (via the existingTLSFingerprintProfileService) still wins if set; otherwise OpenAI Codex OAuth accounts get the new profile automatically instead of requiring a manual per-account opt-in. Non-OAuth / non-OpenAI accounts are unaffected.Test plan
go build ./...andgo vet ./...cleango test ./...— full repo, 0 failures (caught and fixed a real regression along the way: threeinternal/handlertest fixtures embeddedservice.HTTPUpstreamand only overrodeDo, panicking oncedoOpenAIUpstreamstarted callingDoWithTLSunconditionally — added matchingDoWithTLSoverrides)wire_gen.goregenerated viagoogle/wire(not hand-edited) after adding the new DI wiring🤖 Generated with Claude Code