Skip to content

Fix ECH payload size varying per-connection instead of per-process#2

Draft
Copilot wants to merge 2 commits into
masterfrom
copilot/fix-dpi-bypass-possibility
Draft

Fix ECH payload size varying per-connection instead of per-process#2
Copilot wants to merge 2 commits into
masterfrom
copilot/fix-dpi-bypass-possibility

Conversation

Copilot AI commented Apr 5, 2026

Copy link
Copy Markdown

FakeTLS ECH GREASE payload size was determined once at static initialization, making it identical across all connections within a process lifetime — a detectable fingerprint distinguishing it from real Chrome behavior.

Root Cause

Op::ech_payload() computed Random::fast(0, 3) * 32 + 144 during TlsHello::get_default()'s static initializer, locking the ECH payload size (144/176/208/240 bytes) for the entire process.

Fix

Introduces a dedicated EchPayload Op type whose size is drawn from TlsHelloContext, which is constructed fresh per-connection:

// Before: length fixed at process startup
static Op ech_payload() {
  Op res;
  res.type = Type::Random;
  res.length = Random::fast(0, 3) * 32 + 144;  // evaluated once, static
  return res;
}

// After: length computed per-connection via context
TlsHelloContext(...) {
  ech_payload_size_ = static_cast<size_t>(Random::fast(0, 3)) * 32 + 144;
}
  • Added EchPayload to TlsHello::Op::Type enum
  • Op::ech_payload() now returns Type::EchPayload with no embedded length
  • TlsHelloContext stores ech_payload_size_ computed in its constructor (i.e., once per connection)
  • TlsHelloCalcLength and TlsHelloStore query context->get_ech_payload_size() when handling EchPayload ops

Copilot AI linked an issue Apr 5, 2026 that may be closed by this pull request
Copilot AI changed the title [WIP] Fix possible DPI bypass detection issue Fix ECH payload size varying per-connection instead of per-process Apr 5, 2026
Copilot AI requested a review from chipitsine April 5, 2026 14:45
@chipitsine chipitsine requested a review from Copilot April 5, 2026 16:52

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR removes a per-process fingerprint in FakeTLS ECH GREASE generation by making the ECH payload length vary per connection (matching Chrome’s per-connection variability) instead of being fixed at static initialization time.

Changes:

  • Added a new TlsHello::Op::Type::EchPayload operation to represent ECH GREASE payload generation without embedding a static length.
  • Introduced per-connection ech_payload_size_ in TlsHelloContext, computed in the context constructor.
  • Updated TlsHelloCalcLength and TlsHelloStore to size and fill EchPayload using TlsHelloContext::get_ech_payload_size().

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

dpi bypass possibility

3 participants