TCP fingerprint: как антифрод видит прокси через сетевой стек
Содержание
- Почему TCP/IP не врут
- Параметры ядра: что смотрит антифрод
- MSS и MTU: главный провал прокси
- TTL: часовой пояс сетевого стека
- Window Scale: архитектурный косяк
- Timestamp: ловушка для туннелей
- Реальный кейс: nginx 1.24 и Cloudflare
- Python-скрипт для снятия fingerprint
- Поиск MSS в опциях
- Запуск сниффера требует прав root
- Кейс: OpenVPN и MTU 1500
- Кейс: WireGuard и MSS clamping
- Кейс: двойной прокси с разными ОС
- Как антифрод собирает базу
- Что можно изменить в ядре
- Изменить MSS
- Изменить Window Scale
- Отключить Timestamp
- Итог: что делает прокси уязвимым
Антифрод-системы не гадают на кофейной гуще. Они смотрят на TCP-пакеты. Каждый пакет — отпечаток пальцев. И скрыть это сложнее, чем сменить IP.
Почему TCP/IP не врут
IP-адрес сменить легко. А вот сетевой стек операционной системы — нет. Он зашит в ядро. Linux 6.1 отправляет пакеты не так, как Windows 11 или FreeBSD. Разница в миллисекундах и байтах. Но для антифрода это очевидно.
TCP-соединение начинается с handshake. SYN, SYN-ACK, ACK. В каждом пакете — десятки параметров. Размер окна, MSS, опции TCP, таймстемпы, масштабирование. Комбинация уникальна. Как ДНК.
Параметры ядра: что смотрит антифрод
Самые важные параметры TCP-стека, которые выдают прокси:
| Параметр | Обычное значение | Что видит антифрод |
|----------|------------------|---------------------|
| MSS | 1460 (Ethernet) | Размер сегмента. Прокси часто режут |
| Window Scale | 7 (Linux), 8 (Windows) | Масштаб окна. Разный у ОС |
| Timestamp | Опционально | Включается/выключается в ядре |
| SACK | Включен почти везде | Selective ACK. Старые системы без него |
| TTL | 64 (Linux), 128 (Windows) | Время жизни пакета. Выдаёт ОС |
| DF flag | Всегда 1 | Don't Fragment. Прокси иногда сбрасывают |
Вот как выглядит реальный захват TCP-пакета:
```bash
tcpdump -i eth0 -nn 'tcp[tcpflags] & tcp-syn != 0' -X
```
Вывод покажет все параметры. Каждый байт — улика.
MSS и MTU: главный провал прокси
MSS (Maximum Segment Size) — самый жирный маркер. Он вычисляется из MTU интерфейса. MTU 1500 даёт MSS 1460. MTU 1492 (PPPoE) — MSS 1452. MTU 1280 (IPv6 минималка) — MSS 1220.
Прокси часто работают через туннели. GRE, WireGuard, OpenVPN. У каждого свой MTU. Сервер видит MSS клиента, но через прокси пакет идёт с другим MTU. Несостыковка.
Пример: клиент за WireGuard. MTU туннеля 1420. MSS = 1380. Антифрод видит SYN с MSS 1460 (клиент отправил оригинал), но реальный пакет фрагментирован. Или наоборот — прокси режет MSS, и клиент не может открыть страницу.
Проверить MTU своего интерфейса:
```bash
ip link show eth0 | grep mtu
```
Если там 1500, а антифрод видит пакеты с MSS 1380 — вас раскусили.
TTL: часовой пояс сетевого стека
TTL (Time To Live) — количество хопов, которые может пройти пакет. Разные ОС ставят разные значения:
- Linux: 64
- Windows: 128
- FreeBSD: 64
- macOS: 64
- Cisco: 255
Прокси уменьшает TTL на каждом хопе. Но исходное значение остаётся в пакете. Антифрод смотрит: пришёл пакет с TTL 55. 64 - 9 хопов = 55. Всё честно. А если TTL 120 — это Windows через 8 хопов. Но клиент сидит на Linux. Несостыковка.
Есть инструмент для трассировки:
```bash
traceroute -n 8.8.8.8
```
Количество хопов + TTL пакета = версия ОС.
Window Scale: архитектурный косяк
Window Scale — множитель размера окна TCP. Без него окно максимум 65535 байт. С масштабированием — до 1 ГБ. Значение зависит от ОС:
- Linux: 7 (масштаб 128)
- Windows 10: 8 (масштаб 256)
- Windows 7: 2 (масштаб 4)
- macOS: 3 (масштаб 8)
Прокси может не менять этот параметр. Или менять неправильно. Антифрод видит: клиент с Linux, но Window Scale = 8. Подозрительно.
Timestamp: ловушка для туннелей
TCP Timestamp — опция для измерения RTT. Включается в ядре параметром `net.ipv4.tcp_timestamps`. По умолчанию 1 (включено).
Проблема: timestamp содержит время с момента загрузки системы. Если прокси пересылает пакеты без изменения timestamp, сервер видит разницу в миллионах секунд. Или timestamp вообще отсутствует — значит, пакет прошёл через оборудование, которое вырезает опции.
Проверить текущее состояние:
```bash
sysctl net.ipv4.tcp_timestamps
```
Отключить можно, но это снизит производительность TCP.
Реальный кейс: nginx 1.24 и Cloudflare
Пример: сервер на nginx 1.24 за Cloudflare. Cloudflare меняет некоторые TCP-параметры. MSS режется до 1360 (MTU туннеля 1400). TTL становится 59 (Cloudflare добавляет 5 хопов). Window Scale — 7 (Linux).
Антифрод видит: клиент с MSS 1360, TTL 59, Window Scale 7. Это похоже на Cloudflare. Но если реальный клиент за другим прокси — параметры будут иными. И антифрод это заметит.
Проверка через curl:
```bash
curl -v https://example.com 2>&1 | grep -i "mss\|window\|ttl"
```
Вывод покажет, какие параметры использует ваш стек.
Python-скрипт для снятия fingerprint
Можно написать простой сниффер, который анализирует TCP-пакеты:
```python
import socket
import struct
def parse_tcp_syn(packet):
ip_header = packet[0:20]
iph = struct.unpack('!BBHHHBBH4s4s', ip_header)
tcp_header = packet[20:40]
tcph = struct.unpack('!HHLLBBHHH', tcp_header)
mss = None
if len(packet) > 40:
options = packet[40:]
Поиск MSS в опциях
for i in range(len(options)-3):
if options[i] == 2: # Kind 2 = MSS
mss = struct.unpack('!H', options[i+2:i+4])[0]
break
return {
'src_port': tcph[0],
'dst_port': tcph[1],
'window': tcph[5],
'mss': mss,
'ttl': iph[5]
}
Запуск сниффера требует прав root
```
Этот код ловит SYN-пакеты и извлекает параметры. Антифрод делает то же самое, но в масштабе.
Кейс: OpenVPN и MTU 1500
Проблема: OpenVPN по умолчанию использует MTU 1500. Но туннель добавляет 58 байт заголовка. Пакет фрагментируется. Антифрод видит фрагменты — это признак прокси.
Решение: уменьшить MTU на клиенте:
```bash
ip link set dev tun0 mtu 1400
```
Но тогда MSS станет 1360. И это будет видно.
Кейс: WireGuard и MSS clamping
WireGuard не фрагментирует пакеты. Он просто отбрасывает те, что больше MTU. MSS clamping на фаерволле решает проблему:
```bash
iptables -t mangle -A FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
```
Но clamping меняет MSS в пакете. Антифрод видит нестандартное значение. 1380 вместо 1460. Подозрительно.
Кейс: двойной прокси с разными ОС
Пример: первый прокси на Linux (MSS 1460, TTL 64), второй на FreeBSD (MSS 1460, TTL 64). Но FreeBSD использует Window Scale 3. Антифрод видит: MSS 1460, TTL 55 (9 хопов), Window Scale 3. Это не Linux и не Windows. FreeBSD за прокси.
Как антифрод собирает базу
Крупные антифрод-системы (MaxMind, ThreatMetrix) имеют базу TCP fingerprint. Они анализируют миллионы соединений. Каждый провайдер, каждый дата-центр имеет характерный профиль.
Пример: все серверы Hetzner используют Linux с стандартными настройками. MSS 1460, Window Scale 7, TTL 64. Если приходит запрос с MSS 1452 (PPPoE) — это домашний интернет. Сразу видно.
Что можно изменить в ядре
Linux позволяет менять параметры TCP через sysctl:
```bash
Изменить MSS
echo "1460" > /proc/sys/net/ipv4/tcp_mss
Изменить Window Scale
echo "8" > /proc/sys/net/ipv4/tcp_window_scaling
Отключить Timestamp
echo "0" > /proc/sys/net/ipv4/tcp_timestamps
```
Но это глобальные изменения. Они повлияют на все соединения. И антифрод может заметить несоответствие: Window Scale 8, но TTL 64 (Linux). Так не бывает.
Итог: что делает прокси уязвимым
TCP fingerprint — не магия. Это анализ 5-7 параметров. Прокси уязвимы, потому что:
1. MTU туннеля не совпадает с MTU клиента
2. TTL не соответствует версии ОС
3. Window Scale не типичен для ОС
4. Timestamp включен или выключен не так, как у клиента
5. MSS режется или не режется, создавая несостыковки
Антифрод не смотрит на один параметр. Он смотрит на комбинацию. И если комбинация не встречается в природе — это прокси.
Единственный способ обмануть — эмулировать конкретную ОС на всех уровнях. Но это требует изменения ядра. Или использования специализированного ПО, которое подменяет TCP-параметры. Но это уже другая история.