Skip to content

openwarpkit/warp-relay-panel

Repository files navigation

WARP Relay Panel v1.2.2

Панель управления whitelist для WARP Relay серверов.
Бесплатный хостинг на Vercel + Supabase.


Архитектура

Telegram Bot  ──HTTP──▶  Vercel (FastAPI)  ──HTTP──▶  Relay Agent 1
                         Supabase (PostgreSQL)  ────▶  Relay Agent 2
                              ▲                 ────▶  Relay Agent N
                              │
                       Клиент по ссылке
                       (определяется IPv4)
Компонент Где Стоимость
API-панель Vercel serverless Бесплатно
База данных Supabase PostgreSQL Бесплатно (500 MB)
Relay Agent На каждом relay-сервере VPS
Telegram Bot Сервер VPS

Быстрый старт

1. Панель (Vercel + Supabase) — 5 минут

Supabase:

  1. Создать проект на supabase.com
  2. SQL Editor → вставить supabase_schema.sql → Run
  3. Скопировать Project URL и service_role key

Vercel — деплой одной кнопкой:

Deploy with Vercel

После деплоя → Settings → Environment Variables → задать:

Переменная Значение
SUPABASE_URL https://xxx.supabase.co
SUPABASE_KEY eyJ...service-role-key...
ENCRYPTION_KEY Сгенерировать: python3 -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
API_KEY Любой секретный ключ для бота
AGENT_SECRET Общий секрет для relay-агентов
MAX_ACTIVATIONS_PER_DAY 10 (0 = без лимита)

Redeploy чтобы подхватить переменные.

2. Relay-сервер — 1 команда

ssh root@RELAY_IP

git clone https://github.com/openwarpkit/warp-relay-panel.git /opt/warp-relay-panel
bash /opt/warp-relay-panel/relay-agent/setup_relay.sh

Скрипт спросит Agent secret (тот же что AGENT_SECRET на Vercel) и порт (по умолчанию 7580).
Автоматически настроит: timezone МСК, iptables, ipset, systemd, автовосстановление при перезагрузке.

3. Добавить relay в панель

PANEL="https://your-project.vercel.app"
KEY="your-api-key"

curl -X POST ${PANEL}/api/relays \
  -H "X-API-Key: ${KEY}" \
  -H "Content-Type: application/json" \
  -d '{"name": "FI-Helsinki", "host": "1.2.3.4", "agent_port": 7580}'

4. Создать клиента

curl -X POST ${PANEL}/api/clients \
  -H "X-API-Key: ${KEY}" \
  -H "Content-Type: application/json" \
  -d '{"label": "Иван", "note": "подписчик"}'

# Ответ: {"id": 1, "token": "a1b2c3d4e5f67890", ...}
# Ссылка: https://your-project.vercel.app/activate/a1b2c3d4e5f67890

5. Синхронизация

curl -X POST ${PANEL}/api/relays/sync-all -H "X-API-Key: ${KEY}"

Обновление relay-серверов

Обновление работает через API (fire-and-forget): панель отправляет команду, агент подтверждает получение и обновляется в фоне.

# Обновить все relay:
curl -X POST ${PANEL}/api/relays/update-all -H "X-API-Key: ${KEY}"

# Обновить один:
curl -X POST ${PANEL}/api/relays/{id}/update -H "X-API-Key: ${KEY}"

Ответ сразу сообщает какие relay приняли команду, а какие недоступны:

{
  "FI-Helsinki": {"accepted": true, "message": "Update started in background"},
  "DE-Frankfurt": {"error": "[DE-Frankfurt] timeout: POST /update"}
}

Проверить результат обновления — через /health каждого relay:

curl -X GET ${PANEL}/api/relays/{id}/health -H "X-API-Key: ${KEY}"
# → "last_update": {"ok": true, "new_version": "1.2.1", "finished_at": "..."}

Автовосстановление при перезагрузке

При каждом запуске агент (через ExecStartPre) проверяет и восстанавливает ipset и iptables правила из сохранённых конфигов.

Ручная установка relay (без git)
scp -r relay-agent root@RELAY_IP:/tmp/
ssh root@RELAY_IP "bash /tmp/relay-agent/setup_relay.sh"

В этом режиме обновление через API не работает — только вручную через scp.

Ручной деплой Vercel (без кнопки)
cd warp-relay-panel
npm i -g vercel
vercel
# Задать переменные в Dashboard → Settings → Environment Variables
vercel --prod

Безопасность

ENCRYPTION_KEY — критически важно

ENCRYPTION_KEY используется для шифрования IP-адресов клиентов в базе данных (Fernet AES-128-CBC).

⚠️ Если сменить ENCRYPTION_KEY — все ранее зашифрованные IP станут нечитаемыми. Клиенты будут отображаться с ошибкой decrypt_error, активации продолжат работать (будут записываться новые IP с новым ключом), но история будет потеряна.

Правила:

  • Сгенерировать один раз: python3 -c "from cryptography.fernet import Fernet; print(Fernet.generate_key().decode())"
  • Сохранить в надёжном месте (password manager)
  • Никогда не менять после начала работы с клиентами
  • Не коммитить в git

Relay-агент

Агент слушает на порту 7580 по HTTP. Защита:

# Если есть фиксированный IP панели:
ufw allow from PANEL_IP to any port 7580
ufw deny 7580

Если фиксированного IP нет (Vercel serverless) — защита через AGENT_SECRET.

Шифрование в базе

Все IP-адреса хранятся зашифрованными (Fernet). Для поиска используется SHA-256 хэш. IP-бан лист тоже зашифрован. Даже при утечке базы — IP не раскрываются.


API

