Skip to content

[Feature/Bug] Ложные срабатывания и пропуски: необходимость послойной диагностики (L3/L4/L7) для детекции ТСПУ/DPI #5

Description

@Brensom

Использую censorcheck для диагностики сети в связке с Zapret2 (nfqws2) и локальным DoH (dnscrypt-proxy2). Инструмент хорошо справляется с проверкой доступности, но архитектурная зависимость от curl и nslookup (L7) делает невозможным отличить цензуру на уровне сети (DPI/L3) от ограничений сервера (WAF).

Это приводит к ложным срабатываниям и пропуску блокировок, которые выглядят как "сайт не отвечает", хотя на самом деле применяется DPI.

Эмпирические данные

ТСПУ используют разные механизмы блокировки, которые censorcheck интерпретирует одинаково:

Домен Вывод censorcheck Реальный механизм Технические данные
instagram.com Blocked by IP L3 IP-бан TCP SYN дропается (tcping: CLOSED)
discord.com Blocked or site didn't respond L7 TCP-freeze TCP OPEN, TLS OK, но передача данных обрывается (0 байт за 5с)
facebook.com Redirected (307) HTTP-инъекция DPI Редирект на домен-заглушку провайдера
x.com Access Denied (403) WAF / Geo-block 403 от Cloudflare, сайт не заблокирован провайдером

Предложения по архитектуре

1. Разделять L3 IP-бан и L7 TCP-freeze

Функция is_port_open проверяет только SYN-ACK. При TCP-freeze порт открыт, но данные не идут.
Решение: Анализировать объем скачанных данных и тайминг. Если порт OPEN, TLS OK, но size_download == 0 при time_total >= timeout — это TCP-freeze (DPI drops large packets).

2. Детекция HTTP-инъекций (редиректы на заглушки)

Редирект 307 на домен провайдерской заглушки — это не обычный редирект.
Решение: Анализировать заголовок Location при 3xx. Если он содержит известные паттерны заглушек (например, tspu., block.), классифицировать как DPI Injection, а не Redirected.

3. Проблема с --retry-all-errors

Флаг --retry-all-errors в curl_opts (строка 252) заставляет ретраить HTTP-ошибки. При DPI-инъекции с 307, curl может уйти в ретрай или следовать редиректу (-L), загрузить страницу заглушки и выдать ложный статус доступности. Для диагностики цензуры ретраи HTTP-ошибок маскируют саму блокировку.

4. Классификация 403 от Cloudflare

403 от Cloudflare — это Bot Detection или Geo-block, а не DPI.
Решение: Анализировать заголовок Server: cloudflare. При коде 403 и наличии этого заголовка классифицировать как WAF/Geo-block (not DPI). Это снизит шум для пользователей, отлаживающих обход.

5. Детекция DNS Spoofing при локальном DoH

Текущая проверка check_dns_hijacking сравнивает системный DNS и DoH. Если система уже использует локальный DoH/DoT (dnscrypt-proxy2), оба запроса идут через один зашифрованный канал. Подмена на уровне провайдерского UDP не детектируется.
Решение: Для проверки спуфинга нужен прямой UDP-запрос в обход локального прокси (например, через /dev/udp/9.9.9.9/53), так как dig @9.9.9.9 может всё равно маршрутизироваться через локальный резолвер.

Предлагаемая модель реализации

Чтобы не ломать текущий UI, предлагаю вынести классификацию в опциональный флаг --classify или расширить JSON-вывод (-j) полем block_type:

  • l3_ip_ban (TCP CLOSED)
  • l7_tcp_freeze (Port OPEN, TLS OK, 0 bytes)
  • dpi_injection (307 to ISP stub)
  • waf_geo_block (403 Cloudflare)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions