Бот отправляет идеальный User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36.... Cookies на месте, JavaScript выполняется, Canvas-отпечаток совпадает с эталонным. Казалось бы — обычный пользователь Windows. Но один SYN-пакет выдаёт правду: это Linux-сервер в дата-центре. Технология, которая делает это возможным, называется TCP fingerprinting — пассивное определение операционной системы по параметрам TCP-стека. В этой статье мы разберём, как она работает, почему её нельзя обмануть программными средствами и как она применяется для защиты рекламного бюджета от ботов.
Что происходит до HTTP: TCP-рукопожатие
Прежде чем браузер отправит HTTP-запрос, прежде чем сработает любой JavaScript-детектор, происходит нечто фундаментальное — TCP-рукопожатие (three-way handshake). Это три пакета, которые устанавливают соединение между клиентом и сервером:
- SYN — клиент отправляет серверу запрос на соединение.
- SYN-ACK — сервер подтверждает и отправляет свои параметры.
- ACK — клиент подтверждает, соединение установлено.
- Windows 10/11: 64240 байт
- Linux (ядро 5.x–6.x): 29200 байт
- macOS Sonoma: 65535 байт
- Windows: 128
- Linux: 64
- macOS: 64
- Модифицировать ядро Linux. Пересобрать ядро с изменёнными значениями
tcp_init_sock(),tcp_options_write()и десятками других функций сетевого стека. Это требует глубокой экспертизы в ядре Linux и делает систему нестабильной. - Использовать raw sockets. Формировать TCP-пакеты вручную, минуя стандартный сетевой стек. Это означает реализацию собственного TCP-стека с нуля — управление соединениями, ретрансмиссиями, контролем потока. Практически нереализуемо для полноценного HTTP-клиента.
- Запустить реальную Windows. Использовать виртуальную машину или VDS с Windows. Это работает, но стоит значительно дороже Linux-серверов, сложнее автоматизируется и резко снижает рентабельность ботнета.
Ключевой момент: первый SYN-пакет формируется ядром операционной системы, а не браузером и не приложением. Браузер вызывает системный вызов connect(), а всё остальное — выбор размера окна, установку TTL, порядок TCP-опций — делает сетевой стек ядра. У каждой ОС эти значения по умолчанию различаются, и именно это лежит в основе TCP fingerprinting.
Это принципиально отличает TCP fingerprinting от всех прикладных методов детекции. JavaScript можно подменить, User-Agent — подделать, Canvas-отпечаток — эмулировать. Но параметры SYN-пакета задаёт ядро ОС, и без модификации ядра изменить их невозможно.
Анатомия TCP-отпечатка: пять ключевых параметров
TCP fingerprinting опирается на комбинацию нескольких параметров SYN-пакета. По отдельности каждый из них мало что значит, но вместе они создают уникальную подпись операционной системы.
Window Size (размер окна)
Начальный размер TCP-окна — это количество байт, которое клиент готов принять до получения подтверждения. Каждая ОС использует своё значение по умолчанию:
Это значение жёстко задано в коде сетевого стека. Windows использует 64240 уже много лет — это значение оптимизировано под типичные сетевые условия и не менялось с Windows Vista. Linux использует 29200, что соответствует 20 сегментам по 1460 байт. macOS исторически выставляет максимальное 16-битное значение — 65535.
MSS (Maximum Segment Size)
MSS определяет максимальный размер полезных данных в одном TCP-сегменте. Для Ethernet-подключений стандартное значение — 1460 байт (MTU 1500 минус 20 байт IP-заголовка и 20 байт TCP-заголовка). Это значение одинаково для большинства ОС при прямом Ethernet-подключении, но меняется при использовании VPN или PPPoE, что тоже даёт полезную информацию.
TTL (Time to Live)
TTL — это «время жизни» пакета, счётчик, который уменьшается на единицу при прохождении каждого маршрутизатора. Начальное значение TTL задаётся ОС:
Даже если пакет прошёл через несколько маршрутизаторов и TTL уменьшился, исходное значение легко восстановить — достаточно округлить до ближайшей степени двойки. Если мы получили TTL=119, значит, исходное значение было 128 (Windows), а пакет прошёл 9 маршрутизаторов. Если TTL=52, то исходное значение — 64 (Linux или macOS), и пакет прошёл 12 хопов.
DF (Don’t Fragment) флаг
Флаг DF в IP-заголовке указывает маршрутизаторам не фрагментировать пакет. Современные реализации TCP почти всегда устанавливают DF=1 в SYN-пакетах, используя механизм Path MTU Discovery. Однако некоторые старые или встроенные системы этого не делают, что позволяет отличить их от десктопных ОС.
TCP Options и их порядок
Это самый мощный параметр TCP fingerprinting. TCP-опции — это дополнительные поля в заголовке TCP-сегмента, которые согласовывают расширенные возможности соединения. Критически важен не просто набор опций, а их точный порядок.
Windows 10/11 отправляет опции в следующем порядке:
MSS(1460), NOP, Window Scale(8), NOP, NOP, SACK Permitted
Linux (ядро 5.x–6.x):
MSS(1460), SACK Permitted, Timestamps, NOP, Window Scale(7)
macOS Sonoma:
MSS(1460), NOP, Window Scale(6), NOP, NOP, Timestamps, SACK Permitted, EOL
Обратите внимание: Windows не отправляет опцию Timestamps в SYN-пакете — это одно из самых надёжных различий между Windows и Unix-подобными системами. Linux использует Window Scale(7), macOS — Window Scale(6), Windows — Window Scale(8). Порядок NOP-заполнителей тоже различается.
Эта комбинация опций и их порядок зашиты в исходном коде ядра каждой ОС. Они не настраиваются через пользовательский интерфейс, не меняются при обновлении браузера и не зависят от приложения, инициирующего соединение.
Сводная таблица TCP-отпечатков
| Параметр | Windows 10/11 | Ubuntu 22.04 (Linux 5.15+) | macOS Sonoma | Android 13+ |
|---|---|---|---|---|
| Window Size | 64240 | 29200 | 65535 | 65535 |
| TTL | 128 | 64 | 64 | 64 |
| MSS | 1460 | 1460 | 1460 | 1460 |
| DF flag | 1 | 1 | 1 | 1 |
| Window Scale | 8 | 7 | 6 | 6 |
| SACK Permitted | Да | Да | Да | Да |
| Timestamps | Нет | Да | Да | Да |
| Порядок опций | MSS, NOP, WS, NOP, NOP, SACK | MSS, SACK, TS, NOP, WS | MSS, NOP, WS, NOP, NOP, TS, SACK, EOL | MSS, NOP, WS, NOP, NOP, TS, SACK, EOL |
Эта таблица — не теоретическая модель. Это реальные данные, собранные с продакшн-серверов. Каждая строка представляет десятки тысяч проанализированных SYN-пакетов.
Обратите внимание на Android и macOS: их отпечатки очень похожи, что логично — Android использует ядро Linux, а macOS основан на Darwin/BSD. Однако Window Size и Window Scale позволяют различить их.
Пример из реальных данных
Рассмотрим конкретный случай. На сервер приходит HTTP-запрос с заголовками:
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
AppleWebKit/537.36 (KHTML, like Gecko)
Chrome/122.0.0.0 Safari/537.36
Все JavaScript-проверки пройдены: navigator.platform возвращает Win32, Canvas-отпечаток совпадает с реальным Chrome на Windows, WebGL рендерер указывает на NVIDIA GeForce. По прикладным признакам — идеальный пользователь.
Но TCP-уровень показывает другую картину:
window: 29200
ttl: 64 (исходный)
options: [MSS(1460), SACK, Timestamps, NOP, WS(7)]
Window Size 29200, TTL 64, Timestamps в опциях, Window Scale(7) — это безошибочно Linux. Порядок опций совпадает с ядром Linux 5.x. Никакой Windows так не выглядит на уровне TCP.
Вердикт: бот, запущенный на Linux-сервере, использует headless-браузер с подменённым User-Agent. TCP fingerprinting разоблачает его до того, как выполнится первая строка JavaScript.
Теперь сравним с легитимным пользователем:
window: 64240
ttl: 128 (исходный)
options: [MSS(1460), NOP, WS(8), NOP, NOP, SACK]
Window Size 64240, TTL 128, отсутствие Timestamps, характерный порядок NOP-заполнителей — это Windows 10 или 11. User-Agent и TCP-отпечаток совпадают. Пользователь подлинный.
Почему бот не может подделать TCP-отпечаток
Это центральный вопрос, и ответ кроется в архитектуре операционных систем.
Когда бот запускается на Linux-сервере (а подавляющее большинство ботов работают именно на Linux — это дешевле, проще автоматизировать и масштабировать), его TCP-стек формируется ядром Linux. Приложение — будь то headless Chrome, Puppeteer, Playwright или кастомный HTTP-клиент — не контролирует параметры SYN-пакета. Оно вызывает connect(), а ядро заполняет все TCP-параметры по своим внутренним настройкам.
Чтобы бот на Linux отправил SYN-пакет, идентичный Windows, нужно одно из трёх:
На практике менее 0,1% ботов модифицируют TCP-стек. Это слишком сложно, слишком дорого и слишком нестабильно для массовых операций. Экономика кликфрода не позволяет тратить ресурсы на такой уровень маскировки.
p0f и история пассивного OS fingerprinting
Идея определения ОС по TCP-параметрам не нова. Проект p0f, созданный Михалом Залевски (Michal Zalewski) в начале 2000-х, стал первым широко известным инструментом пассивного TCP fingerprinting. В отличие от активных сканеров вроде Nmap, которые отправляют специальные пакеты для определения ОС, p0f работает полностью пассивно — только анализирует проходящий трафик.
p0f поддерживает базу сигнатур, описывающих TCP-параметры различных операционных систем. Инструмент анализирует SYN-пакеты входящих соединений и сопоставляет их с базой. Точность определения ОС достигает 95–98% для основных платформ.
Однако у классического p0f есть ограничения. Он работает в пользовательском пространстве (userspace), что создаёт накладные расходы на копирование пакетов из ядра. При высокой нагрузке — десятки тысяч соединений в секунду — это становится узким местом. Кроме того, база сигнатур p0f обновляется нерегулярно и может отставать от новых версий ОС.
Другие инструменты — такие как Nmap OS detection — работают активно: они отправляют специально сформированные пакеты целевому хосту и анализируют ответы. Это точнее, но неприменимо для антифрод-сценариев: мы не можем отправлять зондирующие пакеты каждому посетителю сайта. Нужен именно пассивный подход — анализ того, что клиент отправляет сам.
Современный подход — использование eBPF (extended Berkeley Packet Filter). eBPF позволяет запустить программу анализа непосредственно внутри ядра Linux, без копирования пакетов в пользовательское пространство. Это даёт нулевые накладные расходы и возможность обрабатывать сотни тысяч соединений в секунду. Каждый SYN-пакет анализируется прямо в ядре, а результат — готовый TCP-отпечаток — передаётся в систему принятия решений. При этом eBPF-программы проходят верификацию в ядре, что гарантирует их безопасность и стабильность.
Почему VPN и прокси не помогают ботам
Распространённое заблуждение: если бот использует VPN или резидентный прокси, его невозможно обнаружить. Для IP-репутационных систем это действительно проблема — резидентный прокси предоставляет IP-адрес реального домашнего провайдера. Но TCP fingerprinting работает на другом уровне.
VPN и прокси меняют IP-адрес и маршрут пакета, но не модифицируют TCP-параметры. SYN-пакет формируется на машине бота до того, как попадает в VPN-туннель. VPN-сервер инкапсулирует пакет в свой туннель и передаёт дальше, но внутренний TCP-заголовок остаётся нетронутым.
Это означает: бот на Linux-сервере, работающий через цепочку из пяти резидентных прокси, всё равно отправит SYN-пакет с Window Size 29200, TTL 64 и характерным Linux-порядком TCP-опций. IP-адрес будет московского провайдера, а TCP-стек — серверного Linux. Именно поэтому TCP fingerprinting является единственным методом детекции, который не теряет эффективности при использовании ботами премиальных резидентных прокси-сервисов.
Единственное, что может измениться — MSS и TTL. Некоторые VPN-протоколы уменьшают MSS из-за дополнительных заголовков туннелирования (например, MSS 1380 вместо 1460 при использовании WireGuard). TTL уменьшается при прохождении маршрутизаторов, но исходное значение восстанавливается элементарно. Все остальные параметры — Window Size, порядок опций, Window Scale, наличие Timestamps — проходят сквозь VPN без изменений.
TCP fingerprinting в обнаружении рекламного фрода
Для антифрод-систем TCP fingerprinting — это фундаментальный слой детекции. Вот как он работает в связке с другими сигналами:
Сценарий 1: несовпадение User-Agent и TCP-отпечатка
User-Agent заявляет Windows Chrome, но TCP-отпечаток показывает Linux. Это безусловный индикатор бота. Реальный пользователь Windows физически не может отправить SYN-пакет с Linux-параметрами. Ложные срабатывания в этом сценарии практически исключены.
Сценарий 2: серверный TCP-профиль
TCP-отпечаток показывает Linux с параметрами, характерными для серверных ядер (специфичные значения TCP Window Scale, нестандартные MSS). Даже если User-Agent совпадает с заявленной ОС, серверный профиль TCP-стека — сильный сигнал автоматизации.
Сценарий 3: кластерный анализ
Группа визитов с разных IP-адресов, но с идентичным TCP-отпечатком. Если 50 «разных пользователей» из разных городов отправляют SYN-пакеты с абсолютно одинаковыми параметрами (одинаковый Window Size, одинаковый TTL, одинаковый порядок опций) — это бот-ферма. Реальные пользователи используют разные ОС, разные версии, разные сетевые конфигурации.
Точность и надёжность
TCP fingerprinting не существует в вакууме. Максимальная эффективность достигается при комбинации с другими слоями: TLS fingerprinting (JA3/JA4), HTTP/2-отпечатками, поведенческим анализом. Но именно TCP-слой является наиболее фундаментальным и сложным для подделки — он работает на уровне ядра ОС, до любого пользовательского приложения.
Почему это важно для вашего бюджета
Если вы управляете рекламными кампаниями в Яндекс.Директ, Google Ads или программатик-платформах, TCP fingerprinting напрямую влияет на ваш ROI. Стандартные средства защиты от скликивания работают на уровне приложения: анализируют cookies, JavaScript-метрики, поведение мыши. Современные боты научились обходить все эти проверки.
TCP fingerprinting невозможно обойти без переписывания ядра операционной системы или отказа от дешёвых Linux-серверов. Это создаёт экономический барьер, который делает кликфрод нерентабельным: стоимость маскировки TCP-стека превышает доход от фальшивых кликов.
По нашим данным, внедрение TCP fingerprinting в связке с TLS-анализом позволяет обнаружить до 70% бот-трафика, который проходит мимо стандартных JavaScript-детекторов и IP-блоклистов. Для рекламодателей с бюджетом от 500 000 рублей в месяц это означает экономию в десятки и сотни тысяч рублей ежемесячно — деньги, которые иначе уходили бы на клики, за которыми не стоит ни один живой человек.
Заключение
TCP fingerprinting — это не экспериментальная технология, а зрелый, проверенный метод с двадцатилетней историей. Каждый SYN-пакет несёт в себе подпись операционной системы, которую невозможно подделать на прикладном уровне. Window Size, TTL, порядок TCP-опций — все эти параметры задаются ядром ОС и остаются неизменными вне зависимости от браузера, VPN или прокси.
Для антифрод-систем это означает надёжный, фундаментальный слой детекции, который работает до HTTP, до JavaScript, до любых прикладных проверок. Бот может идеально имитировать браузер — но не может имитировать операционную систему на уровне TCP-стека.