Add dynamic cert noise calibration for FakeTLS handshake#409
Add dynamic cert noise calibration for FakeTLS handshake#4099seconds merged 2 commits into9seconds:masterfrom
Conversation
The hardcoded noise range (2500-4700 bytes) in the FakeTLS ServerHello does not match the real certificate chain sizes of many popular fronting domains (e.g., dl.google.com ≈ 6480 bytes, microsoft.com ≈ 13004 bytes). This makes the proxy detectable by DPI systems that compare the ApplicationData size with the real cert chain size for the SNI domain. On startup, probe the fronting domain's actual TLS handshake size and use the measured value ± jitter instead of the static range. Falls back to the legacy 2500-4700 range if the probe fails. Also adds optional caching of probe results between restarts (noise-cache-path, noise-cache-ttl) and a configurable probe count (noise-probe-count) under [defense.doppelganger]. Closes 9seconds#408
|
А подскажите, по итогу какие домены лучше использоваться по FakeTLS? Я взял mail.ru и не понимаю, хороший это выбор или нет. Обязательно ли [defense.doppelganger] прописывать связанный с mail.ru в этом случае? Уже пару дней есть жалобы от друзей с Мегафона (Москва) - на нем через раз подключается к mtg клиент. |
9seconds
left a comment
There was a problem hiding this comment.
Спасибо большое, хороший PR. Самое основное - тут идет дублирование логики уже существующего компонента, который прямо и создавался с целью поизмерить что-то в TLS фронта. Давайте попробуем туда перенести.
Кроме того, хотелось бы ничего на диске не хранить. Уже в первом приближении можно получить достаточно хорошие результаты, чтобы не возится с дисковым состоянием
| @@ -0,0 +1,261 @@ | |||
| package fake | |||
There was a problem hiding this comment.
Мне кажется, это лучше перенести в doppelganger/scout. Скаут как раз и задумывался как некоторый такой паук, который ходит к фронту и собирает с него некую статистику. Там уже есть периодичность.
Да, сейчас он только про сбор задержек по списку урлов, но, возможно, имеет смысл именно его модифицировать, чтобы он ходил на / по умолчанию.
Хочется просто не распылять сервисные обращения к фронту с целью получить какую-то стастистку, а хранить все в одном месте.
| return CertProbeResult{Mean: cache.Mean, Jitter: cache.Jitter}, true | ||
| } | ||
|
|
||
| // SaveCachedProbe writes a probe result to path as JSON. |
There was a problem hiding this comment.
Я не уверен, стоит ли хранить это состояние на диске. Буквально в первую секунду работы прокси первым же запросом можно получить довольно хорошее приближение (а скорее всего, даже нормальное число) этого размера. Мне кажется, стоит таким состоянием пренебречь. Все-таки отсутствие внешнего стейта сильно всегда упрощает дело, не надо возиться с устареваним и так далее.
| return os.WriteFile(path, data, 0o644) //nolint: gosec | ||
| } | ||
|
|
||
| // ProbeCertSize connects to hostname:port via TLS multiple times and measures |
There was a problem hiding this comment.
Да, тут прямо дублируется логика скаута. Давайте эту функциональность туда перенесем?
| return capture.appDataBytes, nil | ||
| } | ||
|
|
||
| // recordCapture wraps a net.Conn and parses the raw TLS record stream to |
There was a problem hiding this comment.
Да, посмотрите в сторону скаута, пожалуйста. Там даже такая логика есть
Instead of a separate cert_probe.go that duplicates the scout's TLS connection logic, measure the cert chain size directly from the same HTTPS connections the scout already makes. Changes: - Extend ScoutConnResult with payloadLen field - Add Write interception to ScoutConn for handshake boundary detection - Scout.learn() now computes cert size (sum of ApplicationData between CCS and first client Write) alongside inter-record durations - Ganger aggregates cert sizes across raids and exposes NoiseParams() via atomic pointer for lock-free reads from proxy goroutines - Proxy reads NoiseParams from Ganger on each handshake instead of probing at startup - Remove cert_probe.go, disk cache, and related config options (noise-cache-path, noise-cache-ttl, noise-probe-count) Falls back to legacy 2500-4700 range until the first scout raid completes (typically within 1-2 seconds of startup).
7a2a3fc to
9dfd992
Compare
|
Переработал по замечаниям.
Все тесты проходят, включая |
Closes #408
Summary
The hardcoded noise range (2500-4700 bytes) in the FakeTLS ServerHello doesn't match the real certificate chain sizes for many popular fronting domains. This makes the proxy detectable by DPI that compares ApplicationData size with the actual cert chain size for the SNI domain.
Measured sizes for popular domains:
github.comwww.google.comcdn.jsdelivr.netdl.google.comwww.microsoft.commicrosoft.comChanges
noise-cache-path,noise-cache-ttl)noise-probe-count, default 15)NoiseParams{}preserves legacy behaviorNew config options under
[defense.doppelganger]:Test plan
SendServerHellosignatureTestCalibratedNoiseSizeverifies noise is within mean ± jitterdl.google.com— probe correctly returns mean=6480