Как CDN-провайдеры детектят VPN по MTU и TTL: скрытые метрики сетевого стека
Содержание
- Анатомия пакета: что реально видит сервер
- Почему MTU — главный маркер VPN
- TTL: математика прыжков
- Как CDN собирает эти данные
- Кейс: бесплатный VPN на фоне стриминга
- Кейс: корпоративный VPN против DPI
- Как VPN-провайдеры маскируют MTU
- Кейс: WireGuard под микроскопом
- Скрытые метрики: TCP Window и MSS
- Как это работает на практике: сбор статистики
- Сбор распределения размеров пакетов на edge-сервере
- Что делает Cloudflare с этими данными
- Практические советы по маскировке
- Кейс: как я настраивал VPN для работы с CDN
- Что дальше: эволюция детекции
Анатомия пакета: что реально видит сервер
Когда пакет долетает до edge-сервера Cloudflare или Fastly, он несет не только payload. В IP-заголовке — 14 полей, и большинство из них либо служебные, либо легко подделываются. Но два поля — Total Length и Time To Live — выдают VPN с головой.
MTU (Maximum Transmission Unit) — это не просто цифра в настройках. Это физическое ограничение канала. Для Ethernet — 1500 байт. Для PPPoE — 1492. Для туннелей WireGuard — 1420. Каждый тип подключения оставляет свой след в размере пакетов, которые видит сервер.
TTL — это счетчик прыжков, который уменьшается на каждом хопе. Стандартные значения: 64 для Linux, 128 для Windows, 64 для macOS. Но когда трафик идет через VPN-туннель, TTL меняется нелинейно — и это видно.
Почему MTU — главный маркер VPN
Обычный пользователь сидит за домашним роутером с MTU 1500. Его пакеты летят напрямую, не фрагментируясь. VPN-клиент оборачивает трафик в туннель, добавляя заголовки — и итоговый размер пакета уменьшается.
Пример: WireGuard добавляет 32 байта оверхеда. Если MTU интерфейса — 1500, то полезная нагрузка — 1468. Пакеты с таким размером — визитная карточка WireGuard. OpenVPN с UDP — 1382 байта. IPSec — 1400.
CDN-провайдеры собирают статистику распределения размеров пакетов. Если с одного IP прилетают пакеты строго по 1382 байта — это не случайность. Так работает только туннель.
TTL: математика прыжков
TTL — более тонкий инструмент. Когда вы шлете запрос напрямую, сервер видит TTL, уменьшенный ровно на количество хопов между вами и им. Если ваш Linux отправил пакет с TTL 64, а до сервера 10 хопов — сервер увидит 54.
С VPN картина другая. Ваш пакет доходит до VPN-сервера (например, 8 хопов), TTL становится 56. VPN-сервер отправляет его дальше с новым TTL — обычно 64 или 128. Если до CDN еще 10 хопов — сервер увидит 54. Но при этом количество хопов от VPN-сервера до CDN часто меньше, чем от пользователя до VPN-сервера.
Вот и получается: TTL 54 при 10 хопах от клиента — норма. Но если TTL 58 при 10 хопах — значит, где-то в цепочке был перезапуск счетчика. Это и есть след VPN.
Как CDN собирает эти данные
Никто не анализирует каждый пакет в реальном времени. Это слишком дорого. Вместо этого — сэмплирование. Пограничные маршрутизаторы захватывают каждый N-й пакет, собирают метаданные и отправляют в систему анализа.
Ключевые метрики:
- Распределение размеров пакетов (packet size histogram)
- Разброс TTL для одного IP
- Стабильность этих значений во времени
- Корреляция с поведением пользователя
Пример: пользователь с одного IP шлет запросы с TTL 54 и размером пакетов 1468 байт. Через минуту — TTL 57 и размер 1382. Это уже подозрительно. Через час — снова 54 и 1468. Так ведет себя только VPN с переключением серверов.
Кейс: бесплатный VPN на фоне стриминга
Проблема: пользователь смотрит Netflix через бесплатный VPN. CDN Netflix замечает, что размеры пакетов с его IP скачут между 1382 и 1468 байтами, а TTL меняется каждые 20 минут.
Причина: VPN-клиент автоматически переключает серверы при падении скорости. Каждый сервер — свой TTL и свой MTU.
Решение: Netflix блокирует IP. Не потому что видит VPN-трафик, а потому что видит аномальную нестабильность сетевых метрик. Обычный пользователь сидит на одном канале годами.
Кейс: корпоративный VPN против DPI
Проблема: сотрудник подключается к рабочему VPN из дома. Корпоративный шлюз использует IPSec с MTU 1400. CDN аналитики видят стабильные пакеты по 1400 байт и TTL 55 при 9 хопах.
Причина: корпоративные VPN настроены стабильно. Никаких скачков. Но сама стабильность — маркер.
Решение: CDN не блокирует. Слишком много легитимного корпоративного трафика. Вместо этого — понижение приоритета в очереди. Запросы обрабатываются с задержкой на 200-300 мс. Пользователь думает, что VPN тормозит, и отключается сам.
Как VPN-провайдеры маскируют MTU
Есть два подхода. Первый — принудительное выравнивание MTU. VPN-клиент фрагментирует все пакеты до 1400 байт, маскируя туннель под обычный Ethernet. Минус — потеря производительности до 7% из-за фрагментации.
Второй — имитация стандартного MTU. Клиент добавляет padding до 1500 байт, заполняя пустоту случайными данными. Нагрузка на канал растет, но распределение размеров пакетов становится неотличимым от обычного браузинга.
Проблема в том, что padding надо генерировать правильно. Случайные байты легко отличить от реального TLS-трафика. Поэтому используют шифрование уже заполненного пакета — тогда padding неотличим от данных.
Кейс: WireGuard под микроскопом
Проблема: пользователь использует WireGuard для обхода гео-блокировки. CDN видит пакеты строго по 1420 байт — это MTU WireGuard.
Причина: WireGuard не фрагментирует пакеты. Он передает их как есть, с фиксированным MTU 1420. Для CDN это как отпечаток пальца.
Решение: современные версии WireGuard (1.0.20211208+) поддерживают MSS clamping — принудительное уменьшение MSS в TCP-заголовках. Это маскирует MTU под стандартные 1500. Пакеты становятся 1500 байт, но с уменьшенной полезной нагрузкой. CDN видит нормальный трафик.
Скрытые метрики: TCP Window и MSS
MTU и TTL — не единственные маркеры. TCP Window Size и MSS (Maximum Segment Size) тоже выдают VPN. MSS отправляется в SYN-пакете и сообщает максимальный размер сегмента, который готов принять узел.
Стандартный MSS для Ethernet — 1460 байт. Для PPPoE — 1452. Для туннелей — меньше. Если сервер видит SYN с MSS 1420 — это WireGuard. MSS 1332 — это OpenVPN с MTU 1372.
CDN хранят базу данных известных MSS-значений для всех популярных VPN-протоколов. Совпадение с базой — мгновенная блокировка. Поэтому VPN-клиенты сейчас активно настраивают MSS clamping.
Как это работает на практике: сбор статистики
```bash
Сбор распределения размеров пакетов на edge-сервере
tcpdump -i eth0 -nn -l -e -c 10000 'tcp port 443' | \
awk '{print \$NF}' | sort -n | uniq -c | sort -rn | head -20
```
Этот дамп показывает, какие размеры пакетов реально приходят на сервер. Если вы видите пик на 1420 байт — это WireGuard. Пик на 1382 — OpenVPN. Пик на 1356 — SoftEther.
Для автоматизации используют что-то вроде:
```python
import dpkt
import socket
from collections import Counter
def analyze_pcap(filename):
sizes = Counter()
with open(filename, 'rb') as f:
pcap = dpkt.pcap.Reader(f)
for ts, buf in pcap:
eth = dpkt.ethernet.Ethernet(buf)
if isinstance(eth.data, dpkt.ip.IP):
ip = eth.data
if ip.p == dpkt.ip.IP_PROTO_TCP:
sizes[ip.len] += 1
return sizes.most_common(10)
print(analyze_pcap('capture.pcap'))
```
Что делает Cloudflare с этими данными
Cloudflare использует не только MTU и TTL. У них есть система Bot Management, которая анализирует сотни сигналов. MTU и TTL — это лишь базовая фильтрация. Если IP попадает в зону риска по этим метрикам, включается глубокий анализ TLS-отпечатков.
JA3 и JA4 — это хеши от TLS ClientHello. Каждый VPN-клиент имеет свой уникальный отпечаток. OpenVPN с TLS 1.3 выглядит иначе, чем обычный Chrome. Даже если MTU и TTL замаскированы, JA3 выдаст.
Практические советы по маскировке
Если вы администрируете VPN-сервер и хотите снизить вероятность детекции:
1. Настройте MSS clamping на всех интерфейсах:
```bash
iptables -t mangle -A POSTROUTING -p tcp --tcp-flags SYN,RST SYN \
-j TCPMSS --clamp-mss-to-pmtu
```
2. Выравнивайте MTU до 1500 на всех туннелях. Лучше потерять 3% скорости, чем получить блокировку.
3. Используйте стабильные TTL. Не позволяйте VPN-клиенту менять серверы слишком часто. Один сервер — один TTL.
4. Смешивайте трафик. Не гоните весь трафик через VPN. Пусть часть запросов идет напрямую, часть — через туннель. Это сбивает статистику.
Кейс: как я настраивал VPN для работы с CDN
Проблема: клиент жаловался, что его VPN-сервер (на базе OpenVPN) блокируется на уровне CDN. Запросы проходят, но с задержкой 1.5 секунды. При этом прямой трафик с того же сервера летает.
Причина: MTU туннеля был 1372 байта. CDN видел пакеты строго по 1372 байта и помечал IP как VPN. Дальше — понижение приоритета.
Решение: переключил OpenVPN на UDP с MTU 1500 и настроил MSS clamping. Распределение размеров пакетов стало неотличимо от обычного трафика. Задержка упала до 80 мс. Проблема ушла.
Что дальше: эволюция детекции
MTU и TTL — это старая школа. Сейчас активно развивается анализ межпакетных интервалов (inter-packet delay). VPN-туннели вносят дополнительную задержку на шифрование и дешифрование. Даже если вы замаскировали MTU и TTL, распределение задержек между пакетами выдает туннель.
Точность детекции по MTU и TTL — около 85%. С учетом JA3 и анализа задержек — до 97%. Но и VPN-клиенты не стоят на месте. Они уже умеют имитировать поведение обычного браузера. Война продолжается.