Как работает TCP/IP-фингерпринтинг: TTL, размер окна, MSS и порядок TCP-опций выдают вашу ОС из рукопожатия — и как их читают p0f и JA4T.
Ещё до того, как ваш браузер отправит хотя бы один байт TLS-сообщения ClientHello, ваша операционная система уже представилась. Трёхстороннее TCP-рукопожатие, которым открывается каждое соединение, несёт горстку низкоуровневых параметров — начальный TTL, объявленный размер окна, максимальный размер сегмента и порядок TCP-опций, — которые ядро вашей ОС заполняет собственными значениями по умолчанию. Ни одно из этих значений не выбираете вы или ваше приложение, а их сочетание достаточно стабильно, чтобы угадать, под какой операционной системой вы работаете. Это и есть TCP/IP-фингерпринтинг: пассивное определение ОС по сырым заголовкам пакетов, выполняемое ещё до того, как согласовано какое-либо шифрование.
Ключевые выводы
- Отпечаток пишет ядро ОС, а не браузер. Начальный TTL, размер TCP-окна, MSS и порядок TCP-опций в пакете SYN задаются сетевым стеком операционной системы — поэтому отпечаток идентифицирует ОС, а не приложение, отправляющее запрос.
- Это происходит до TLS. TCP/IP-фингерпринтинг читает пакет SYN трёхстороннего рукопожатия, на один уровень ниже TLS-рукопожатия, которое идентифицируют JA3/JA4. Они накладываются друг на друга.
- Это пассивный метод. Сервер может определить вашу ОС просто приняв соединение — без зондов, без JavaScript, ничего не отправляя вам обратно. Этот подход первым предложил инструмент p0f; JA4T — современная, структурированная его версия.
- Он выявляет несоответствие между реальной ОС и заявленной. Пакет SYN, чьи значения по умолчанию говорят «Linux», прибывающий с заголовком
User-Agent, который заявляет «Windows Chrome», — классический сигнал подмены, используемый при обнаружении ботов. - NAT, прокси и VPN размывают его. Поскольку сигналы живут в заголовках, которые шлюзы и туннели переписывают, отпечаток отражает ближайший стек, записавший пакет, — именно поэтому он помогает определять VPN и прокси.
Что такое TCP/IP-фингерпринтинг?
Каждое TCP-соединение открывается трёхсторонним рукопожатием: клиент отправляет SYN, сервер отвечает SYN-ACK, а клиент подтверждает ACK. Этот первый пакет SYN собирается стеком TCP/IP операционной системы, и несколько его полей не определяются стандартами протокола — стандарты задают смысл каждого поля, но оставляют значения по умолчанию на усмотрение реализации. Разные ядра выбирают разные значения по умолчанию, и они редко меняются между соединениями.
Поскольку эти значения по умолчанию зашиты в сетевой стек ОС, отпечаток описывает операционную систему и её версию, а не браузер или пользователя. Два разных браузера на одной и той же машине Windows дают одинаковый TCP/IP-отпечаток; один и тот же браузер на Windows и на Linux даёт два разных. Это обратная сторона браузерного фингерпринтинга, который идентифицирует приложение и слеп к ядру под ним.
Сигналы в пакете SYN
Основную работу выполняют четыре значения заголовков, взятые из уровня IP (RFC 791) и уровня TCP (RFC 9293).
1. Начальный TTL (Time To Live)
Поле TTL в IP-заголовке уменьшается на единицу на каждом маршрутизаторе, поэтому наблюдатель никогда не видит исходное значение напрямую — но операционные системы стартуют с небольшого набора хорошо известных значений по умолчанию: 64 (Linux, macOS, современные BSD), 128 (Windows) и 255 (некоторые сетевые устройства и старые Unix). Если пакет прибывает с TTL 57, он почти наверняка стартовал с 64 и прошёл 7 переходов. Округление наблюдаемого TTL вверх до ближайшего распространённого значения по умолчанию восстанавливает семейство ОС-источника.
2. Размер TCP-окна
TCP-заголовок объявляет начальное окно приёма — сколько байт отправитель готов принять, прежде чем потребует подтверждения. Точное стартовое значение специфично для стека: исторически Windows, Linux и macOS поставлялись с узнаваемо разными начальными размерами окна, и это значение — один из самых сильных различителей в пакете SYN. В сочетании с опцией масштабирования окна (RFC 7323) оно сужает ОС, а иногда и её версию.
3. Максимальный размер сегмента (MSS)
Опция MSS (RFC 6691) объявляет наибольшую TCP-нагрузку, которую клиент готов принять в одном сегменте. Её значение выводится из MTU канала — обычно 1460 байт в стандартном Ethernet (1500 MTU минус 40 байт заголовков), но ниже через PPPoE, туннели или VPN. Необычное значение MSS уже само по себе информативно: значение 1400 или ниже нередко выдаёт, что трафик проходит через туннель, а это намёк на использование VPN.
4. TCP-опции и их порядок
Поле TCP-опций может нести MSS, масштабирование окна, разрешение SACK, временные метки и NOP-заполнение — и, что особенно важно, порядок, в котором стек их перечисляет, специфичен для реализации. Linux, Windows и macOS выдают каждый свою характерную раскладку опций (например, MSS, SACK, Timestamp, NOP, Window-Scale против MSS, NOP, Window-Scale, SACK, Timestamp). Подобно порядку расширений в TLS ClientHello, порядок раскрывает больше идентичности, чем любое отдельное значение.
| Сигнал | Задаётся | Типичный Linux | Типичный Windows |
|---|---|---|---|
| Начальный TTL | IP-стек | 64 | 128 |
| Размер окна | TCP-стек | специфичен для стека | специфичен для стека |
| MSS | выводится из MTU | 1460 | 1460 |
| Порядок опций | TCP-стек | характерная раскладка | характерная раскладка |
Пассивное обнаружение: p0f и JA4T
Определяющее свойство TCP/IP-фингерпринтинга в том, что он пассивен. В отличие от инструментов активного определения ОС, которые отправляют специально составленные зонды и измеряют отклики, пассивный фингерпринтер должен лишь наблюдать трафик, который клиент и так отправляет. Принятия обычного соединения достаточно, чтобы прочитать SYN.
p0f — инструмент, популяризировавший этот подход: пассивный фингерпринтер, сопоставляющий наблюдаемые пакеты SYN с базой известных сигнатур ОС и определяющий операционную систему, а иногда время работы или тип канала, не отправляя цели ни одного пакета. Он задал формат сигнатур, которому до сих пор следует большинство пассивных систем определения ОС.
JA4T — TCP-уровневый участник набора JA4+ от FoxIO, того же проекта, что стоит за современным TLS-отпечатком JA4. JA4T складывает размер TCP-окна, TCP-опции в их порядке, значение MSS и значение масштабирования окна в одну структурированную, читаемую человеком строку — перенося философию «сортируемого, читаемого отпечатка» JA4 на транспортный уровень. Поскольку он находится ниже TLS, JA4T может пометить соединение ещё до того, как разобран ClientHello.
Как это сочетается с TLS-фингерпринтингом
TCP/IP-фингерпринтинг и TLS-фингерпринтинг читают соседние уровни одной и той же последовательности рукопожатия и идентифицируют разные вещи:
| Уровень | Техника | Что идентифицирует |
|---|---|---|
| IP + TCP | p0f / JA4T | Ядро операционной системы |
| TLS | JA3 / JA4 | TLS-библиотеку (и тем самым приложение) |
Именно это различие делает их парой мощной. TCP/IP-отпечаток говорит, какая ОС отправила пакет; TLS-отпечаток говорит, какое клиентское ПО открыло сессию. Когда они расходятся — SYN в стиле Windows, несущий TLS-рукопожатие, совпадающее с macOS Safari, — соединение внутренне противоречиво, а несогласованность между наблюдаемыми уровнями — основной принцип, лежащий в основе методов обнаружения ботов. Скрейпер, работающий на Linux-сервере и подделывающий User-Agent Chrome-на-Windows, всё равно выдаёт Linux-пакет SYN, и ни один заголовок, который он задаёт, этого не изменит.
Что он раскрывает — и его ограничения
TCP/IP-отпечаток может раскрыть семейство и версию ОС, намекнуть на тип канала (Ethernet, PPPoE, туннель) по значению MSS и выявить несоответствие между заявленной и реальной платформой. Но это грубый инструмент по сравнению с отпечатками более высоких уровней, и несколько вещей его размывают:
- NAT и балансировщики нагрузки могут переписывать или нормализовать TCP-опции, поэтому отпечаток может отражать шлюз, а не конечный хост.
- VPN и прокси завершают или переинкапсулируют соединение; тогда сервер снимает отпечаток ОС конечной точки VPN, а не вашей. Это палка о двух концах — он скрывает вашу настоящую ОС, но похожий на резидентный IP в паре с отпечатком ОС дата-центра сам по себе является сигналом VPN/прокси.
- Низкое разрешение. TCP/IP-фингерпринтинг хорошо различает семейства ОС, но не может определить конкретный браузер, модель устройства или пользователя. Это грубый первичный фильтр, а не уникальный идентификатор.
По этим причинам он почти всегда используется как один вход среди многих — в сочетании с TLS- и HTTP/2-отпечатками, репутацией IP и поведенческими сигналами, — а не как самостоятельный вердикт.
Часто задаваемые вопросы
Могу ли я изменить свой TCP/IP-отпечаток?
Только изменив сетевой стек ОС, который его производит. Некоторые инструменты приватности и обхода цензуры предлагают «подмену отпечатка ОС», которая переписывает TTL, размер окна и порядок опций, имитируя другую систему, но это работает на уровне ядра/файрвола — настройки браузера, расширения и переопределения User-Agent до него не добираются, потому что значения записываются ещё до запуска любого кода приложения.
Скрывает ли VPN мой TCP/IP-отпечаток?
Частично. VPN туннелирует ваш трафик, поэтому целевой сервер видит пакет SYN, произведённый стеком VPN-клиента или его выходного узла, а не ваш исходный. Ваш настоящий отпечаток ОС скрыт, но туннель часто оставляет собственные следы — уменьшенный MSS из-за накладных расходов инкапсуляции или отпечаток ОС, не совпадающий с резидентным IP, — которые системы обнаружения используют, чтобы заключить о наличии VPN.
Это то же самое, что определение ОС в Nmap?
Нет. Nmap выполняет активное определение ОС — он отправляет серию специально составленных зондовых пакетов и анализирует отклики. TCP/IP-фингерпринтинг, как он обсуждается здесь, пассивен: он лишь наблюдает пакеты, которые клиент отправляет в ходе обычного соединения, что делает его бесшумным и незаметным со стороны клиента.
Почему один лишь TTL не определяет ОС?
Поскольку TTL уменьшается на каждом маршрутизаторе, наблюдаемое вами значение — это стартовое значение по умолчанию минус число переходов, и разные значения по умолчанию могут совпасть после достаточного количества переходов. TTL сужает семейство ОС (64 против 128 против 255), но надёжен только в сочетании с размером окна, MSS и порядком опций — полной сигнатурой, а не любым отдельным полем.


