Перейти к основному содержимому

Скрипт с мониторингом фильтрации трафика на серверах

·1135 слов·6 минут·
logo

dpich — это утилита из проекта dpi-checkers, которая запускает набор чекеров для анализа фильтрации трафика: определение IP и геолокации, проверку CIDR-шатдаунов, эвристику умных машинок (инжекты RST, сбросы TLS, подмены ответов) и диагностику DNS (спуфинг, leak, перехват DoH).

Получился checkdpi — один bash-файл, который сам подключается к серверам, проверяет, что там всё готово, запускает dpich --all и присылает отчёт обратно.

Что он делает
#

Скрипт работает с пулом удалённых серверов по SSH. Для каждого сервера он делает так:

  • проверяет, что SSH доступен;
  • проверяет свободное место;
  • смотрит, установлен ли dpich, и если нет — предлагает установить с официального репозитория;
  • сверяет локальный и удалённый конфиг по версии или по md5, и если отличается — заливает новый;
  • удаляет старые отчёты на сервере перед запуском;
  • запускает dpich, ждёт завершения, скачивает результат и проверяет, что YAML валиден.

Структура проекта
#

Всё кладите в одну папку:

checkdpi/
├── checkdpi.sh            # основной скрипт
├── config.example.yml     # шаблон конфига для dpich
└── dpi-ch-result_*.yaml   # актуальные отчёты (по одному на сервер, будут после запуска скрипта)

Шаблон конфига уже настроен на автоматический режим — auto-exit: true, формат YAML, вывод в /root/.local/dpi-ch/dpi-ch-result_.

Серверы
#

Скрипт опрашивает список серверов, заданный в переменной DEFAULT_SERVERS в начале файла. Имена соответствуют алиасам из ~/.ssh/config:

DEFAULT_SERVERS=("thor" "loki" "wanda")

Список меняется прямо в скрипте или переопределяется через аргументы.

Запуск
#

По умолчанию — последовательно, интерактивно, с отображением TUI:

./checkdpi.sh

Параллельно — все серверы одновременно, быстрее:

./checkdpi.sh -p

Можно указать конкретные серверы:

./checkdpi.sh -p thor wanda loki hulk

В параллельном режиме каждый сервер запускается в фоне через script, чтобы обойти требование TTY, а логи пишутся во временные файлы /tmp/checkdpi_<server>.log. Если что-то падает, в конце выводится последний кусок лога.

Предварительные проверки в скрипте
#

Перед запуском чекеров скрипт делает пять вещей:

  1. SSH connectivity. ssh -o BatchMode=yes -o ConnectTimeout=5 server "true". Если не проходит — сервер исключается из запуска, и потом не надо отвлекаться на час.

  2. Дисковое место. df -m в каталоге установки. Менее 100 МБ — пропуск.

  3. dpich. Проверяет, что бинарник есть в /root/.local/dpi-ch/dpich или в $PATH. Если нет — спрашивает, ставить ли, и запускает официальный скрипт установки.

  4. Конфиг. Скрипт читает версию из комментария # version: в локальном config.example.yml и сравнивает с удалённым. Если версии нет — fallback на md5sum. При несовпадении конфиг перезаливается через scp.

    При этом если на сервере вообще нет конфига — скрипт сам заливает шаблон. Дополнительных ручных действий не требуется: достаточно положить config.example.yml в папку checkdpi/ локально, и скрипт скопирует его на все серверы при первом запуске.

  5. Очистка. Удаляет старые отчёты на сервере, чтобы не было путаницы.

Синхронизация конфига
#

В начале config.example.yml есть строка:

# version: 1.0

Если менять конфиг и увеличивать версию, при следующем запуске скрипт сам подтянет изменения на все серверы. Это удобно, когда меняются таймауты, добавляются хосты для проверки или меняются фингерпринты.

Если версионности нет — скрипт сравнивает md5 локального и удалённого файла. Если различаются — обновляет.

Отчёты
#

После запуска отчёт скачивается локально с именем вида:

dpi-ch-result_<server>_<дата>.yaml

Скрипт хранит только один последний отчёт на каждый сервер. Старый удаляется только после успешной валидации нового.

Что проверяет dpich
#

В конфиге включены четыре чекера:

whoami
#

Определяет публичный IP, ASN, провайдера и геолокацию. Нужно, чтобы сразу видеть, с какого адреса идет проверка, и не перепутать серверы.

cidrwhitelist
#

Проверяет, не под шатдауном ли сервер. Если только белые доступны — фиксируется изоляция.

webhost
#

Основной чекер. Собирает пул хостов разных провайдеров (Akamai, Cloudflare, Hetzner, DigitalOcean, Vultr, OVH и другие), проверяет:

  • доступность (TCP connection)
  • TLS-рукопожатие (версия, SAN, CN)
  • эвристику умных машинок ведомства из 3 букв (tcp1620)
  • пропускную способность (bursttxkbps, burstrxkbps)

Эвристика умных машинок работает через несколько соединений с разными фингерпринтами. Если провайдер инжектит RST, сбрасывает TLS или подменяет ответы — отчёт показывает ERR или NOT_SUPPORTED_BY_HOST.

