Skip to content

Размер шума в FakeTLS ServerHello не соответствует реальным сертификатам #408

@dolonet

Description

@dolonet

Привет!

Обнаружил проблему с детектируемостью 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions