Skip to content

Latest commit

 

History

History
299 lines (212 loc) · 12.2 KB

File metadata and controls

299 lines (212 loc) · 12.2 KB

EN / RU / ZH

sub-filter

Умный фильтр подписок на прокси-серверы (VLESS, VMess, Trojan, Shadowsocks, Hysteria2).
Программа проверяет каждую ссылку внутри подписки на:

  • безопасность (например, блокирует security=none в VLESS),
  • корректность (например, требует pbk при security=reality),
  • наличие «запрещённых слов» в названии или адресе сервера на основании гибких правил (вырезать или удалить),
  • фильтрация описания серверов по странам, их флагам и национальным названиям.

Результат — чистая, рабочая подписка, готовая к использованию в Clash, Sing-Box, роутерах и других клиентах.

⚠️ Программа не проверяет живучесть прокси. Для этого используйте xray-checker.


Что умеет программа?

✅ Валидация по гибким правилам из rules.yaml и настройкам из badwords.yaml
✅ Фильтрация по одной или нескольким странам (до 20) и плохим словам
✅ Дедупликация ссылок с выбором наиболее полной версии среди одинаковых серверов
✅ Кеширование (по умолчанию 30 минут)
✅ Поддержка CLI-режима с выводом в терминал


Как собрать программу?

Требуется Go 1.21+.

go build -o sub-filter .

Архитектура

Проект использует модульную архитектуру с dependency injection:

  • pkg/config: Загрузка и валидация конфигурации из YAML/JSON/TOML файлов
  • pkg/service: Основная бизнес-логика, HTTP handlers, кэширование regex
  • pkg/errors: Типизированные ошибки с кодами и severity
  • pkg/logger: Структурированное логирование на основе slog
  • pkg/cache: Кэширование скомпилированных regex для производительности

Протоколы (VLESS, VMess, etc.) реализованы в отдельных пакетах с общим интерфейсом ProxyLink.


Как запустить?

Программа поддерживает два режима работы: HTTP-сервер и CLI (консольный).

Пример конфигурационных файлов

Формат конфигурации

Основной файл config/config.yaml:

# Пути к файлам
sources_file: "./config/sub.txt"      # Список URL подписок
rules_file: "./config/rules.yaml"     # Правила валидации
bad_words_file: "./config/badwords.yaml" # Запрещенные слова
uagent_file: "./config/uagent.txt"    # User-Agent для запросов

# Кэширование
cache_dir: "/tmp/sub-filter-cache"    # Директория кэша
cache_ttl: 1800s                      # Время жизни кэша

# Лимиты
max_country_codes: 20                 # Макс кодов стран
max_merge_ids: 10                     # Макс подписок для merge
merge_buckets: 256                    # Шарды для merge

Режим 1: HTTP-сервер (динамическая фильтрация)

Запускается с указанием порта. Подписки фильтруются «на лету» при каждом запросе.

Синтаксис:

./sub-filter <порт> [cache_ttl] [sources_file] [bad_words_file] [uagent_file] [rules_file]

Примеры:

# Минимальный запуск (использует файлы из ./config/)
./sub-filter 8000

# Полный запуск
./sub-filter 8000 1800 ./config/sub.txt ./config/bad.txt ./config/uagent.txt ./config/rules.yaml

Эндпоинты:

Эндпоинт Описание
/filter Фильтрация одной подписки
/merge Объединение и фильтрация нескольких подписок

Параметры:

  • id — номер строки из sources_file (для /filter)
  • ids — номера строк через запятую (для /merge, максимум 20)
  • c — коды стран по ISO 3166-1 alpha-2 через запятую (максимум 20)
  • lim — максимальное количество ссылок в результате (для /filter и /merge)

Примеры:

  • /filter?id=1 — фильтрация первой подписки
  • /filter?id=1&c=DE — фильтрация по Германии
  • /merge?ids=1,2,3&c=US,CA — объединение трёх подписок с фильтрацией по США и Канаде

Режим 2: CLI (однократная обработка)

Обрабатывает все подписки один раз и сохраняет результаты в кеш.

Синтаксис:

./sub-filter --cli [--stdout] [--config файл.yaml] [--country AD,DE]

Флаги:

Флаг Описание
--cli Запуск в CLI-режиме
--stdout Вывод результата в терминал
--config Использовать внешний файл конфигурации
--country Фильтрация по странам (например, --country=AR,AE)

Примеры:

# Обработать все подписки и сохранить в кеш
./sub-filter --cli

# Вывести результат в терминал
./sub-filter --cli --stdout

# Обработать с фильтрацией по странам
./sub-filter --cli --country=NL,RU

# Использовать внешний конфиг
./sub-filter --cli --config ./my-config.yaml

Фильтрация по странам

Формат стран

Информация о странах хранится в ./config/countries.yaml в плоском формате:

RU:
  cca3: RUS
  flag: '🇷🇺'
  name: Russia
  native: 'Россия|Российская Федерация'

Программа ищет внутри фрагмента ссылки (#...) следующие строки:

  • Код страны (CCA2): RU
  • Код (CCA3): RUS
  • Флаг: 🇷🇺
  • Общее название: Russia
  • Национальные названия: Россия, Российская Федерация

Сравнение — регистронезависимое и поддерживает URL-декодирование.


Что означают параметры?

Параметр Описание
<порт> Порт HTTP-сервера (обязателен в серверном режиме)
cache_ttl Время кеширования в секундах (по умолчанию 1800)
sources_file Список URL-подписок (по одному на строку) sub.txt
bad_words_file Список правил обработки запрещённых слов (удалить/вырезать) badwords.yaml
uagent_file Список разрешённых User-Agent (например, Clash) uagent.txt
rules_file Файл правил валидации rules.yaml

Флаги CLI

Флаг Описание
--cli Запуск в CLI-режиме
--stdout Вывод результата в stdout
--config Путь к файлу конфигурации
--country Фильтрация по странам (только в CLI)

Как проверить, что всё работает?

Сервер

curl -H "User-Agent: Clash" "http://localhost:8000/filter?id=1&c=AD"

CLI

./sub-filter --cli --country=US --stdout

Результаты сохраняются в /tmp/sub-filter-cache (или в указанную директорию).


Как использовать в клиенте?

Добавьте подписку вида:

http://ваш-сервер:8000/filter?id=1&c=NL,RU

🔒 Рекомендуется использовать за reverse proxy с HTTPS.


Docker

Запуск сервера

docker run -d \
  -p 8080:8080 \
  -v $(pwd)/config:/config:ro \
  -v $(pwd)/cache:/tmp/sub-filter-cache \
  ghcr.io/viktor45/sub-filter:latest \
  8080 1800

CLI в Docker

# Обработка подписок
docker run --rm \
  -v $(pwd)/config:/config:ro \
  -v $(pwd)/cache:/tmp/sub-filter-cache \
  ghcr.io/viktor45/sub-filter:latest \
  --cli --country=DE

# Вывод в терминал
docker run --rm \
  -v $(pwd)/config:/config:ro \
  -v $(pwd)/cache:/tmp/sub-filter-cache \
  ghcr.io/viktor45/sub-filter:latest \
  --cli --stdout

💡 Убедитесь, что папки ./config и ./cache существуют перед запуском.