- Документация для
badwords.yaml - Назначение и концепция
- Структура файла
- Типы действий
- Синтаксис регулярных выражений
- Практические примеры
- Правила написания паттернов
- Отладка и тестирование
- Рекомендации по организации
- Заключение
Файл badwords.yaml — это набор правил для фильтрации и модификации названий прокси-ссылок в программе sub-filter.
Думайте о нём как о словаре "плохих слов", но не в смысле цензуры, а в смысле удаления бесполезной, рекламной, или опасной информации из названий серверов.
"Bad word" — это паттерн (слово, фраза или регулярное выражение), который появляется в названии прокси и нежелателен в финальном списке. Примеры:
- [TEST] в имени → указывает на тестовый сервер (не нужен в боевом списке)
- [SPAM] в имени → явный маркер спама
- 192.168.x.x в имени → приватный IP (признак ошибки парсинга)
- v1.2.3 в имени → номер версии (загромождает имя)
sub-filter поддерживает две стратегии обработки найденного паттерна:
strip— удалить только найденный паттерн из имени, оставить строку (сервер принят, имя очищено)delete— удалить всю строку целиком (сервер полностью отклонен)
Выбор стратегии зависит от важности фильтруемого контента:
strip— для незначительного мусора (версии, маркеры, демо-версии)delete— для критических ошибок (спам, вредонос, недействительные параметры, локальные IPs)
Файл badwords.yaml содержит массив правил. Каждое правило — это объект с тремя полями:
- pattern: "ваше регулярное выражение для вырезания"
action: "strip"
- pattern: "ещё одно выражение для удаления всей строки"
action: "delete"
- pattern: "fp=chrome"
action: "replace"
replacement: "fp=firefox"| Поле | Тип | Обязательное | Описание |
|---|---|---|---|
pattern |
строка | ✅ да | Регулярное выражение (Go regexp синтаксис) |
action |
строка | ✅ да | strip, delete или replace |
replacement |
строка | ✅ да для replace |
Строка замены при action: "replace" |
# Удалить слово "test" из имени
- pattern: "test"
action: "strip"
# Отклонить весь сервер, если в имени есть "spam"
- pattern: "\\[spam\\]"
action: "delete"Поведение: найденная подстрока удаляется из имени, сервер остаётся в списке.
Процесс:
- Найти совпадение с паттерном в имени сервера
- Удалить найденное совпадение
- Сжать несколько пробелов в один
- Обрезать пробелы в начале и конце
- Вернуть обновлённое имя
Когда использовать:
- Удаление версий (
v1.2.3) - Удаление тестовых маркеров (
[TEST],[DEMO]) - Удаление мусора и рекламы, не влияющего на функциональность (
#1,@admin, etc.)
Пример результата:
Входное имя: "My [TEST] Server v1.2.3"
Паттерн 1: "\[TEST\]" (strip) → "My Server v1.2.3"
Паттерн 2: "v\d+\.\d+\.\d+" (strip) → "My Server"
Финальное имя: "My Server"
Статус: ✅ ПРИНЯТ
Поведение: найденная подстрока отвергает всю строку целиком, сервер полностью исключается из списка.
Процесс:
- Найти совпадение с паттерном в имени сервера
- Если совпадение найдено: отклонить сервер
- Если совпадений нет: продолжить обработку
Когда использовать:
- Блокировка опасного контента (
[SPAM],[MALWARE]) - Блокировка приватных IPs (признак ошибки парсинга)
- Блокировка неработающих портов (
port: 99999) - Блокировка устаревших протоколов
Пример результата:
Входное имя: "Server [SPAM] in US"
Паттерн: "\\[spam\\]" (delete, регистронезависимый)
Результат: ❌ ОТКЛОНЕНО (вся строка удалена)
Поведение: найденная подстрока заменяется на другую, сервер остаётся в списке.
Поля правила:
pattern— регулярное выражение для поискаaction: "replace"replacement— строка, которая подставляется вместо найденного совпадения
Процесс:
- Найти совпадение с паттерном в имени сервера
- Заменить совпадение на значение
replacement - Сжать несколько пробелов в один
- Обрезать пробелы в начале и конце
- Вернуть обновлённое имя
Когда использовать:
- Исправление параметров, которые не влияют на работу, но мешают фильтрации
- Корректировка значений внутри фрагментов ссылки без удаления всей строки
- Замена устаревших или нежелательных меток на безопасные альтернативы
Пример:
- pattern: "fp=chrome"
action: "replace"
replacement: "fp=firefox"Если правило совпало,
fp=chromeбудет заменено наfp=firefox, а строка сохранится.
sub-filter использует Go regexp пакет (синтаксис POSIX Extended Regular Expression с расширениями Go).
| Конструкция | Значение | Пример |
|---|---|---|
. |
Любой символ (кроме \n) |
a.c → abc, aXc |
* |
0 или больше | ab*c → ac, abc, abbc |
+ |
1 или больше | ab+c → abc, abbc |
? |
0 или 1 | ab?c → ac, abc |
[abc] |
Один из символов | [aeiou] → любой гласный |
[^abc] |
Не один из символов | [^0-9] → не цифра |
[a-z] |
Диапазон | [0-9] → любая цифра |
(...) |
Группировка | (ab)+ → ab, abab |
| |
ИЛИ | cat|dog → cat или dog |
| Последовательность | Значение |
|---|---|
\d |
Любая цифра (0-9) |
\D |
Не цифра |
\w |
Буква, цифра, подчёркивание |
\W |
Не буква, цифра, подчёркивание |
\s |
Пробел, табуляция, новая строка |
\S |
Не пробельный символ |
^ |
Начало строки |
$ |
Конец строки |
\b |
Граница слова |
\\ |
Экранирование спецсимволов |
Go regexp использует встроенные флаги синтаксиса:
| Флаг | Назначение |
|---|---|
(?i) |
Регистронезависимый поиск (include в начало паттерна) |
(?m) |
Многострочный режим |
Примеры:
(?i)test # "test", "TEST", "Test" — все совпадают
(?i)\[demo\] # "[DEMO]", "[demo]", "[Demo]" — все совпадают
Если вам нужно искать буквальный спецсимвол (а не его особый смысл), экранируйте его обратной косой чертой:
| Символ | Экранирование | Пример |
|---|---|---|
. |
\. |
example\.com → ищет "example.com" (с точкой) |
[ |
\[ |
\[TEST\] → ищет "[TEST]" (квадратные скобки) |
( |
\( |
\(v1\) → ищет "(v1)" |
* |
\* |
\*plus\* → ищет "plus" |
\ |
\\ |
C:\\path\\to\\file → ищет "C:\path\to\file" |
# НЕПРАВИЛЬНО (YAML поглотит одну косую):
pattern: "\[TEST\]" # YAML прочитает это как "[TEST" — не то!
# ПРАВИЛЬНО:
pattern: "\\[TEST\\]" # YAML прочитает "\[TEST\]" → regex поймёт "[TEST]"Задача: из имени "Server v1.2.3 Fast" удалить версию, оставив сервер.
- pattern: '\bv\d+\.\d+(\.\d+)?\b'
action: "strip"
# Объяснение:
# \b — граница слова (чтобы не совпадать "version")
# v\d+\.\d+ — "v" + цифры + "." + цифры (v1.2)
# (\.\d+)? — опционально ".3"Результат:
Входное имя: "Server v1.2.3 Fast"
После strip: "Server Fast"
Статус: ✅ ПРИНЯТ с изменённым именем
Задача: удалить из имён маркеры типа [DEMO], (demo), <demo> — регистронезависимо.
- pattern: '(?i)\[demo\]|\(demo\)|<demo>'
action: "strip"
# Объяснение:
# (?i) — регистронезависимый поиск (включён в начало)
# \[demo\] — "[demo]" (скобки экранированы)
# | — ИЛИ
# \(demo\) — "(demo)"
# <demo> — "<demo>"Результат:
"Server [DEMO] US" → "Server US"
"My Proxy (demo)" → "My Proxy"
"Test <demo> Japan" → "Test Japan"
Задача: отклонить всю строку, если в имени есть приватный IP (признак некорректного парсинга).
- pattern: '(?i)(localhost|127\.0\.0\.1|192\.168\.\d+\.\d+|10\.\d+\.\d+\.\d+|172\.(1[6-9]|2[0-9]|3[01])\.\d+\.\d+)'
action: "delete"
# Объяснение:
# localhost — специальное имя
# 127\.0\.0\.1 — localhost IP (точки экранированы)
# 192\.168\.\d+\.\d+ — сеть 192.168.0.0/16
# 10\.\d+\.\d+\.\d+ — сеть 10.0.0.0/8
# 172\.(1[6-9]|2[0-9]|3[01])\.\d+\.\d+ — сеть 172.16.0.0/12Результат:
"Proxy 192.168.1.1" → ❌ ОТКЛОНЕНО
"Server 10.0.0.5" → ❌ ОТКЛОНЕНО
"Good Server US" → ✅ ПРИНЯТО
Задача: отклонить сервер, если его имя содержит маркеры спама, мошенничества или вредоноса.
- pattern: '(?i)\[(spam|fraud|malware|phishing|scam)\]'
action: "delete"
# Объяснение:
# (?i) — регистронезависимый
# \[ — открывающая скобка (экранирована)
# (spam|fraud|malware|phishing|scam) — любое из этих слов
# \] — закрывающая скобкаРезультат:
"Server [SPAM] EU" → ❌ ОТКЛОНЕНО
"Good [fraud] Proxy" → ❌ ОТКЛОНЕНО
"Normal Server" → ✅ ПРИНЯТО
Задача: отклонить сервер, если его имя содержит порт вне диапазона 1-65535.
- pattern: ':(0|6553[6-9]|655[4-9][0-9]|65[6-9][0-9]{2}|6[6-9][0-9]{3}|[7-9][0-9]{4})'
action: "delete"
# Объяснение:
# : — двоеточие (отделяет адрес от порта)
# (0|...) — либо 0, либо числа > 65535Результат:
"Server:99999" → ❌ ОТКЛОНЕНО
"Server:0" → ❌ ОТКЛОНЕНО
"Server:443" → ✅ ПРИНЯТО
-
Используйте граница слова
\bдля целых слов:# ХОРОШО — совпадает "test", но не "testing" pattern: '\btest\b' action: "strip" # ПЛОХО — совпадает и "test", и "testing", и "atesting" pattern: 'test' action: "strip"
-
Экранируйте специальные символы в YAML (удваивайте обратные косые):
# ПРАВИЛЬНО pattern: '\\[TEST\\]' # НЕПРАВИЛЬНО pattern: '\[TEST\]' # YAML съест косые!
-
Используйте
(?i)для регистронезависимого поиска:# ХОРОШО — совпадает "TEST", "test", "Test" pattern: '(?i)\[demo\]' # ПЛОХО — совпадает только "[demo]" pattern: '\[demo\]'
-
Группируйте альтернативы скобками:
# ХОРОШО pattern: '(?i)(spam|fraud|malware)' # ПЛОХО (может быть неоднозначно) pattern: 'spam|fraud|malware'
-
Для delete-правил будьте строги, для strip-правил — осторожны:
# ХОРОШО — удаляет только стандартные версионные строки - pattern: '\bv\d+\.\d+\.\d+\b' action: "strip" # ПЛОХО — может удалить что-то важное - pattern: '\d+' action: "delete"
| Ошибка | Пример | Исправление |
|---|---|---|
| Не экранированы квадратные скобки | pattern: '[TEST]' |
pattern: '\\[TEST\\]' |
Отсутствует (?i) для case-insensitive |
pattern: '\[demo\]' |
pattern: '(?i)\\[demo\\]' |
| Слишком широкий паттерн | pattern: 'a' |
pattern: '(?i)\\[a\\]' (конкретнее) |
| Отсутствует экранирование в YAML | pattern: "\[TEST\]" |
pattern: "\\[TEST\\]" (двойные слэши) |
| Использование граници слова в неправильном месте | pattern: 'test\b' для "testing" |
pattern: '\btest\b' (с обеих сторон) |
Убедитесь, что файл badwords.yaml синтаксически корректен:
# Попробуйте загрузить конфиг (программа покажет ошибки парсинга)
./sub-filter --cli
# Если конфиг загружен без ошибок YAML, выведется:
# "Configuration loaded successfully"Способ 1: Online regex тестер
Посетите regex101.com:
- Выберите "Go" в меню "Flavor"
- Вставьте ваш паттерн в поле "Regular Expression"
- Вставьте тестовые имена в поле "Test String"
- Проверьте совпадения
Пример:
Flavor: Go
Pattern: (?i)\[demo\]|\(demo\)|<demo>
Test strings:
My [DEMO] Server ✅ совпадает
Test (demo) US ✅ совпадает
Server <demo> ✅ совпадает
Normal Server ❌ не совпадает
| Проблема | Причина | Решение |
|---|---|---|
| "Error: invalid pattern" при запуске | Синтаксическая ошибка в regex | Проверьте паттерн на regex101.com с флагом Go |
| Паттерн не совпадает с ожидаемыми строками | Отсутствует (?i) или неправильное экранирование |
Используйте (?i) для case-insensitive; проверьте двойные слэши в YAML |
| Strip удаляет слишком много | Паттерн слишком широкий | Сузьте паттерн (добавьте \b или более конкретные символы) |
| Delete отклоняет хорошие серверы | Паттерн совпадает случайно | Сделайте паттерн более конкретным (например, \[SPAM\] вместо SPAM) |
Рекомендуется упорядочить правила по логике:
-
Strip-правила первыми (очистка мусора)
- Версии
- Тестовые маркеры
- Демо-маркеры
-
Delete-правила вторыми (отклонение критических)
- Спам/вредонос
- Приватные IPs
- Неверные порты
# ХОРОШАЯ ОРГАНИЗАЦИЯ
# === Strip правила (очистка) ===
- pattern: '\bv\d+\.\d+(\.\d+)?\b'
action: "strip"
- pattern: '(?i)\[test(ing|ed|er)?\]'
action: "strip"
# === Delete правила (блокировка) ===
- pattern: '(?i)\[(spam|fraud|malware)\]'
action: "delete"
- pattern: '192\.168\.\d+\.\d+'
action: "delete"Используйте YAML-комментарии для документирования:
# Удаление версионных строк (v1.2.3, v2.0)
- pattern: '\bv\d+\.\d+(\.\d+)?\b'
action: "strip"
# Блокировка серверов, помеченных как спам
- pattern: '(?i)\[spam\]'
action: "delete"Файл badwords.yaml — мощный инструмент для автоматической очистки и фильтрации подписок. Правильная конфигурация позволяет:
- ✅ Сохранить полезные серверы (используя
strip) - ✅ Исключить заспамленные источники (используя
delete) - ✅ Обеспечить чистоту финального списка (автоматическое удаление версий, маркеров, ошибок)
Начните с простых паттернов (точные слова и фразы), затем переходите на более сложные регулярные выражения по мере необходимости.
При возникновении вопросов — используйте regex101.com для визуального тестирования паттернов.