Как обнаружить VPN-туннель по анализу TTL и временных задержек пакетов
Содержание
Обнаружение VPN по TTL и задержкам
VPN-туннель оставляет следы. Даже если трафик зашифрован, сами пакеты выдают себя. TTL и RTT — два маркера, которые не спрятать за шифрованием. Разберём, как это работает на практике.
Физика TTL
TTL (Time To Live) — счётчик маршрутизаторов. Каждый хоп уменьшает его на единицу. Обычная ОС отправляет пакеты с фиксированным начальным значением: Windows — 128, Linux — 64, macOS — 64. Когда пакет проходит через VPN, происходит двойная маршрутизация: сначала до сервера VPN, потом до цели. И вот тут начинается магия.
Пакет, отправленный с Windows (TTL=128), попадает в туннель. VPN-сервер пересылает его дальше, но уже со своим TTL. Если VPN работает на Linux-сервере — начальное значение станет 64. Разница в 64 единицы — мгновенный маркер. Но это грубый метод, срабатывает только при прямом сравнении.
Точный расчёт
Формула простая: `начальный_TTL - конечный_TTL = количество_хопов`. Если у тебя Windows, а пакет пришёл с TTL=55, значит хопов было 73. Нереально много для обычного интернета. Скорее всего, это VPN с кучей промежуточных узлов.
Но есть нюанс. Некоторые VPN-сервисы специально выставляют TTL, маскируясь под целевую ОС. OpenVPN позволяет задать параметр `mssfix` и подправить TTL. Поэтому TTL — только первый звоночек, а не приговор.
RTT как индикатор
Временные задержки — более тонкий инструмент. VPN добавляет минимум один лишний хоп до сервера. Для TCP-сессий это критично: каждый ACK идёт через туннель. Измерь RTT до обычного сайта и до VPN-сервера — разница будет минимум в 2-3 раза.
Пинг до `8.8.8.8` без VPN: 15 мс. С VPN через сервер в другой стране: 80-120 мс. Это заметно невооружённым глазом. Но проблема в том, что RTT зависит от нагрузки на сеть. В час пик задержки растут у всех.
Методика обнаружения
Соберём всё в рабочий алгоритм:
```bash
ping -c 10 -i 0.2 8.8.8.8 | tail -1
```
Это даст средний RTT. Повтори три раза с интервалом в минуту. Если разброс значений меньше 10% — сеть стабильна. VPN даёт разброс 20-30% из-за двойной маршрутизации.
Для TTL:
```bash
ping -c 5 -t 5 example.com | grep ttl
```
Сравни значения с ожидаемыми для твоей ОС. Отклонение больше 5 — повод копать глубже.
Пример на Python
Автоматизируем проверку:
```python
import subprocess
import statistics
def check_ttl_rtt(host, count=10):
result = subprocess.run(
['ping', '-c', str(count), host],
capture_output=True, text=True
)
lines = result.stdout.split('\n')
ttl_values = []
rtt_values = []
for line in lines:
if 'ttl=' in line:
ttl = int(line.split('ttl=')[1].split()[0])
ttl_values.append(ttl)
if 'time=' in line:
rtt = float(line.split('time=')[1].split()[0])
rtt_values.append(rtt)
return {
'ttl_avg': statistics.mean(ttl_values),
'ttl_stdev': statistics.stdev(ttl_values),
'rtt_avg': statistics.mean(rtt_values),
'rtt_stdev': statistics.stdev(rtt_values)
}
```
На выходе получишь средние значения и стандартное отклонение. Стандартное отклонение TTL больше 2 — подозрительно. Для RTT больше 15% от среднего — тоже.
Кейс с корпоративной сетью
Пример: компания с офисом в Москве и VPN-сервером в Питере. Сотрудник подключается к корпоративной сети через OpenVPN. Пинг до внутреннего сервера `10.0.0.5` показывает RTT 35 мс. Это нормально для расстояния Москва-Питер, но для локальной сети — абсурд. TTL при этом равен 63, хотя Windows-машина должна слать 128. Классический признак VPN.
Решение: сравнить RTT до внутренних ресурсов с RTT до внешних. Если до внутреннего сервера задержка больше, чем до внешнего сайта — это туннель.
Кейс с DPI-системой
Провайдер использует DPI для блокировки VPN. Система анализирует TTL входящих и исходящих пакетов. Если TTL в ответе отличается от ожидаемого для данного типа ОС — трафик помечается как VPN. Метод работает, потому что большинство VPN-клиентов не меняют TTL по умолчанию.
Проблема: легитимные прокси и CDN тоже меняют TTL. Поэтому DPI дополнительно смотрит на RTT. Если задержка до сайта с CDN меньше 10 мс, а TTL скачет — это нормально. Если RTT высокий и TTL нестабильный — VPN.
Кейс с WireGuard
WireGuard работает на уровне ядра, поэтому TTL меняется иначе. Тест на Ubuntu 22.04 с WireGuard показал: начальный TTL 64, после прохождения туннеля — 63. Разница в 1 единицу. Это почти неотличимо от обычной маршрутизации. Но RTT выдаёт: задержка выросла с 12 мс до 28 мс при подключении к серверу в соседнем ЦОД.
Обнаружение WireGuard по TTL — тупиковый путь. Нужен комплексный анализ: RTT, джиттер, паттерны пакетов. WireGuard не добавляет заголовков, но добавляет задержку на шифрование. На слабом железе это 0.5-1 мс на пакет.
Таблица сравнения методов
| Метод | Точность | Скорость | Ложные срабатывания |
|-------|----------|----------|---------------------|
| TTL | Средняя | Мгновенно | Высокие |
| RTT | Высокая | 10-30 сек | Средние |
| TTL+RTT | Высокая | 10-30 сек | Низкие |
| Джиттер | Средняя | 1-2 мин | Средние |
Джиттер — вариация задержек между пакетами. VPN создаёт нестабильный джиттер из-за шифрования и туннелирования.
Ограничения метода
VPN с фиксированным TTL и оптимизированным маршрутом не обнаружит ни один из этих методов. Пример: коммерческие VPN с выделенными каналами. Они держат RTT в пределах 5-10 мс от обычного и выставляют TTL под целевую ОС. Тут нужен анализ трафика на уровне приложений.
Ещё ограничение: мобильные сети. LTE/5G добавляют 20-40 мс задержки в любом случае. RTT-метод даст ложное срабатывание. В таких случаях ориентируйся на TTL и джиттер.
Практические рекомендации
Для обнаружения VPN на своей машине используй комбинацию TTL и RTT. Замерь базовые значения без VPN, потом с VPN. Разница в TTL больше 5 единиц и рост RTT больше 50% — туннель.
Для обнаружения чужих VPN — только комплексный анализ. Пинг с разными размерами пакетов, TCP-трейс, анализ заголовков. Один метод всегда даст осечку.
Заключительные мысли
TTL и RTT — не панацея, но работают в 80% случаев. Современные VPN-протоколы — OpenVPN, WireGuard, IPSec — не маскируют эти параметры по умолчанию. Пока разработчики не добавят такую функцию, методы остаются актуальными. А когда добавят — появятся новые способы. Это гонка вооружений, и она бесконечна.