dns
#

Проверяет DNS-спуфинг, leak и перехват DoH. Тестирует классические резолверы (AdGuard, Cloudflare, Google, Yandex, Quad9, MSK-IX и др.) по UDP/TCP, а также DoH-точки.

Конфиг dpich
#

Шаблон config.example.yml выглядит так:

all:
  format: yaml
  auto-exit: true
  prefix: /root/.local/dpi-ch/dpi-ch-result_
  ts-format: 2006-01-02_15-04
  checkers:
    - whoami
    - cidrwhitelist
    - webhost
    - dns

checkers:
  cidrwhitelist:
    timeout: 7s
    whitelisted:
      - https://max.ru/
      - https://ya.ru/
      - https://vk.ru/
    regular:
      - https://github.com/
      - https://ru.wikipedia.org/
      - https://www.google.com/

  webhost:
    workers: 8
    farm-timeout: 3m
    tcp-conn-timeout: 3s
    tls-handshake-timeout: 3s
    tcp-read-timeout: 10s
    tcp-write-timeout: 10s
    siberian-conn-count: 4       # Количество соединений для детекции эвристик умных машинок

  dns:
    resolve:
      plain-opt:
        timeout: 7s
        workers: 5
      doh-opt:
        timeout: 7s
        workers: 5

inetutil:
  fingerprint: edge
  browser-headers:
    Accept-Language: ru-RU,ru;q=0.9,en-US;q=0.8,en;q=0.7
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 ...

updater:
  enabled: true
  period: 24h
  root-dir: /root/.local/dpi-ch/data

Фингерпринт выбран edge.

Установка dpich на серверах
#

Если dpich не установлен, скрипт ставит его через официальный инсталлятор:

bash <(curl -Ls https://hyperion-cs.github.io/dpi-checkers/ru/dpi-ch/install/unix.sh)

Как читать отчёт?
#

Отчёт представляет собой YAML-файл, разбитый по чекерам. Давайте разберём основные блоки на примере:

whoami:
    status:
        msg: Ok
        code: OK
    ip: 198.51.100.42 # Ваш публичный IP
    asn: AS0
    org: ""
    location: ""

whoami показывает, с какого IP и из какой сети был запущен скрипт. Полезно для уверенности, что тест прошёл именно с нужного сервера, а не через случайный VPN.

cidrwhitelist:
    status:
        msg: You're NOT under one
        code: NOT_DETECTED

cidrwhitelist проверяет шатдаун. Если бы сервер был отрезан от мира и пускал только на легитимные внутренние ресурсы, статус был бы DETECTED.

dns:
    leak:
        status:
            msg: Ok
        items:
            - ip: 2.200.XX.XX
              org: i3D.net B.V
              location: NL

В dns.leak видно, от чьего имени идут запросы к корневым серверам. В данном случае DNS-резолвер физически ходит в интернет через Заковию.

Далее идёт проверка классических (plain) DNS и DoH. Обратите внимание на перехваты и блокировки:

    plain:
        status:
            msg: Ok
        providers:
            Google DNS:
                - msg: Ok
            MSK-IX DNS:
                - msg: NXDOMAIN spoofing
                  code: NXDOMAIN_SPOOFING
            NSDI:
                - msg: NXDOMAIN spoofing
                  code: NXDOMAIN_SPOOFING
    doh:
        status:
            msg: Ok
        providers:
            Google DNS:
                - msg: Ok
            Mullvad DNS:
                - msg: 'http: malformed response'
                  code: INETUTIL_ERR

Часть аномальных ответов (например, NXDOMAIN spoofing для MSK-IX или malformed response для DoH) прямо указывает на то, что умные машинки или провайдер вмешивается в DNS-трафик и подменяет ответы.

webhost — самый большой блок. Он делает запросы к популярным хостингам и сервисам (Cloudflare, DigitalOcean, VK, Yandex, Apple и др.) и проверяет, что с ними происходит.

webhost:
    Foreign Infrastructure Providers:
        items:
            - group: Cloudflare
              ip: 104.17.67.222
              alive:
                msg: Ok
              tcp1620:
                msg: "No"
              siberian:
                msg: "No"
              bursttxkbps: 3.240756e+06

В результатах webhost важны два поля:

  • tcp1620: Если здесь tcp: connection reset или ERR, значит по пути кто-то целенаправленно рубит нужное соединение RST-пакетом.
  • siberian: Эвристика, проверяющая реакцию “умных машинок”. Если статус DETECTED, это значит, что DPI активно анализирует и ломает пакеты к этому хосту.

Для bursttxkbps и burstrxkbps отображается пропускная способность при handshake и передаче данных. Если значения сильно отличаются в меньшую сторону, возможно, применяется шейпинг провайдером.

А нафига это всё?
#

Когда серверов несколько, ручной процесс надоедает. Здесь всё в одном месте — несколько серверов, один запуск, отчёты лежат рядом, их можно сравнивать.

Без скрипта для каждой проверки нужно заходить на каждый сервер по SSH, запускать dpich, копировать отчёт, сравнивать…

Ссылки
#

Related