-
Notifications
You must be signed in to change notification settings - Fork 335
Размер шума в FakeTLS ServerHello не соответствует реальным сертификатам #408
Description
Привет!
Обнаружил проблему с детектируемостью FakeTLS handshake. Сейчас шум в ServerHello генерируется в фиксированном диапазоне 2500-4700 байт (generateNoise в server_side.go), но реальные размеры зашифрованной части хэндшейка у разных доменов сильно отличаются.
Суть проблемы:
При FakeTLS handshake mtg после ServerHello + ChangeCipherSpec отправляет ApplicationData-запись со случайным шумом 2500-4700 байт, имитирующую зашифрованную часть хэндшейка (EncryptedExtensions + Certificate + CertificateVerify + Finished).
Но реальный размер этих данных зависит от цепочки сертификатов домена, указанного в секрете. Я измерил реальные размеры ApplicationData в TLS handshake для популярных доменов, которые обычно используют как fronting:
| Домен | Реальный размер (байт) | В диапазоне 2500-4700? |
|---|---|---|
github.com |
2932 | да |
www.wikipedia.org |
2968 | да |
www.cloudflare.com |
2984 | да |
www.google.com |
3953 | да |
ajax.googleapis.com |
4365 | да |
cdn.jsdelivr.net |
5488 | нет (+17%) |
www.apple.com |
5119 | нет (+9%) |
amazon.com |
6053 | нет (+29%) |
dl.google.com |
6480 | нет (+38%) |
www.microsoft.com |
8169 | нет (+74%) |
microsoft.com |
13004 | нет (+177%) |
login.microsoftonline.com |
4108-6121 | нестабильно |
Текущий диапазон 2500-4700 покрывает примерно треть популярных доменов. Для остальных — шум значительно меньше реального сертификата. DPI может сравнить размер ApplicationData с реальным размером сертификата для домена из SNI в ClientHello — если расхождение большое, это признак FakeTLS.
Особенно критично для dl.google.com (часто используется по умолчанию) — реальный размер ~6480, а mtg отправляет максимум 4700.
Также интересно: login.microsoftonline.com возвращает разные размеры (4108 vs 6121) — видимо, балансировка на серверы с разными сертификатами. Это подтверждает, что статический диапазон не может правильно имитировать все домены.
Предлагаемое решение:
При старте прокси делать несколько реальных TLS-соединений к домену из секрета и измерять фактический размер зашифрованных данных хэндшейка (суммарный payload всех ApplicationData записей между CCS и началом application data). Затем использовать измеренный размер ± jitter вместо захардкоженного диапазона. Fallback на текущий диапазон 2500-4700, если проба не удалась.
У себя в форке я уже реализовал это с кэшированием результатов между перезапусками и конфигурируемым количеством проб: dolonet@f2ea186
Если идея ок, могу подготовить чистый PR в mtg.