Торрент детекция
Принцип
Section titled “Принцип”Xray умеет детектировать BitTorrent на уровне роутинга и отправлять webhook при срабатывании правила. Никаких внешних инструментов (nDPI, iptables, NFQUEUE) не нужно.
Два действия происходят одновременно при обнаружении BitTorrent-трафика:
- Трафик уходит в
blackhole— соединение обрывается немедленно - Xray отправляет webhook в панель — панель логирует нарушение и при необходимости банит пользователя
Конфигурация Xray на ноде
Section titled “Конфигурация Xray на ноде”Routing rule
Section titled “Routing rule”{ "routing": { "rules": [ { "protocol": ["bittorrent"], "outboundTag": "block", "webhook": { "url": "https://panel-domain.com/webhooks/node-event", "deduplication": 300 } } ] }}deduplication: 300 — один и тот же пользователь не будет триггерить webhook чаще чем раз в 300 секунд (5 минут). Без этого панель получала бы тысячи запросов в секунду от одного торрент-клиента.
Blackhole outbound
Section titled “Blackhole outbound”{ "outbounds": [ { "tag": "block", "protocol": "blackhole", "settings": { "response": { "type": "http" } } } ]}type: "http" — возвращает HTTP 403 вместо просто обрыва TCP. Торрент-клиент быстрее понимает что соединение отклонено.
Webhook от Xray
Section titled “Webhook от Xray”Xray отправляет POST-запрос на указанный URL при срабатывании правила. Payload содержит информацию о пользователе (email-тег из inbound) и деталях соединения.
Пример payload (на основе документации Xray):
{ "user": "abc123@astral", "inbound": "vless-ws-tls", "protocol": "bittorrent", "timestamp": 1737000000}user — это xray email тег, который мы задаём при добавлении клиента в формате {user_id}@astral. Из него достаём user_id.
Панель: обработка webhook
Section titled “Панель: обработка webhook”Endpoint
Section titled “Endpoint”POST /webhooks/node-eventАутентификация: Xray не поддерживает добавление заголовков в webhook из коробки, поэтому URL содержит секретный токен:
https://panel-domain.com/webhooks/node-event?token={NODE_SECRET}Либо — настроить на ноде nginx-прокси, который добавляет Authorization заголовок перед форвардингом на панель.
Логика обработки
Section titled “Логика обработки”func (h *WebhookHandler) HandleNodeEvent(c fiber.Ctx) error { // Проверка токена из query param if c.Query("token") != h.cfg.NodeWebhookSecret { return c.SendStatus(401) }
var event XrayWebhookEvent c.BodyParser(&event)
// "abc123@astral" → "abc123" userID := strings.TrimSuffix(event.User, "@astral")
violation := &Violation{ UserID: userID, Protocol: event.Protocol, InboundTag: event.Inbound, DetectedAt: time.Unix(event.Timestamp, 0), } h.violationRepo.Create(violation)
// Считаем нарушения за последние 24 часа count := h.violationRepo.CountRecent(userID, 24*time.Hour)
switch { case count == 1: h.notifier.SendWarning(userID) case count >= 3: h.subscriptionService.Suspend(userID, SuspendReasonTorrent) h.worker.Enqueue(SyncUserTask{UserID: userID}) h.notifier.SendSuspended(userID) }
return c.SendStatus(200)}Политика (настраивается в админке)
Section titled “Политика (настраивается в админке)”| Нарушений за 24ч | Действие |
|---|---|
| 1 | Предупреждение (email / Telegram) |
| 2 | Повторное предупреждение |
| 3+ | Приостановка подписки + sync на ноды |
Управление конфигом через агента
Section titled “Управление конфигом через агента”Routing rule с webhook добавляется при инициализации ноды. Агент применяет его через Xray API при первом запуске или при изменении настроек из админки.
// При добавлении ноды в панели агент получает команду применить базовый конфиг// включая torrent-blocking rule
func (a *Agent) ApplyBaseConfig(cfg *BaseConfig) error { // Добавляем blackhole outbound a.handlerClient.AddOutbound(...)
// Добавляем routing rule через Xray Routing API a.routerClient.AddRule(...)
return nil}URL для webhook берётся из конфига агента (передаётся панелью при регистрации ноды) — так можно централизованно менять URL без правки конфигов на каждой ноде вручную.
Изменения в БД
Section titled “Изменения в БД”Два новых объекта (добавить при финализации схемы):
violation_logs
id,user_id,inbound_tag,protocol,detected_at
user_warnings
id,user_id,reason,sent_at,acknowledged_at
В subscriptions: добавить torrent_suspended в enum status (или отдельное поле suspend_reason).
Ограничения
Section titled “Ограничения”Частичная детекция. Xray не гарантирует 100% детекцию всех BitTorrent-соединений (зашифрованный MSE, нестандартные порты). Но этого достаточно как основание для предупреждения/бана — пользователь явно использует торрент-клиент.
deduplication. 300 секунд означает что между первым срабатыванием и блокировкой пользователь успеет скачать ~50-100 МБ. Если нужна мгновенная блокировка — логика suspend должна срабатывать уже на первом нарушении, а не на третьем.