Все /api/* эндпоинты требуют заголовок X-API-Key.

Клиенты

Метод Путь Описание
POST /api/clients Создать {"label":"...", "note":"..."}
GET /api/clients Список всех (?include_blocked=false)
GET /api/clients/{id} Детали клиента
GET /api/clients/{id}/logs История активаций
GET /api/clients/{id}/traffic Трафик клиента со всех relay
PATCH /api/clients/{id}/block Блокировать {"blocked": true}
DELETE /api/clients/{id} Удалить (+ убрать IP с relay)

Общий IP: при блокировке/удалении клиента IP удаляется с relay только если никто другой на этом IP не сидит.

Relay-серверы

Метод Путь Описание
POST /api/relays Добавить relay
GET /api/relays Список
DELETE /api/relays/{id} Удалить
PATCH /api/relays/{id}/toggle Вкл/выкл {"active": false}
GET /api/relays/{id}/health Здоровье + last_update
GET /api/relays/{id}/stats Статистика (клиенты, трафик, порты)
GET /api/relays/{id}/traffic Потребление трафика по IP
POST /api/relays/{id}/sync Синхронизировать whitelist
POST /api/relays/{id}/update Обновить агент (fire-and-forget)
POST /api/relays/sync-all Синхронизировать все relay
POST /api/relays/update-all Обновить все relay
GET /api/relays/health-all Проверить все relay

IP-блэклист (хард-бан)

Метод Путь Описание
POST /api/blacklist Забанить {"ip":"1.2.3.4", "reason":"..."}
GET /api/blacklist Список всех банов
GET /api/blacklist/check/{ip} Проверить IP
DELETE /api/blacklist/{id} Разбанить по ID
DELETE /api/blacklist/by-ip Разбанить {"ip":"1.2.3.4"}

IP-бан блокирует активацию для ЛЮБОГО клиента с этим IP. Клиенты не блокируются — могут активироваться с другого IP.

Трафик / Статистика / Активация

Метод Путь Описание
GET /api/traffic Трафик со всех relay (по IP)
GET /api/stats Общая статистика
GET /activate/{token} Активация по ссылке (публичный)
GET /health Healthcheck

Relay Agent API

Порт 7580. Все эндпоинты (кроме /health) требуют X-Agent-Key.

Метод Путь Описание
POST /whitelist/update {"new_ip":"...", "old_ip":"...", "client_id": 1}
POST /whitelist/remove {"ip":"..."}
POST /whitelist/sync {"clients":[{"ip":"...", "client_id": 1}]}
GET /whitelist/list Текущий ipset
GET /traffic Трафик по IP за месяц (сброс по МСК)
GET /traffic/{ip} Конкретный IP + clients_on_ip
POST /traffic/reset Принудительный сброс
GET /health Система + last_update (без авторизации)
GET /stats Клиенты, порты, сессии, трафик
GET /refcount Маппинг IP → client_ids
POST /update Самообновление (fire-and-forget)

Интеграция с Telegram-ботом

Пример для aiogram 3
import aiohttp

PANEL_URL = "https://your-project.vercel.app"
API_KEY = "your-api-key"
HEADERS = {"X-API-Key": API_KEY, "Content-Type": "application/json"}

async def create_client(label: str) -> dict:
    async with aiohttp.ClientSession() as session:
        async with session.post(
            f"{PANEL_URL}/api/clients",
            headers=HEADERS,
            json={"label": label},
        ) as resp:
            return await resp.json()

async def get_activate_url(token: str) -> str:
    return f"{PANEL_URL}/activate/{token}"

async def get_client_info(client_id: int) -> dict:
    async with aiohttp.ClientSession() as session:
        async with session.get(
            f"{PANEL_URL}/api/clients/{client_id}",
            headers=HEADERS,
        ) as resp:
            return await resp.json()

async def ban_ip(ip: str, reason: str = "") -> dict:
    async with aiohttp.ClientSession() as session:
        async with session.post(
            f"{PANEL_URL}/api/blacklist",
            headers=HEADERS,
            json={"ip": ip, "reason": reason},
        ) as resp:
            return await resp.json()

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

warp-relay-panel/
├── api/                        # Vercel serverless
│   ├── index.py                # FastAPI (роуты, активация, блэклист)
│   ├── database.py             # Supabase операции
│   ├── relay_client.py         # HTTP-клиент для relay-агентов
│   └── crypto.py               # Шифрование IP (Fernet)
├── relay-agent/                # Ставится на каждый relay
│   ├── agent.py                # FastAPI агент
│   ├── setup_relay.sh          # Полная установка
│   ├── update.sh               # Ручное обновление (fallback)
│   ├── ensure_rules.sh         # Восстановление iptables/ipset
│   ├── requirements.txt
│   └── .env.example
├── supabase_schema.sql         # SQL для создания таблиц
├── vercel.json                 # Конфигурация Vercel
├── requirements.txt            # Python зависимости (Vercel)
└── .env.example                # Переменные окружения

Changelog

v1.2.2

  • Фоновая синхронизация whitelist через /whitelist/sync
  • Статус последней синхронизации в /healthlast_sync (ok, synced, clients, in_progress)
  • Пагинация выборок из Supabase (list_clients, list_ip_bans, get_all_active_ips)
  • Исправлено удаление осиротевших IP из ipset (RefCountMap.remove_client — когда refcount=0, но IP остался в map)
  • Таймаут HTTP-запросов на /whitelist/sync поднят до 30 сек (страховка для больших payload)
  • В ответе full_sync теперь {total_clients, skipped_banned, relays: {...}} вместо плоского словаря

v1.2.1

  • Обновление relay через API (fire-and-forget, без таймаутов Vercel)
  • Статус последнего обновления в /healthlast_update
  • Timezone МСК на всех relay (трафик сбрасывается по московскому времени)
  • Документация ENCRYPTION_KEY

v1.2.0

  • IP-блэклист (хард-бан по IP)
  • Защита общих IP (refcount на панели и агенте)
  • Мониторинг трафика по IP (conntrack accounting)
  • Фильтрация ботов (Telegram preview и др.)
  • Автовосстановление iptables/ipset при перезагрузке
  • Самообновление relay через API

v1.0.1

  • Исправлен ipset destroyipset flush

v1.0.0

  • Первый релиз

About

Панель управления whitelist для WARP Relay серверов.

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors