From 9acd54ff2a9cfd99d8a15284c5d45905c7d6fdc0 Mon Sep 17 00:00:00 2001 From: goodvin Date: Sat, 25 Jul 2026 12:54:15 +0300 Subject: [PATCH 01/12] Update domains.txt --- domains.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/domains.txt b/domains.txt index 62990c6..b8ed701 100644 --- a/domains.txt +++ b/domains.txt @@ -193,4 +193,5 @@ netlify.com netlifydns.com netlifyusercontent.com www.ubuntu-touch.io -ubports.com \ No newline at end of file +ubports.com +4pda.to \ No newline at end of file From a3e755c0a497004b8ce96bac6606644688c5a13e Mon Sep 17 00:00:00 2001 From: goodvin Date: Tue, 28 Jul 2026 00:50:44 +0300 Subject: [PATCH 02/12] Update domains.txt --- domains.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/domains.txt b/domains.txt index b8ed701..ab8fa96 100644 --- a/domains.txt +++ b/domains.txt @@ -194,4 +194,5 @@ netlifydns.com netlifyusercontent.com www.ubuntu-touch.io ubports.com -4pda.to \ No newline at end of file +4pda.to +www.patreon.com \ No newline at end of file From 20c484dc59aaf22b04b6caeb96ed95fa5e7f17e2 Mon Sep 17 00:00:00 2001 From: goodvin Date: Fri, 31 Jul 2026 16:54:09 +0300 Subject: [PATCH 03/12] Update domains.txt --- domains.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/domains.txt b/domains.txt index ab8fa96..6412acc 100644 --- a/domains.txt +++ b/domains.txt @@ -195,4 +195,6 @@ netlifyusercontent.com www.ubuntu-touch.io ubports.com 4pda.to -www.patreon.com \ No newline at end of file +www.patreon.com +registry-1.docker.io +docker.io \ No newline at end of file From 0865df3de3eb3d380d1af3978fe18d46779c025d Mon Sep 17 00:00:00 2001 From: goodvin Date: Sat, 1 Aug 2026 14:20:27 +0300 Subject: [PATCH 04/12] Update domains.txt --- domains.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/domains.txt b/domains.txt index 6412acc..6aa6cb2 100644 --- a/domains.txt +++ b/domains.txt @@ -197,4 +197,5 @@ ubports.com 4pda.to www.patreon.com registry-1.docker.io -docker.io \ No newline at end of file +docker.io +downloads.claude.ai \ No newline at end of file From c9c1e8b1eea7d5891e9c416e5d7f1a076b8f9769 Mon Sep 17 00:00:00 2001 From: goodvin Date: Sat, 1 Aug 2026 18:57:11 +0300 Subject: [PATCH 05/12] Update domains.txt --- domains.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/domains.txt b/domains.txt index 6aa6cb2..ff4cff3 100644 --- a/domains.txt +++ b/domains.txt @@ -198,4 +198,5 @@ ubports.com www.patreon.com registry-1.docker.io docker.io -downloads.claude.ai \ No newline at end of file +downloads.claude.ai +claude.com \ No newline at end of file From 38d5bdf0ceb59fbbc986cac098470b736c3e9c8c Mon Sep 17 00:00:00 2001 From: goodvin Date: Sat, 1 Aug 2026 22:31:10 +0300 Subject: [PATCH 06/12] Update domains.txt --- domains.txt | 69 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 68 insertions(+), 1 deletion(-) diff --git a/domains.txt b/domains.txt index ff4cff3..ec08c31 100644 --- a/domains.txt +++ b/domains.txt @@ -199,4 +199,71 @@ www.patreon.com registry-1.docker.io docker.io downloads.claude.ai -claude.com \ No newline at end of file +claude.com +30bf3790.obrut.show +amedia.online +anime1.best +animego.me +animevost.org +api.anilibria.app +api.anilibria.tv +api.apbugall.org +api.bhcesh.me +api.cdnlibs.org +api.filmix.tv +api.g1.plvideo.ru +api.lumex.space +api.luxembd.ws +api.moonanime.art +api.rgshows.me +api.rstprgapipt.com +api.srvkp.com +api.vokino.org +apivb.com +base.ashdi.vip +cdnmovies-stream.online +chaturbate.com +coldcdn.xyz +ee.bongacams.com +embed.su +eneyida.tv +filmixapp.cyou +getstv.com +go.zet-flix.online +hdrezka.me +iframe.video +in.tizam.info +iptv.online +kinobase.org +kinogo.luxury +kinogo.media +kinoukr.com +kinovibe.vip +kodikapi.com +m.hqporner.com +megaoblako.com +moviesapi.club +myfanserial.net +plapi.cdnvideohub.com +player.autoembed.cc +player.smashystream.com +player.videasy.net +portal.lumex.host +redheadsound.studio +rt.pornhub.com +rt.pornhubpremium.com +ru.spankbang.com +ru.xhamster.com +rus.runetki5.com +vibix.org +videoseed.tv +vidfast.pro +vidlink.pro +vidora.su +vidsrc.cc +www.ebalovo.pro +www.eporner.com +www.porntrex.com +www.xnxx.com +www.xvideos.com +www.xvideos.red \ No newline at end of file From 660a31c35e2788f0773916f79ca8e7e9a44b1e7c Mon Sep 17 00:00:00 2001 From: goodvin Date: Wed, 5 Aug 2026 20:58:33 +0300 Subject: [PATCH 07/12] =?UTF-8?q?Add=20warm-nftset.sh=20=E2=80=94=20period?= =?UTF-8?q?ic=20nftset=20warmer?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Elements in bbrkn_v4/bbrkn_v6 carry a 1d timeout and are only refreshed when a query reaches the host dnsmasq on :5350, where the nftset= directives are applied. Idle domains — or ones answered from the pihole FTL cache — age out of the sets and their traffic silently falls back to the plain WAN route instead of the tunnel. warm-nftset.sh re-resolves every domain from the deployed 90-nftset.conf (base + related subdomains) directly against 127.0.0.1:5350, bypassing the FTL cache. Sourcing the domain list from the deployed config means there is no second list to keep in sync. Ping is off by default: packets originating on the gateway itself go through OUTPUT, never prerouting_mangle, so they leave unmarked and almost all time out — a misleading signal, not a real failure. Run on the gateway via `make warm` or hourly cron. Measured: 1059 domains in ~1m45s at PARALLEL=8, v4 526->2203, v6 305->1440 elements. Co-Authored-By: Claude Opus 5 --- Makefile | 9 ++- README.md | 52 ++++++++++++++++- scripts/warm-nftset.sh | 128 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 187 insertions(+), 2 deletions(-) create mode 100755 scripts/warm-nftset.sh diff --git a/Makefile b/Makefile index 8758a4d..3d814f7 100644 --- a/Makefile +++ b/Makefile @@ -18,7 +18,7 @@ CACHE_TTL_DAYS ?= 15 export NFTSET_CONF RESOLVE_CONF CHROME_SERVER DOMAINS_FILE DNS_SERVER NFTSET_TARGET_DIR CACHE_DIR CACHE_TTL_DAYS # --- Основные цели --- -.PHONY: all clean cache-clean check generate deploy +.PHONY: all clean cache-clean check generate deploy warm all: generate deploy @echo "✅ Конфиги успешно сгенерированы и задеплоены" @@ -55,3 +55,10 @@ deploy: @echo "🚀 Деплой конфигов в систему" @chmod +x scripts/deploy-to-gateway.sh @./scripts/deploy-to-gateway.sh + +# Прогрев nft-сетов. Запускать на шлюзе — читает задеплоенный конфиг и +# ходит в host-инстанс dnsmasq на 127.0.0.1:5350. +warm: + @echo "🔥 Прогрев nft-сетов" + @chmod +x scripts/warm-nftset.sh + @./scripts/warm-nftset.sh diff --git a/README.md b/README.md index d63fb2b..2c08766 100644 --- a/README.md +++ b/README.md @@ -82,7 +82,8 @@ bbrkn/ ├── Makefile # управление сборкой и деплоем ├── scripts/ │ ├── generate-configs.sh # генерация dnsmasq-конфигов -│ └── deploy-to-gateway.sh # деплой в Pi-hole + rollback +│ ├── deploy-to-gateway.sh # деплой в Pi-hole + rollback +│ └── warm-nftset.sh # прогрев nft-сетов по cron (на шлюзе) └── .forgejo/workflows/deploy.yaml # CI/CD на self-hosted runner ``` @@ -97,6 +98,7 @@ make deploy # только задеплоить в Pi-hole make clean # удалить сгенерированные конфиги из /tmp make cache-clean # очистить кэш API-ответов (.cache/api/) make check # проверить синтаксис domains.txt +make warm # прогреть nft-сеты (запускать на шлюзе) ``` --- @@ -173,6 +175,54 @@ CACHE_TTL_DAYS=0 make generate --- +## Прогрев nft-сетов (`warm-nftset.sh`) + +Элементы сетов `bbrkn_v4`/`bbrkn_v6` живут по `timeout` (сейчас `1d`) и обновляются **только** когда запрос доходит до host-инстанса `:5350` — именно там применяются директивы `nftset=`. Если домен долго никто не открывал (или ответ отдал кэш pihole FTL), элемент истекает, и трафик к этому домену уходит мимо туннеля напрямую в WAN. + +`scripts/warm-nftset.sh` закрывает эту дыру: заново резолвит **все** домены из задеплоенного `90-nftset.conf` (база + связанные субдомены) **напрямую** через `dig @127.0.0.1 -p 5350`, минуя кэш FTL, — каждый запрос гарантированно доходит до тегирующего инстанса. + +> **Запускать только на шлюзе.** Инстанс `:5350` слушает `listen-address=127.0.0.1` и с других хостов LAN недоступен. Список доменов берётся из задеплоенного конфига, так что скрипт всегда работает с актуальным после последнего деплоя списком. + +```bash +# разово, вручную +make warm +./scripts/warm-nftset.sh + +# ежечасно по cron (пользователь на шлюзе, sudo без пароля для nft) +crontab -e +17 * * * * /path/to/bbrkn/scripts/warm-nftset.sh >/dev/null 2>&1 +``` + +### Переменные окружения + +| Переменная | По умолчанию | Описание | +|---|---|---| +| `NFTSET_CONF` | `/etc/dnsmasq.d/90-nftset.conf` | Задеплоенный конфиг — источник списка доменов | +| `RESOLVER` / `RESOLVER_PORT` | `127.0.0.1` / `5350` | Host-инстанс dnsmasq, применяющий `nftset=` | +| `PARALLEL` | `8` | Одновременных запросов к `:5350` | +| `DIG_TIMEOUT` / `DIG_TRIES` | `3` / `2` | Таймаут и число попыток на домен | +| `WARM_PING` | `0` | `1` — дополнительно пинговать первый A-адрес (только для отладки) | +| `STATE_DIR` | `~/.local/state/bbrkn` | Лог `warm.log` и lock-файл | +| `LOG_MAX_BYTES` | `4194304` | Порог ротации лога в `warm.log.1` | + +Параллельные запуски блокируются через `flock` — медленный прогон не наложится на следующий по cron. + +### Лог + +``` +2026-08-05T20:46:57+03:00 START domains=1059 conf=/etc/dnsmasq.d/90-nftset.conf v4=526 v6=305 +2026-08-05T20:48:44+03:00 DONE ok=1036 noping=0 dnsfail=23 v4=526->2203 v6=305->1440 +2026-08-05T20:48:44+03:00 dnsfail: azureedge.net cdn-telegram.org kinozal.tv ... +``` + +`v4=X->Y` — число элементов в сете до и после прогона (считается через `sudo -n nft list set`; без прав sudo вместо числа будет `?`, на сам прогрев это не влияет). Элементов больше, чем доменов — у CDN на один домен приходится несколько адресов. Домены в `dnsfail` не резолвятся вообще (мёртвые записи, NXDOMAIN) — кандидаты на удаление из `domains.txt`. + +> `WARM_PING=1` на шлюзе почти всегда даёт `noping`: пакеты, рождённые на самом шлюзе, идут через `OUTPUT` и не проходят цепочку `prerouting_mangle`, то есть уходят в WAN без метки. Это диагностический режим, не показатель проблемы. + +Полный прогон 1059 доменов при `PARALLEL=8` занимает ~1 мин 45 с. + +--- + ## Запуск вручную ```bash diff --git a/scripts/warm-nftset.sh b/scripts/warm-nftset.sh new file mode 100755 index 0000000..52295c6 --- /dev/null +++ b/scripts/warm-nftset.sh @@ -0,0 +1,128 @@ +#!/bin/bash +set -uo pipefail + +# ============================== +# Прогрев nft-сетов (запускать НА ШЛЮЗЕ) +# ============================== +# Заново резолвит все домены, которые dnsmasq помечает директивами nftset=, +# обращаясь напрямую к host-инстансу 127.0.0.1#5350. Прямой запрос обходит +# кэш pihole FTL: запрос, попавший в кэш FTL, до :5350 не доходит и элементы +# в inet filter bbrkn_v4/bbrkn_v6 не обновляет — они молча истекают по timeout +# и домен уходит мимо туннеля. +# +# Источник списка доменов — сам задеплоенный конфиг, поэтому отдельный список +# синхронизировать не нужно: скрипт всегда работает с тем, что реально +# загружен в dnsmasq после последнего успешного деплоя. + +# --- Конфигурация через переменные окружения --- +# Задеплоенный конфиг с директивами nftset= (источник списка доменов) +NFTSET_CONF="${NFTSET_CONF:-/etc/dnsmasq.d/90-nftset.conf}" +# Host-инстанс dnsmasq, который применяет nftset= +RESOLVER="${RESOLVER:-127.0.0.1}" +RESOLVER_PORT="${RESOLVER_PORT:-5350}" + +# Состояние и лог +STATE_DIR="${STATE_DIR:-${HOME}/.local/state/bbrkn}" +LOG="${LOG:-${STATE_DIR}/warm.log}" +LOCK="${LOCK:-${STATE_DIR}/warm.lock}" +LOG_MAX_BYTES="${LOG_MAX_BYTES:-4194304}" # ротация лога, 4 МиБ + +# Параметры опроса +PARALLEL="${PARALLEL:-8}" # одновременных запросов к :5350 +DIG_TIMEOUT="${DIG_TIMEOUT:-3}" # секунд на попытку +DIG_TRIES="${DIG_TRIES:-2}" + +# Пинг выключен по умолчанию: пакеты, рождённые на самом шлюзе, идут через +# OUTPUT и не проходят цепочку prerouting_mangle — уходят в обычный WAN без +# метки и почти все отваливаются по таймауту. Включать только для отладки. +WARM_PING="${WARM_PING:-0}" +PING_TIMEOUT="${PING_TIMEOUT:-2}" + +NFT="${NFT:-/usr/sbin/nft}" + +mkdir -p "$STATE_DIR" + +# Один инстанс: медленный прогон не должен наложиться на следующий по cron. +exec 9>"$LOCK" +if ! flock -n 9; then + echo "$(date -Is) SKIP предыдущий запуск ещё выполняется" >>"$LOG" + exit 0 +fi + +log() { echo "$(date -Is) $*" >>"$LOG"; } + +# Количество элементов в сете. У каждого элемента есть timeout, поэтому +# "expires" встречается ровно один раз на элемент. Ошибка здесь не фатальна — +# это только метрика прогресса. +set_count() { + sudo -n "$NFT" list set inet filter "$1" 2>/dev/null | grep -c 'expires' || echo "?" +} + +if [ ! -r "$NFTSET_CONF" ]; then + log "FATAL не читается $NFTSET_CONF" + echo "Ошибка: не читается $NFTSET_CONF (скрипт запускается на шлюзе)" >&2 + exit 1 +fi + +mapfile -t HOSTS < <(sed -n 's|^nftset=/\([^/]*\)/.*|\1|p' "$NFTSET_CONF" | sort -u) +if [ "${#HOSTS[@]}" -eq 0 ]; then + log "FATAL в $NFTSET_CONF не найдено ни одной директивы nftset=" + echo "Ошибка: в $NFTSET_CONF не найдено ни одной директивы nftset=" >&2 + exit 1 +fi + +BEFORE_V4=$(set_count bbrkn_v4) +BEFORE_V6=$(set_count bbrkn_v6) +log "START domains=${#HOSTS[@]} conf=$NFTSET_CONF v4=$BEFORE_V4 v6=$BEFORE_V6" + +warm_one() { + local host="$1" a aaaa + a=$(dig +short +timeout="$DIG_TIMEOUT" +tries="$DIG_TRIES" \ + @"$RESOLVER" -p "$RESOLVER_PORT" A "$host" 2>/dev/null \ + | grep -E '^[0-9]+\.' | head -1) + aaaa=$(dig +short +timeout="$DIG_TIMEOUT" +tries="$DIG_TRIES" \ + @"$RESOLVER" -p "$RESOLVER_PORT" AAAA "$host" 2>/dev/null \ + | grep -E '^[0-9a-fA-F]*:' | head -1) + + if [ -z "$a" ] && [ -z "$aaaa" ]; then + echo "dnsfail $host" + return + fi + + # Пинг только подтверждает проходимость маршрута; в сет IP попал уже на + # шаге резолва выше. + if [ "$WARM_PING" = "1" ] && [ -n "$a" ]; then + if ping -n -q -c1 -W "$PING_TIMEOUT" "$a" >/dev/null 2>&1; then + echo "ok $host $a" + else + echo "noping $host $a" + fi + else + echo "ok $host ${a:-$aaaa}" + fi +} +export -f warm_one +export RESOLVER RESOLVER_PORT DIG_TIMEOUT DIG_TRIES WARM_PING PING_TIMEOUT + +RESULTS="$(printf '%s\n' "${HOSTS[@]}" \ + | xargs -r -P "$PARALLEL" -I{} bash -c 'warm_one "$@"' _ {})" + +OK=$(grep -c '^ok ' <<<"$RESULTS" || true) +NOPING=$(grep -c '^noping ' <<<"$RESULTS" || true) +DNSFAIL=$(grep -c '^dnsfail ' <<<"$RESULTS" || true) + +AFTER_V4=$(set_count bbrkn_v4) +AFTER_V6=$(set_count bbrkn_v6) +log "DONE ok=$OK noping=$NOPING dnsfail=$DNSFAIL v4=${BEFORE_V4}->${AFTER_V4} v6=${BEFORE_V6}->${AFTER_V6}" +if [ "$DNSFAIL" -gt 0 ]; then + log "dnsfail: $(grep '^dnsfail ' <<<"$RESULTS" | cut -d' ' -f2 | tr '\n' ' ')" +fi + +echo "✔ Прогрето доменов: $OK, не резолвится: $DNSFAIL; bbrkn_v4 ${BEFORE_V4}->${AFTER_V4}, bbrkn_v6 ${BEFORE_V6}->${AFTER_V6}" + +# Ротация лога +if [ -f "$LOG" ] && [ "$(stat -c%s "$LOG")" -gt "$LOG_MAX_BYTES" ]; then + mv -f "$LOG" "${LOG}.1" +fi + +exit 0 From 0ac0aa0cc4b78801b064649351a51c07e43ef200 Mon Sep 17 00:00:00 2001 From: goodvin Date: Sat, 8 Aug 2026 12:24:13 +0300 Subject: [PATCH 08/12] Update domains.txt --- domains.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/domains.txt b/domains.txt index ec08c31..f6f2f5c 100644 --- a/domains.txt +++ b/domains.txt @@ -266,4 +266,5 @@ www.eporner.com www.porntrex.com www.xnxx.com www.xvideos.com -www.xvideos.red \ No newline at end of file +www.xvideos.red +gemini.google.com \ No newline at end of file From 5643ba5615bc1e5be0ac372e09ca0fc70feb9e2a Mon Sep 17 00:00:00 2001 From: goodvin Date: Sat, 8 Aug 2026 15:24:08 +0300 Subject: [PATCH 09/12] Update domains.txt --- domains.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/domains.txt b/domains.txt index f6f2f5c..38efac8 100644 --- a/domains.txt +++ b/domains.txt @@ -267,4 +267,5 @@ www.porntrex.com www.xnxx.com www.xvideos.com www.xvideos.red -gemini.google.com \ No newline at end of file +gemini.google.com +nakarte.me \ No newline at end of file From 47f91b519179caca46ffb4e42f0171f41bc76ff4 Mon Sep 17 00:00:00 2001 From: goodvin Date: Sun, 16 Aug 2026 20:49:35 +0300 Subject: [PATCH 10/12] Update domains.txt --- domains.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/domains.txt b/domains.txt index 38efac8..d5d07dc 100644 --- a/domains.txt +++ b/domains.txt @@ -268,4 +268,5 @@ www.xnxx.com www.xvideos.com www.xvideos.red gemini.google.com -nakarte.me \ No newline at end of file +nakarte.me +a-api.anthropic.com \ No newline at end of file From 19fbb5c1a25509ee5fcf4191fa6d469049cc0417 Mon Sep 17 00:00:00 2001 From: goodvin Date: Mon, 17 Aug 2026 07:39:55 +0300 Subject: [PATCH 11/12] ADD Google Video domains --- domains.txt | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/domains.txt b/domains.txt index d5d07dc..5734b1b 100644 --- a/domains.txt +++ b/domains.txt @@ -269,4 +269,19 @@ www.xvideos.com www.xvideos.red gemini.google.com nakarte.me -a-api.anthropic.com \ No newline at end of file +a-api.anthropic.com +youtube.com +youtu.be +youtube-nocookie.com +ytimg.com +ggpht.com +googlevideo.com +gvt1.com +gvt2.com +gvt3.com +googleusercontent.com +gstatic.com +jnn-pa.googleapis.com +play.googleapis.com +youtubei.googleapis.com +googleapis.com \ No newline at end of file From ae8295546bacbdf9a38b7ebc09ea388c28bb3265 Mon Sep 17 00:00:00 2001 From: goodvin Date: Fri, 28 Aug 2026 20:59:23 +0300 Subject: [PATCH 12/12] Update domains.txt --- domains.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/domains.txt b/domains.txt index 5734b1b..f2ddaa5 100644 --- a/domains.txt +++ b/domains.txt @@ -284,4 +284,7 @@ gstatic.com jnn-pa.googleapis.com play.googleapis.com youtubei.googleapis.com -googleapis.com \ No newline at end of file +googleapis.com +api.bambulab.com +bambulab.com +e.bambulab.com \ No newline at end of file