- PVSM.RU - https://www.pvsm.ru -
В последние годы в России активно развивается и применяется инфраструктура фильтрации трафика на уровне провайдеров. Основные технологии, которые используются для этого — ТСПУ (технические средства противодействия угрозам) и DPI (Deep Packet Inspection).
В этой статье мы разберём, как именно эти системы видят и классифицируют трафик, на каких полях и протоколах принимаются решения о блокировке, и какие техники применяются для обхода (с точки зрения механики, а не «инструкций»).
ТСПУ — это общее название комплекса оборудования и ПО, которое устанавливается у операторов связи в соответствии с требованиями законодательства (в первую очередь 149-ФЗ "О связи" (закон о "суверенном интернете"), 398-ФЗ и приказы Роскомнадзора). Это "чёрные ящики" на сетях провайдеров, под контролем Роскомнадзора (РКН). К 2023–2026 годам покрытие — 100% узлов связи, с переходом на отечественное оборудование (Сигналтек, Yadro, Ростелеком).
Основные функции ТСПУ:
Централизованно задаёт правила для DPI (что блокировать и как).
Синхронизирует списки (в т.ч. реестры).
Собирает отчёты от DPI и передаёт их в центр управления.
DPI — это ключевая технология внутри ТСПУ. Обычный маршрутизатор анализирует только заголовки сетевого (L3) и транспортного (L4) уровней: IP-адреса и TCP/UDP порты. DPI-системы заглядывают в Payload (полезную нагрузку) пакета, анализируя протоколы прикладного уровня (L7). Используется для идентификации трафика (HTTP/S, QUIC, VPN, Tor), даже зашифрованного (по SNI, JA3/JA4 отпечаткам, поведенческим паттернам).
Основные функции DPI:
DPI-анализ (глубокая проверка пакетов).
Фильтрация по спискам запрещённых ресурсов (реестр РКН).
Блокирование по IP, доменам, SNI, протоколам, сигнатурам.
Протокольная идентификация (HTTP, HTTPS, QUIC, VPN-протоколы, Tor, Shadowsocks и др.).
Сбор статистики и передача в центр управления.
DPI-узел находится в разрыве трафика (inline) или получает копию трафика (mirror/SPAN). В режиме inline система может:
пропускать пакет;
дропать пакет;
подменять ответ (RST, FIN, HTTP redirect);
маркировать поток для дальнейшей обработки.
Inline (в разрыв): трафик физически проходит через DPI.
Mirror/SPAN: копия трафика отправляется на DPI, оригинальный поток не прерывается. DPI может только анализировать и сигнализировать, но не вмешиваться напрямую.
Клиент — пользователь (абонент).
BRAS/BNG — узел провайдера, где пользователь (абонент) аутентифицируется и получает доступ в сеть.
DPI — инспектирует и фильтрует трафик (inline или mirror).
Upstream / IX — внешний интернет.
ТСПУ управляет DPI-узлами через централизованные политики: сигнатуры, списки доменов, IP, протоколов, шаблоны поведения.
DPI анализирует трафик послойно, по модели OSI.
На этом уровне доступны: source/destination IP и port, TCP flags, sequence/ack numbers, размер и частота пакетов.
Этого достаточно для: блокировок по IP, rate limiting, детектирования некоторых VPN/туннелей по паттернам.
Для небезопасных протоколов (HTTP, DNS без шифрования) DPI видит полезную нагрузку целиком. Для зашифрованных протоколов (TLS) анализ ограничен метаданными.
Хотя современный интернет практически полностью перешёл на HTTPS (TLS), процесс установления соединения начинается в открытом виде. При инициации HTTPS-соединения клиент отправляет пакет ClientHello, который не зашифрован. Этот пакет содержит ключевую информацию: версию TLS, список поддерживаемых cipher suites и extensions.
Одним из наиболее важных расширений является SNI (Server Name Indication). SNI передаёт доменное имя сервера в открытом виде (например, server_name = example.com [1]). Это необходимо серверу для выбора правильного SSL-сертификата, особенно когда несколько доменов размещены на одном IP-адресе.
DPI-системы активно используют эту особенность для блокировки сайтов. Алгоритм работы DPI выглядит следующим образом:
Перехватывает TCP-пакет с флагами PSH и ACK.
Парсит структуру TLS Record.
Извлекает значение поля server_name из расширения SNI.
Сопоставляет его с политиками или чёрным списком (например, реестром запрещённых ресурсов).
Принимает решение до установления полной TLS-сессии: в случае совпадения отправляет клиенту TCP RST (разрыв соединения), перенаправляет на заглушку или применяет другие меры блокировки.
Даже в TLS 1.3 SNI остаётся видимым, если не используется Encrypted Client Hello (ECH). DPI не может видеть HTTP-заголовки, полный URL или тело запроса, поскольку они зашифрованы после установки сессии. Однако SNI предоставляет достаточно информации для предварительной фильтрации.
После того как DPI увидел SNI, возможны два основных сценария блокировки:
SNI-блокировка — разрыв соединения (TCP RST) сразу после получения ClientHello
IP-блокировка — после разрешения домена (через DNS или DoH/DoT) в реестр добавляется IP-адрес, и блокируется уже по IP
Многие провайдеры комбинируют оба метода.
DNS как дополнительный источник информации
До начала TLS-handshake почти всегда выполняется DNS-запрос. Если DNS не зашифрован (стандартный UDP/TCP на порт 53), DPI видит QNAME (имя домена в запросе) и может блокировать соединение ещё на этапе разрешения домена. В случае использования зашифрованных протоколов, таких как DoH (DNS over HTTPS) или DoT (DNS over TLS), DNS-запрос скрыт, и DPI полагается на SNI, IP-адрес после разрешения или поведенческие признаки трафика.
Поведенческий анализ для сложных случаев
Когда прямых сигнатур (как SNI) недостаточно, DPI применяет статистический и поведенческий анализ:
Размер первых пакетов в соединении.
Тайминги отправки и получения данных.
Направление и объём трафика.
Характер retransmission (повторных передач).
Это позволяет классифицировать и блокировать VPN-протоколы, прокси или туннели поверх HTTPS, даже если они маскируются под обычный трафик.
Пример захвата SNI с помощью Scapy
Для понимания того, как DPI видит ваши пакеты, воспользуемся библиотекой scapy. Напишем простой сниффер, который выделяет домены из TLS-трафика.
from scapy.all import sniff
from scapy.layers.inet import IP
from scapy.layers.tls.all import TLSClientHello, TLSExtensionServerName
def extract_sni(pkt):
# Проверяем наличие TLS ClientHello в пакете
if TLSClientHello not in pkt:
return None
# Перебираем расширения в поисках ServerName
# В Scapy расширения лежат в поле .extensions или .ext (зависит от версии)
extensions = getattr(pkt[TLSClientHello], 'extensions', pkt[TLSClientHello].ext)
for ext in extensions:
if isinstance(ext, TLSExtensionServerName):
try:
# Извлекаем первый сервер из списка (обычно он там один)
server_name = ext.servernames[0].servername.decode('utf-8')
return server_name
except (IndexError, AttributeError):
continue
return None
def packet_callback(pkt):
sni = extract_sni(pkt)
if sni:
src_ip = pkt[IP].src
print(f"[DPI Alert] Detected SNI: {sni} from {src_ip}")
print("Сниффинг запущен. Ожидание TLS ClientHello...")
# Фильтр tcp port 443 ускоряет работу, отсекая лишний мусор
sniff(filter="tcp port 443", prn=packet_callback, store=0)
Важно понимать: DPI не расшифровывает содержимое TLS-трафика в обычном режиме работы. Для настоящей расшифровки потребовался бы полноценный MITM (man-in-the-middle), а это практически невозможно в масштабах провайдера по следующим причинам:
Нет приватного ключа сервера Без него невозможно расшифровать сессию TLS.
Невозможно вмешаться в handshake без подмены сертификата Современные браузеры и приложения проверяют цепочку сертификатов и используют Certificate Transparency, HPKP (устаревший), Expect-CT, а также встроенные списки pinned сертификатов (например, в Chrome, Firefox, Telegram, Signal). Подмена сертификата сразу вызовет ошибку.
Поэтому реальные DPI-системы работают исключительно с незашифрованными или метаданными:
на этапе до шифрования (ClientHello, SNI, JA3/JA4 отпечатки)
по метаданным соединения (IP-адреса, порты, объём первых пакетов, тайминги)
по поведенческим признакам и корреляции потоков (паттерны трафика, характер retransmission, размер пакетов, направление)
Именно поэтому блокировка происходит чаще всего именно по SNI или по уже известным IP-адресам после разрешения DNS, а не по содержимому запросов и ответов.
Один из классических способов обхода примитивных DPI — фрагментация пакета. Если разбить Client Hello на два TCP-сегмента, система фильтрации может не собрать их воедино для анализа сигнатуры, если она настроена на «потоковую» обработку без полноценного реассемблирования (что дорого по ресурсам).
Ниже пример псевдокода, который создает сырой сокет и отправляет фрагментированный запрос:
from scapy.all import IP, TCP, Raw, send
def fragment_client_hello(dst_ip, dst_port, sni):
"""
Упрощённая демонстрация фрагментации TLS ClientHello.
Отправляет SYN, затем разбитый на 2 части пакет с началом ClientHello и SNI.
"""
# Шаг 1: Отправка SYN для начала TCP-handshake (упрощённо, без SYN-ACK)
ip = IP(dst=dst_ip)
tcp_syn = TCP(dport=dst_port, flags="S")
send(ip / tcp_syn, verbose=0)
# Пример начала ClientHello (TLS record header + начало handshake)
client_hello_start = b"x16x03x01x00xaax01x00x00xa6x03x03" # ContentType=22 (handshake), version=3.1 (TLS 1.0), length, etc.
# Часть с SNI (упрощённо, extension server_name)
sni_bytes = sni.encode('utf-8')
sni_extension = b"x00x00" + len(sni_bytes + 3).to_bytes(2, 'big') + b"x00" + len(sni_bytes).to_bytes(2, 'big') + b"x00" + sni_bytes # server_name extension
client_hello_sni = b"x00x00x00" + sni_extension # Placeholder для остальной части
# Шаг 2: Фрагментированные пакеты (seq нужно корректировать на основе реального SYN-ACK)
# Part 1: Начало ClientHello
tcp_part1 = TCP(dport=dst_port, seq=1, ack=1, flags="PA") # Упрощённо, seq/ack должны быть реальными
part1 = ip / tcp_part1 / Raw(load=client_hello_start)
send(part1, verbose=0)
# Part 2: Продолжение с SNI (seq = предыдущий seq + len(payload part1))
tcp_part2 = TCP(dport=dst_port, seq=1 + len(client_hello_start), ack=1, flags="PA")
part2 = ip / tcp_part2 / Raw(load=client_hello_sni)
send(part2, verbose=0)
print(f"Фрагментированный ClientHello с SNI '{sni}' отправлен на {dst_ip}:{dst_port}")
# Пример вызова (требует root-прав: sudo python3 script.py)
# fragment_client_hello("93.184.216.34", 443, "example.com")
Это псевдокод для демонстрации. В реальности нужно обработать SYN-ACK от сервера, рассчитать правильные seq/ack и использовать полный ClientHello (можно сгенерировать через Scapy's TLSClientHello).
Фрагментация работает на уровне IP или TCP-сегментов, но современные DPI часто собирают фрагменты перед анализом.
Важно: реальная фрагментация требует аккуратной работы с последовательными номерами, MSS, window size и т.д.
С переходом многих сервисов на QUIC (UDP 443) классический SNI-анализ становится сложнее, потому что:
Initial пакет QUIC шифрует большую часть заголовков
SNI тоже может быть зашифрован (ECH)
* ECH (Encrypted Client Hello) — расширение, позволяющее зашифровать поле SNI, используя публичный ключ сервера, полученный через DNS (DoH/DoT). В этом случае DPI видит только адрес «фронтэнда» (например, Cloudflare), но не конечный целевой домен. Однако внедрение ECH замедляется из-за активного противодействия со стороны регуляторов, которые могут блокировать трафик с неизвестными ECH-конфигурациями.
Но на 2026 год большинство DPI-систем в России всё ещё довольно эффективно блокируют QUIC по:
UDP-порту 443
сигнатурам Initial-пакета
известным CID (Connection ID) крупных сервисов
статистике трафика (объём, паттерны)
Технические ограничения DPI
Глубокая инспекция пакетов на уровне L7 требует значительных вычислительных ресурсов: каждый поток необходимо разобрать, классифицировать и сопоставить с наборами сигнатур и политик в реальном времени. При росте пропускной способности сети это приводит к высокой нагрузке на DPI-узлы и необходимости компромиссов между глубиной анализа и производительностью.
Дополнительной проблемой является рост ложных срабатываний: схожие паттерны трафика у легитимных сервисов и запрещённых приложений могут приводить к ошибочной блокировке. DPI также сильно зависит от актуальности сигнатур — любые изменения в протоколах или реализации приложений требуют постоянного обновления правил, иначе эффективность фильтрации снижается.
Архитектурные ограничения
Многие сети используют асимметричную маршрутизацию, при которой прямой и обратный трафик проходят через разные узлы. В таких условиях DPI видит лишь часть сессии, что усложняет корректный анализ состояний TCP и прикладных протоколов.
Отдельной проблемой является распространение QUIC, работающего поверх UDP: отсутствие классического TCP-handshake и шифрование значительной части метаданных резко сокращают объём информации, доступной для инспекции.
В перспективе дополнительным ограничением становится внедрение ECH (Encrypted Client Hello), при котором поле SNI шифруется. Это лишает DPI одного из ключевых источников информации о целевом домене и вынуждает системы фильтрации полагаться почти исключительно на IP-адреса и поведенческие признаки.
JA3 / JA4 — отпечатки TLS-клиента (очень эффективно для выявления VPN, прокси, ботов)
HTTP/2 + HTTP/3 заголовки (псевдозаголовки, порядок, значения)
Протокольные сигнатуры (WireGuard, OpenVPN, Shadowsocks, VLESS, VMess, Hysteria и др.)
Анализ поведения (объём трафика, количество соединений, интервалы)
Современные системы ТСПУ/DPI — это уже не просто «чёрные списки IP». Это сложные системы, которые комбинируют: пассивный анализ L4–L7, активное зондирование, машинное обучение для выявления аномалий, а также базы отпечатков TLS и протоколов. В настоящее время наблюдается настоящая «гонка вооружений» между архитекторами сетевых протоколов, стремящимися к большей приватности и устойчивости (например, через ECH, QUIC и обфускацию трафика), и разработчиками систем фильтрации, такими как ТСПУ и DPI, которые постоянно развиваются с помощью ИИ и новых сигнатур для выявления и блокировки нежелательного трафика. В перспективе, с ростом использования ECH, QUIC и ИИ в DPI, эволюция этих технологий продолжится, требуя от инженеров новых подходов к сетевой архитектуре.
Автор: DevRoad
Источник [3]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/tcp/444034
Ссылки в тексте:
[1] example.com: http://example.com
[2] Image: https://sourcecraft.dev/
[3] Источник: https://habr.com/ru/articles/992232/?utm_source=habrahabr&utm_medium=rss&utm_campaign=992232
Нажмите здесь для печати.