No description
Find a file
goodvin d91dbf066b
All checks were successful
Deploy DNS Configuration / deploy (push) Successful in 7m43s
ADD DOMAIN: notebooklm.google
2026-03-22 07:25:35 +03:00
.forgejo/workflows Рефакторинг 2026-03-21 09:46:15 +03:00
scripts unbound variable 2026-03-21 22:12:58 +03:00
.gitignore Рефакторинг 2026-03-21 09:46:15 +03:00
domains.txt ADD DOMAIN: notebooklm.google 2026-03-22 07:25:35 +03:00
LICENSE Initial commit 2025-09-09 16:35:42 +03:00
Makefile Рефакторинг 2026-03-21 09:46:15 +03:00
README.md Рефакторинг 2026-03-21 09:46:15 +03:00

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 выполняет следующие шаги:

  1. Проверяет наличие сгенерированных конфигов.
  2. Создаёт timestamped-бэкапы текущих конфигов в TARGET_DIR.
  3. Копирует новые конфиги в TARGET_DIR.
  4. Перезапускает контейнер Pi-hole.
  5. Ждёт запуска (до 30 секунд, polling через docker inspect).
  6. Выполняет DNS health check через dig / nslookup.
  7. При ошибке на шагах 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