|
All checks were successful
Deploy DNS Configuration / deploy (push) Successful in 16m0s
|
||
|---|---|---|
| .forgejo/workflows | ||
| scripts | ||
| .gitignore | ||
| domains.txt | ||
| LICENSE | ||
| Makefile | ||
| README.md | ||
bbrkn — DNS Bypass Config Generator
Автоматизирует генерацию конфигураций Pi-hole / dnsmasq для маршрутизации трафика заблокированных доменов через VPN-туннель (WireGuard).
Как это работает
flowchart TD
A[domains.txt] --> B[generate-configs.sh]
B -->|кэш .cache/api| B
B -->|MISS / EXPIRED| C[Chromium headless API]
C --> B
B --> D[91-ipset-bbrkn.conf]
B --> E[92-resolve-bbrkn.conf]
D --> F[deploy-to-gateway.sh]
E --> F
F -->|backup + copy| G[Pi-hole dnsmasq.d/]
F -->|docker restart| H[Pi-hole container]
F -->|DNS health check| H
H -->|rollback если упал| G
subgraph "Трафик клиента"
K[Клиент] -->|DNS запрос| H
H -->|домен в ipset → mark| I[iptables]
I --> J[WireGuard VPN]
J --> L[Интернет]
end
Классификация доменов
Для каждого домена из domains.txt скрипт обращается к Chromium headless API и классифицирует результат:
| Результат API | Действие |
|---|---|
JSON с relatedDomains |
Сайт — добавляется домен + все связанные субдомены |
JSON с error: ERR_NAME_NOT_RESOLVED или Timeout |
Мёртвый домен — пропускается, в конфиг не попадает |
JSON с любой другой ошибкой (ERR_CERT_*, ERR_CONNECTION_REFUSED и т.д.) |
Сервис — добавляется только сам домен без субдоменов (не HTTP-сервис: SMTP, VPN, игровой сервер и т.п.) |
| API недоступен (не 200 / не JSON после всех попыток) | Fallback — домен всё равно добавляется без субдоменов; фиксируется в разделе отчёта API FAILURES |
Любой домен из
domains.txtгарантированно попадает в финальный конфиг, даже если API недоступен.
Формат выходных файлов
Домены группируются по базовому домену с комментарием:
# example.com — 4 subdomains
ipset=/example.com/bbrkn
ipset=/static.example.com/bbrkn
ipset=/api.example.com/bbrkn
...
# some-service.com — 0 subdomains
ipset=/some-service.com/bbrkn
Структура проекта
bbrkn/
├── domains.txt # список доменов для обхода
├── Makefile # управление сборкой и деплоем
├── scripts/
│ ├── generate-configs.sh # генерация dnsmasq-конфигов
│ └── deploy-to-gateway.sh # деплой в Pi-hole + rollback
└── .forgejo/workflows/deploy.yaml # CI/CD на self-hosted runner
Makefile
make all # generate + deploy (полный цикл)
make generate # только сгенерировать конфиги
make deploy # только задеплоить в Pi-hole
make clean # удалить сгенерированные конфиги из /tmp
make cache-clean # очистить кэш API-ответов (.cache/api/)
make check # проверить синтаксис domains.txt
Переменные окружения
generate-configs.sh
| Переменная | По умолчанию | Описание |
|---|---|---|
DOMAINS_FILE |
domains.txt |
Входной файл со списком доменов |
IPSET_CONF |
/tmp/91-ipset-bbrkn.conf |
Выходной файл правил ipset |
RESOLVE_CONF |
/tmp/92-resolve-bbrkn.conf |
Выходной файл правил server= |
CHROME_SERVER |
http://127.0.0.1:3000 |
Адрес Chromium headless API |
DNS_SERVER |
8.8.8.8 |
DNS-сервер для резолвинга через VPN |
IGNORE_PARTS |
(пусто) | Подстроки через пробел — домены с совпадением игнорируются |
CACHE_DIR |
.cache/api |
Директория кэша API-ответов |
CACHE_TTL_DAYS |
15 |
Время жизни кэша в днях; 0 — отключить кэш |
STRICT_MODE |
0 |
1 — завершать с кодом 1 при любых ошибках API |
DEBUG |
0 |
1 — включить подробный лог |
DEBUG_LOG |
/tmp/generate-configs.debug.log |
Путь к файлу отладочного лога |
deploy-to-gateway.sh
| Переменная | По умолчанию | Описание |
|---|---|---|
TARGET_DIR |
/opt/appdata/pihole/etc/dnsmasq.d |
Директория dnsmasq в Pi-hole |
IPSET_CONF |
/tmp/91-ipset-bbrkn.conf |
Сгенерированный файл ipset |
RESOLVE_CONF |
/tmp/92-resolve-bbrkn.conf |
Сгенерированный файл server= |
DOCKER_CONTAINER |
pihole |
Имя Docker-контейнера Pi-hole |
DNS_LISTEN_ADDR |
127.0.0.1 |
Адрес, на котором Pi-hole слушает DNS |
DNS_CHECK_DOMAIN |
google.com |
Домен для DNS health check после рестарта |
Кэш API-ответов
При каждом запуске ответы Chromium API сохраняются в $CACHE_DIR/<domain>.json. При повторном запуске:
- Если файл кэша свежее
CACHE_TTL_DAYSдней → ответ берётся из кэша, Chromium не запускается. - Если файл старше TTL → перезапрашивается и кэш обновляется.
- Если кэш повреждён (невалидный JSON) → перезапрашивается автоматически.
На self-hosted runner workspace сохраняется между запусками, поэтому повторные CI-запуски значительно быстрее.
# Сбросить кэш и запросить всё заново
make cache-clean && make generate
# Отключить кэш для одного запуска
CACHE_TTL_DAYS=0 make generate
Деплой и автооткат
deploy-to-gateway.sh выполняет следующие шаги:
- Проверяет наличие сгенерированных конфигов.
- Создаёт timestamped-бэкапы текущих конфигов в
TARGET_DIR. - Копирует новые конфиги в
TARGET_DIR. - Перезапускает контейнер Pi-hole.
- Ждёт запуска (до 30 секунд, polling через
docker inspect). - Выполняет DNS health check через
dig/nslookup. - При ошибке на шагах 5 или 6 — автоматически откатывается: восстанавливает бэкапы и перезапускает контейнер со старой конфигурацией.
Запуск вручную
# Полный цикл
make all
# Только генерация (без деплоя)
make generate
# Dry-run — проверить что будет сгенерировано, ничего не записывать
./scripts/generate-configs.sh --dry-run
# Отладочный режим
DEBUG=1 make generate
# Строгий режим — завершить с ошибкой если часть доменов не опросилась
STRICT_MODE=1 make generate
CI/CD
Workflow запускается при push в main, а также вручную из UI (workflow_dispatch).
push → main
└─ make clean
└─ make all
├─ generate-configs.sh (генерация с кэшем)
└─ deploy-to-gateway.sh (деплой + rollback)
└─ upload artifacts (конфиги + debug-лог, даже при падении)
Self-hosted runner работает непосредственно на шлюзе, поэтому деплой происходит локально без SSH.
Пример отчёта
===== DEBUG REPORT =====
Input file: domains.txt
Raw input lines: 170
Processed lines: 170
Normalized OK: 165
Normalized skipped: 5
Ignored (IGNORE_PARTS): 12
Cache hits: 148 (TTL: 15d, dir: .cache/api)
Cache expired/refetched: 3
API success (sites): 11
API error/failed: 3
Related domains added: 87
Final unique domains: 256
---- VALID BASE SITES ----
example.com
another-site.org
...
---- API FAILURES (added without subdomains) ----
some-domain.com → api_failed_added_without_subdomains
...
===== END DEBUG REPORT =====
Зависимости
| Инструмент | Где используется |
|---|---|
bash 4.2+ |
оба скрипта |
curl |
запросы к Chromium API |
jq |
парсинг JSON-ответов |
docker |
перезапуск Pi-hole |
ipset |
сброс маршрутов после деплоя |
dig или nslookup |
DNS health check (опционально) |
Лицензия
MIT