Цифровой дворник

Практические заметки о сетях, self-hosting, виртуализации, мониторинге, автоматизации и локальном ИИ.

Telegram: @digclean

Обложка

Домашний MikroTik hAP ac lite — MIPS 650 МГц, 64 МБ памяти — начал задыхаться: CPU 99–100%, свободной оперативки 17 МБ. Классический совет в такой ситуации — «купи нормальный роутер». Но прежде чем тратить деньги, я решил разобраться, что он вообще делает.

Сначала проверил сам

Прогнал конфиг: SNMP открыт наружу, RDP проброшен в интернет, слабый Wi-Fi-пароль, скрипт, тянущий код с GitHub. Почистил всё это — CPU стоит колом. Значит, проблема глубже, и одним взглядом её не увидеть.

Подключил второй мозг

Отдал те же конфиги субагенту — отдельной сессии ИИ. И он нашёл то, что я проморгал: 12 мёртвых маршрутов с gateway 10.100.0.2 — это собственный адрес роутера в L2TP-туннеле. Роутер гнал трафик «в самого себя», маршруты висели в статусе INACTIVE, а рабочие копии тех же сетей шли через туннель до зарубежного VPS (10.100.10.10).

Одна команда:

/ip route remove [find gateway=10.100.0.2]

Минус 12 маршрутов — трафик пошёл по живому пути. Минута работы. Вывод: два мозга видят разное, и на серьёзных вещах второй проход не помешает.

Ролевой аудит: три субагента, три модели

Один субагент помог — я усилил подход. Три роли, три разные модели, одни и те же свежие конфиги:

  • сетевой инженер — DeepSeek Flash;
  • безопасник — GPT-4o mini;
  • админ — DeepSeek Pro.

Каждый искал своё. Вот что набралось:

  • DHCP-клиент по умолчанию висит на WAN рядом с PPPoE. Если провайдер выдаст адрес, дефолт-маршрут с distance 1 перебьёт PPPoE (distance 2) и сломает NAT. Мина замедленного действия.
  • Мёртвый маршрут до лабораторной сети через шлюз, которого нет ни в одной connected-сети.
  • ~110 маршрутов-дублей от старых дампов — дедупликация похудела таблицу на 25–30%.
  • Мусор через VPN: multicast, RFC1918, широкие /8 и /12 через туннель с MTU 1400.
  • BFD включён на всех интерфейсах при полном отсутствии BGP/OSPF — hello-пакеты впустую жгут CPU.
  • YouTube address-list на 496 записей, обновляется каждые 12 часов и не используется ни одним правилом.
  • DHCP lease-time 10 минут — клиенты перерегистрируются каждые 5 минут, лишний broadcast на слабом MIPS.
  • Проброс RDP целится в динамический DHCP-лиз — адрес сменится, и проброс молча уедет на чужой хост.
  • Скрипт обновления списка с правами reboot/password — многовато для «обновить список».
  • Авто-SMB на роутере — лишний вектор в LAN.

Итого +10 находок. Три проверил живьём — всё подтвердилось.

Экзамен: 21 модель против одного конфига

Захотелось честной проверки: всем моделям — один и тот же конфиг (14,5 КБ) и один промпт: опиши, найди до 5 проблем, скажи, что пинговать. Потом сверка с реальными пингами.

Кто блеснул:

  • GPT-5 — единственный, кто с нуля нашёл DHCP-клиент на WAN (главную находку прошлого аудита);
  • qwen3-coder — указал на мёртвый маршрут и предложил пинговать именно его;
  • gemma3 — лучшая локальная: 4,2K токенов разбора бесплатно;
  • qwen2.5:14b — заметил check-gateway=none на куче маршрутов: роутер не проверяет шлюзы, поэтому мёртвые висят вечно.

Кто облажался:

  • три thinking-модели (qwen3:30b, qwen3-vl:8b, deepseek-r1:14b) вернули пустой ответ — весь лимит ушёл в скрытые размышления. С max_tokens=16000 все трое заговорили;
  • deepseek-coder:6.7b выдумал RIPv2, которого в конфиге нет, и выдал учебник;
  • qwen2.5:7b придумал проблему с ether3/ether4 — а они в bridge;
  • llama3.1:8b упал с ошибкой 500, не переварив конфиг.

Пинговая сверка подтвердила подозрения: интернет, дом, офис и LAN отвечают, а туннельные адреса 10.100.0.2 и 10.100.50.2 дают 100% потерь.

Весь эксперимент обошёлся в $0.23 (148K токенов промпта + 70K вывода). Локальные модели сожгли 91K дневной квоты, но денег — ноль.

Чистка

Собрал всё и прошёлся метлой: BGP/OSPF — off (мёртвые, но жрали CPU), BFD — off, мёртвые и дублирующиеся маршруты удалены, OpenVPN-сервер снят, YouTube-лист вычищен вместе со скриптом.

CPU упал с 99% до 15%. Память вдохнула. Роутер на 64 МБ ожил и замены не просит.

Выводы

Прежде чем покупать железо — почистите конфиг. Часто роутер не слабый, а просто завален мусором, копившимся годами: VPN-хабы, старые дампы, скрипты «на всякий случай».

И второе. Я один пропустил мёртвые маршруты — субагент нашёл. Три роли дали ещё +10 находок. 21 модель подтвердила главное и подсветила закономерности. Ни один ИИ не увидел всего, но вместе с живой проверкой они закрыли почти все реальные проблемы. Теперь это мой стандарт: роли × модели × живая проверка.

#network

Обложка

Что внутри

Архитектура четырёхуровневая:

  • L0 — разговоры: сырые диалоги, как есть;
  • L1 — атомы: отдельные факты, вытащенные из разговоров;
  • L2 — сцены: связанные блоки по темам и задачам;
  • L3 — персона: профиль пользователя с привычками и предпочтениями.

При этом ничего не сжимается безвозвратно: от верхнего уровня всегда можно спуститься вниз до исходного текста. Верхние слои хранятся читаемыми Markdown-файлами, нижние — в базе для полнотекстового поиска.

Установка

Плагин ставится одной командой:

openclaw plugins install @tencentdb-agent-memory/memory-tencentdb
openclaw gateway restart

После этого в конфиге нужно включить сам плагин:

{
  "plugins": {
    "entries": {
      "memory-tencentdb": {
        "enabled": true,
        "hooks": {
          "allowConversationAccess": true
        }
      }
    }
  }
}

По умолчанию всё хранится в локальном SQLite + sqlite-vec — ничего дополнительно поднимать не надо.

Embedding: bge-m3 вместо облака

По умолчанию плагин ищет по ключевым словам. Для семантического поиска нужна embedding-модель — она превращает текст в векторы, по которым ищется смысл, а не точное совпадение.

Ставить облачную (OpenAI text-embedding) не хотелось — это зависимость и копейки за каждый запрос. Взяли локальную bge-m3, которая уже жила в нашем ollama. О том, что это за модель, почему она и чем лучше nomic-embed-text, — отдельный пост про bge-m3; здесь она просто работает как движок памяти.

Настройка embedding в конфиге плагина:

{
  "memory-tencentdb": {
    "config": {
      "recall": { "strategy": "hybrid" },
      "embedding": {
        "enabled": true,
        "provider": "openai",
        "baseUrl": "http://198.51.100.17:11434/v1",
        "apiKey": "ollama",
        "model": "bge-m3",
        "dimensions": 1024,
        "sendDimensions": false
      }
    }
  }
}

Пара важных деталей:

  • bge-m3 не принимает параметр dimensions — это фиксированная модель. Поэтому sendDimensions: false, иначе ollama вернёт 400 «does not support matryoshka representation»;
  • strategy: hybrid — это RRF-слияние двух поисков: полнотекстового (FTS) и векторного. Один ищет точные слова, второй — смысл, и результаты объединяются.

Грабли по пути

Первая: ollama в контейнере оказался остановлен. Порт молчит, плагин падает с ошибкой «EmbeddingService is not available». Лечится просто — запустить сервис, но без этого вся схема выглядит сломанной.

Вторая: контейнер с ollama сидит во внутренней сети, а агент — во внешней. Между ними шлюз-прокси. Без маршрута агент до embedding-модели не дотягивается. Маршрут прописывается через конфиг сетевого демона, чтобы пережить перезагрузку:

[Route]
Destination = 198.51.100.0/24
Gateway = 192.0.2.114

Третья: плагин при первом запуске с embedding нашёл старые данные без векторных меток и сам сбросил векторные таблицы — чтобы не подмешивать битые векторы. Это нормальное поведение, просто первые воспоминания переиндексируются заново.

Бенчмарки: до и после

Замерял не лабораторно, а на живой сессии — так честнее.

До

  • Память: только файлы-напоминалки и дневники (~85 КБ), поиск по ним — отдельным инструментом;
  • Контекст сессии за 1.5 часа работы: 247 тысяч токенов, занято 25% окна;
  • Стоимость: $0.06 за сессию;
  • Каждый разговор про лабу приходилось начинать с пересказа контекста.

После

  • Память: плагин сам захватывает разговоры (L0), вытаскивает факты (L1), строит сцены (L2) и профиль (L3);
  • База: SQLite + векторы bge-m3, ~/.openclaw/memory-tdai/;
  • Первый recall после установки: 334 мс на поиск — FTS 78 мс, векторный поиск 258 мс;
  • В контекст подмешивается ~500–700 символов релевантных воспоминаний перед каждым ходом;
  • Уже через несколько минут работы: 7 разговоров и 2 факта в базе.

Реальную экономию токенов на длинных сессиях замерим через несколько дней — на одном и том же наборе вопросов про лабу. Тогда же видно будет, насколько меньше приходится пересказывать контекст с нуля.

Итог

TencentDB Agent Memory — не магическая таблетка, а рабочий инструмент: сам пишет, сам ищет, сам подмешивает. Локально, без облака, с читаемыми файлами вместо чёрного ящика. Главное — не забыть, что embedding-модель должна быть живой и доступной по сети, иначе вся «память» молча превращается в дорогой поиск по ключевым словам.

Бонус: bge-m3, которую мы когда-то поставили «на всякий случай», наконец-то нашла своё место. Ничего в этой лабе не пропадает — просто ждёт своего часа.

Ссылки

— TencentDB Agent Memory

— BGE-M3: embedding-модель

— Ollama

— SQLite

#openclaw #selfhosting

Обложка

Давно хотел видеть всю инфраструктуру одним взглядом: две площадки, роутеры в разных концах города, туннели между ними, контейнеры на двух внутренних сетях, кто за каким NAT сидит и кто сейчас лежит. Не «список устройств в Wi-Fi», а именно схему — чтобы по ней сразу читалось, что через что ходит.

Рассказываю, как выбирал инструмент, что в итоге поставил и как оживил карту статусами туннелей.

Муки выбора

Сначала казалось, что задача простая — «нарисовать сеть», а инструментов вон сколько. Перебрал пять кандидатов, и у всех нашлось одно общее ограничение: это discovery-инструменты. Они сканируют один сегмент (обычно LAN) и рисуют «что болтается в broadcast domain». А моя топология — инфраструктурная: связи между площадками, туннели поверх интернета, контейнеры за NAT. Сканер за свой broadcast domain не заглянет в принципе.

NetAlertX (~7k звёзд). Один контейнер, лёгкий, красивые карточки устройств, online/offline, порты. Но карта древовидная: родитель → дети. Туннели рисует неидеально, VLAN — подписью на ребре. Вердикт: отличный «кто висит в домашней сети», но схема лабы — нет.

NetPulse (1 звезда, 8 коммитов). PHP + SQLite, ICMP/TCP/SNMP, ручное рисование связей, пунктиры, цвета. По духу — то, что надо, но проект сырой, наружу такое не выставишь. Вердикт: «рисовалка с пингами», которую за вечер напишешь сам.

Scanopy (~5.7k звёзд). L2/L3, VLAN, порты, контейнеры, живая карта. Но три контейнера + PostgreSQL + привилегированный сканер. Для домашней лабы тяжело и привилегированно, и снова L2-центричен — межсайтовые туннели не покажет.

MikroTik-NetMap (0 звёзд, но живой). Веб-альтернатива The Dude: сам находит соседей роутеров по MNDP/LLDP, dotted-линии для VPN, анимация трафика. Но рисует только то, что роутеры видят в L2. Мои контейнеры и туннели между площадками автоматически не покажет.

Homelable (3179⭐, MIT, обновляется чуть ли не ежедневно). – Импорт Proxmox VE — сам вытаскивает контейнеры и VM – Свободный канвас: зоны-сети, вложенность (хост → контейнеры внутри), ручные линки любого типа – Живые статусы нод: ping/TCP/HTTP – Экспорт PNG/SVG, read-only Live View, MCP-сервер для ИИ-ассистентов – Docker-образ или bare-metal скрипт — влезает в обычный LXC

Вердикт: единственный, кто закрывает именно мою задачу — произвольная схема + живые статусы + импорт уже существующей инфраструктуры.

Почему Homelable

  1. Моя топология — граф: 2 площадки, полтора десятка контейнеров, 2 внутренних сети, 3 типа туннелей между роутерами. Нужен свободный канвас с ручными связями, а не авто-дерево.
  2. Импорт Proxmox даёт 80% наполнения бесплатно — не надо вбивать контейнеры руками.
  3. Живые статусы — схема одновременно работает мониторингом.
  4. Лёгкий: frontend + backend, живёт в LXC рядом с остальными сервисами.
  5. Экспорт PNG — картинку можно вставить в статью.

Точный путь установки

Шаг 1. Контейнер

Свежий LXC на Proxmox (ubuntu, unprivileged, nesting=1 — docker внутри требует):

pct create 116 local:vztmpl/ubuntu-26.04-standard_26.04-1_amd64.tar.zst \
  --hostname homelable --memory 2048 --cores 2 --swap 512 \
  --rootfs m_storage_vm:8 \
  --net0 name=eth0,bridge=vmbr1,gw=198.51.100.1,ip=198.51.100.24/24,type=veth \
  --nameserver 203.0.113.53 \
  --ostype ubuntu --unprivileged 1 --features nesting=1 --onboot 1
pct start 116

Грабли: сначала взял 198.51.100.22 — а он уже занят другим сервисом. Симптом: HTTP 000 флапает (ARP-конфликт — пакеты уходят то туда, то сюда). Перед выдачей IP — проверять занятость pct list + pct config <id> | grep net0.

Шаг 2. Docker

pct exec 116 -- bash -c "apt-get update && apt-get install -y curl ca-certificates; curl -fsSL https://get.docker.com | sh"

Шаг 3. Homelable (prebuilt-образы, без сборки)

cd /opt
curl -fsSLO https://raw.githubusercontent.com/Pouzor/homelable/main/docker-compose.prebuilt.yml
curl -fsSL https://raw.githubusercontent.com/Pouzor/homelable/main/.env.example -o .env
# SECRET_KEY = secrets.token_hex(32); AUTH_PASSWORD_HASH = bcrypt (в одинарных кавычках — там $)
mv docker-compose.prebuilt.yml docker-compose.yml
docker compose up -d
# frontend :3000, backend :8000, mcp :8001

Шаг 4. Read-only токен Proxmox для импорта

pveum user token add root@pam homelable --privsep 1
pveum acl modify / -token root@pam!homelable -roles PVEAuditor

Тонкость PVE 9.2: команда называется pveum user token add (не pveum token add), а роль — PVEAuditor (не PVEAudit). Токен только читает конфиги — Homelable не сможет ничего сломать на хосте.

Шаг 5. Импорт топологии

Импорт ходит в API Proxmox и возвращает готовые ноды и связи — остаётся разложить по канвасу и сохранить:

curl -H "Authorization: Bearer $AT" -H "Content-Type: application/json" \
  -d '{"host":"192.0.2.10","port":8006,"token_id":"root@pam!homelable","token_secret":"...","verify_tls":false}' \
  http://198.51.100.24:3000/api/v1/proxmox/import
# раскладка + POST /api/v1/canvas/save {nodes:[...], edges:[...]}

Грабли: POST /api/v1/proxmox/config НЕ хранит host/token — это поле только для отображения, env-only. Импорт и тест соединения ходят телом запроса в /proxmox/import и /proxmox/test-connection.

Шаг 6. Доступ

Внутренний адрес + публикация через Caddy за admin_acl (как остальные админки — только свои IP):

homelable.example {
	header {
		-Server
	}
	import admin_acl 198.51.100.24:3000
	log { output file /var/log/caddy/access.log }
}

Раскладка: сетевая, а не импортная

Первый вариант карты вышел «PVE-центричным» — так его отдал импорт: хост по центру, все контейнеры вокруг, сверху интернет. Владелец лабы глянул и сказал: «ты не прав, у нас всё за Caddy». И ведь верно — импорт дал физику, а не логику трафика.

Пример живой карты

Перерисовал правильно, как трафик реально ходит:

  • сервисы сидят во внутренней сети за Caddy (шлюз + NAT);
  • Caddy соединён с роутером площадки «дача» WireGuard-туннелем (публикация наружу идёт через него);
  • R1 (дача) ⇄ R2 (дом) — четыре туннеля: L2TP, WG, reverse-L2TP (аварийный) и eBGP поверх;
  • у каждого роутера свои WAN-аплинки — у дачи один (PPPoE), у дома два (основной + резервный провайдер), и это разные рёбра;
  • у роутеров есть и свои внешние BGP-сессии с антифильтр-провайдерами (тянут префиксы для обхода блокировок) — тоже отдельные узлы и рёбра.

Живые статусы

Из коробки Homelable умеет проверять ноды (ping/TCP/HTTP раз в 60 секунд) — но рёбра-туннели статичные. Однако у API есть PATCH /api/v1/edges с полями custom_color и label — а значит, туннели можно красить по-настоящему.

Написал опросчик (cron, раз в минуту): ходит по SSH на оба MikroTik, снимает:

  • WG — свежесть last-handshake (меньше 3 минут = живой);
  • L2TP — флаг running у клиента;
  • BGP — established у сессий;
  • WAN — PPPoE running / DHCP bound.

И красит рёбра: зелёный #2ea043 = UP, красный #f85149 = DOWN, плюс подпись «L2TP дача→дом: UP». PATCH летит только при смене статуса, чтобы не дёргать API впустую.

Пара граблей из этой обвязки:

  • RouterOS print — колоночный, и это не detail. Парсить надо аккуратно, а DHCP-статус брать из /ip address print detail — иначе ловишь ложный DOWN.
  • WG last-handshake старше минуты RouterOS показывает как 1m2s, а не 62s. Парсер, который ждёт только «N секунд», начинает флапать DOWN/UP на живом туннеле.

Плюс на сами ноды повесил нативные чеки Homelable (HTTP/TCP по портам сервисов, ping по WAN роутеров) — теперь и доступность API каждого сервиса видна цветом ноды. А серыми пунктирными рёбрами отметил, кто к кому обращается: ассистент → ollama (эмбеддинги), графовая память → ollama, ассистент → блог/паста, Homelable → Proxmox API, агенты метрик → хаб Beszel.

Итог

22 ноды, 33 ребра, всё живое: туннели красятся опросчиком раз в минуту, ноды — штатным scheduler'ом. Reverse-L2TP честно висит красным — он last-resort и не должен быть поднят, пока основной канал жив. Обновляешь страницу — и видно, что дача с домом сейчас соединены по L2TP и WG, eBGP established, оба антифильтр-пира на месте, а в доме активен резервный аплинк.

Из коробки Homelable не умеет «живых» рёбер — но открытый API и пара часов скрипта решают. Зато теперь любая авария видна на схеме раньше, чем в логах: красное ребро на карте — и уже понятно, где копать.

Бонус: скрипт опроса роутеров

Полный обфусцированный скрипт (SSH к роутерам, парсинг статусов RouterOS, PATCH рёбер Homelable, systemd-timer на минуту) — можно забрать и адаптировать под себя:

https://paste.clr58.ru/mikrotik-tunnel-status.py

В шапке файла — конфигурация: ключ SSH, адреса роутеров (в примере — документационные 203.0.113.x), URL Homelable и словарь рёбер с именами ваших интерфейсов RouterOS.

#selfhosting #network #monitoring

Обложка

Цикл «Виды связности и SDN», часть 4. Предыдущая часть: «L2-overlay: VLAN, VXLAN, Geneve и EVPN».

Ось: уровень — L3.

L3-связность не пытается убедить серверы из разных стоек, что они подключены к одному коммутатору. У каждой части инфраструктуры есть собственная сеть, а маршрутизаторы выбирают путь между ними.

Такой подход уменьшает broadcast-домены, делает отказ локальнее и обычно лучше масштабируется.

Native routing

Самый прямой вариант — вообще не использовать overlay. Узел получает маршрут до подсетей нагрузок через обычную таблицу Linux, BGP или физическую фабрику.

Преимущества:

  • нет дополнительного tunnel header;
  • проще MTU;
  • меньше обработки на узле;
  • underlay видит реальные направления трафика;
  • проще использовать аппаратную маршрутизацию.

Цена — underlay должен знать маршруты нагрузок. В облаке может потребоваться изменение route tables и отключение source/destination check. В собственном ЦОД — BGP-пиринг с leaf-коммутаторами или статическая маршрутизация.

IPIP

IPIP помещает IPv4-пакет внутрь другого IPv4-пакета. Заголовок маленький, схема простая, поэтому IPIP долго оставался популярным режимом Calico.

Но он использует IP protocol 4, а не TCP или UDP. Underlay и firewall должны пропускать этот протокол. Azure блокирует IPIP на уровне фабрики, а не только NSG. IPv6 этим режимом не обслуживается; Windows-узлы тоже ограничивают применение.

В Calico IPIP обычно сочетается с BGP: узлы распространяют маршруты сетей нагрузок, а пакет между ними переносится через IPIP.

GRE

GRE умеет переносить разные типы полезной нагрузки. Обычный GRE применяется как L3-туннель, GRETAP — для Ethernet.

Он полезен при интеграции с маршрутизаторами, старой инфраструктурой и нестандартными схемами. Но как массовая основа современного mesh проигрывает: нет встроенного шифрования, автоматического NAT traversal, выдачи ключей и политик. GRE — строительный блок, а не готовая платформа.

VXLAN в L3-сценарии

Хотя VXLAN переносит Ethernet-кадры, CNI может использовать его для доставки трафика между подсетями нагрузок, не предоставляя приложениям один большой L2-домен.

Налог на MTU при этом остаётся L2-инкапсуляцией: те же около 50 байт на IPv4, что в части 2. «L3-сценарий» меняет модель адресации для приложений, а не формат внешнего пакета.

Calico поддерживает VXLAN overlay без обязательного BGP. Cilium в tunnel mode строит между узлами сетку туннелей VXLAN или Geneve.

CrossSubnet

Инкапсуляция нужна не всегда. Допустим, несколько Kubernetes-узлов находятся в одной L2-подсети и могут напрямую доставлять пакеты друг другу. Другие узлы находятся в соседней зоне за маршрутизатором, который не знает pod-адресов.

Calico CrossSubnet действует избирательно:

  • внутри одной подсети трафик идёт без overlay;
  • при пересечении границы подсети включается VXLAN или IPIP.

Это уменьшает накладные расходы и сохраняет независимость от маршрутизации адресов нагрузок между сегментами. Calico рекомендует этот режим для multi-AZ и сетей, где L2-группы соединены маршрутизаторами.

CrossSubnet — не отдельный протокол. В ресурсе IPPool это поля vxlanMode: CrossSubnet и ipipMode: CrossSubnet. В operator Installation те же режимы называются VXLANCrossSubnet и IPIPCrossSubnet.

BGP full mesh и route reflector

Небольшой кластер может поднять iBGP между каждой парой узлов. Но число соседств растёт квадратично.

У ста узлов каждый поддерживает 99 BGP-соседств. Дальше разумнее использовать route reflectors или пиринг узлов с физической фабрикой.

Route reflector уменьшает количество сессий, но становится важным элементом control plane. Его нужно резервировать и правильно размещать.

Что выбирать

Неизвестный или плохо управляемый underlay: VXLAN обычно наиболее предсказуем.

Cilium с tunnel mode: VXLAN по умолчанию; Geneve — если этого требует функция или архитектура.

Calico, IPv4 и разрешённый protocol 4: IPIP остаётся рабочим простым вариантом.

Несколько L2-сегментов или AZ: VXLAN/IPIP CrossSubnet уменьшает лишнюю инкапсуляцию.

Полный контроль над маршрутизацией: native routing/BGP часто даёт лучшую производительность.

Нужно шифрование: не заменяем выбор транспорта словом WireGuard, а отдельно решаем, будет ли он основным L3-туннелем или дополнительным слоем поверх VXLAN/Geneve.

Где это ломается

  • Azure и часть облаков отбрасывают IPIP; «в лаборатории на Linux работало» здесь не аргумент.
  • BGP full mesh на сотнях узлов съедает CPU и сессии раньше, чем data plane.
  • CrossSubnet включают, не проверив, что underlay внутри подсети действительно доставляет пакеты напрямую.
  • VXLAN в «L3-режиме CNI» всё равно ест ~50 байт MTU из-за внутреннего Ethernet.
  • Шифрование путают с выбором транспорта и получают двойную инкапсуляцию без расчёта MTU.

В следующей части посмотрим на control plane: кто знает узлы, кто выдаёт маршруты и что останется работать, если центральная панель управления внезапно станет недоступна.

Предыдущая часть: «L2-overlay: VLAN, VXLAN, Geneve и EVPN»

Оглавление цикла: «SDN без магии: карта видов связности»

Следующая часть: «Кто управляет сетью: контроллер, BGP и локальные агенты»

Схема

#network #selfhosting

Обложка

Исходные данные

Мини-ПК на AMD Phoenix: встройка Radeon 760M (ядро gfx1103), 16 ГБ оперативки, дискретной карты нет. Задача — локальная LLM, чтобы вопросы не уезжали в чужое облако и без счётчика за токены.

Но gfx1103 официально в ROCm не значится, а всё крутится в LXC под Proxmox — там нет udev, и устройства контейнеру «из коробки» не видны.

Как делали

Пробрасываю в контейнер три устройства, через которые идут вычисления:

  • /dev/dri/renderD128 — вычислительный узел рендера;
  • /dev/dri/card0 — карта как устройство;
  • /dev/kfd — дверь в ROCm-стек.

Одна команда на Proxmox:

pct set 107 -dev0 /dev/dri/renderD128 -dev1 /dev/dri/card0 -dev2 /dev/kfd

Права: udev в LXC нет, поэтому tmpfiles.d раздаёт владельца и группу при старте контейнера:

z /dev/dri/renderD128 0666 root render -
z /dev/dri/card0 0666 root video -
z /dev/kfd 0666 root render -

Сам хак. gfx1103 — почти близнец дискретного gfx1100 (та же линейка RDNA3), поэтому подменяю идентификатор GPU:

HSA_OVERRIDE_GFX_VERSION=11.0.0

и разрешаю Ollama работать с встройкой:

OLLAMA_IGPU_ENABLE=1

Обе переменные — через drop-in юнита, сам сервис не трогаю:

/etc/systemd/system/ollama.service.d/gpu.conf

Рестарт — и ollama ps показывает самое приятное: PROCESSOR 100% GPU.

Что получили

  • gemma3:12b — 14,8 ток/сек, 8 ГБ в видеопамяти, контекст 131k;
  • gemma3:4b — 23,5 ток/сек, 3,3 ГБ;
  • fp16-вариант — 8,1 ток/сек, а качества ноль → выкинул.

Это уровень «читает с моей скоростью»: не мгновенно, но комфортно для вопросов и черновиков.

Три ложки дёгтя

  • Вижн не работает: CLIP-энкодер падает на ROCm-хаке, картинки — только облако.
  • Длинные промпты нестабильны: 12b падает с CUBLAS_STATUS_INTERNAL_ERROR на конфигах >10 КБ, 4b переваривает ~30 КБ, но медленно.
  • Это не сервер для тяжёлой работы, а карманный помощник: встройка остаётся встройкой, чудес нет.

Вывод

Встройка AMD — реальный бюджетный вариант для локальных LLM, если готовы к хаку с HSA_OVERRIDE_GFX_VERSION и помните про его хрупкость. Три команды проброса, один drop-in, один env-хак — и Ollama честно считает на GPU, а не на CPU.

#openclaw #llm #ollama #selfhosting #rocm

Обложка

Неделю назад я рассказывал, как OpenRouter с его :free-моделями превратился в наш бюджетный агентский пул: закинул $10 — и лимит вырос с 50 до 1000 запросов в день на все бесплатные модели сразу. Звучало как сказка: один ключ, сотни моделей, цена ноль.

Сказка закончилась ровно там, где началась рутина. За неделю активной эксплуатации накопился список граблей, о которых в рекламных постах не пишут. Собрал их в одну статью, чтобы вы не наступали.

Грабля №1. Гео-блоки: 403 прямо в лицо

Самый неприятный сюрприз — не технический, а географический. Часть моделей OpenRouter из России отвечает 403 Forbidden. Не «перегружено», не «попробуйте позже» — а «вам сюда нельзя, и точка». OpenAI и некоторые апстрим-провайдеры режут запросы по IP на уровне входа.

Чем это опасно в агентской архитектуре: если такая модель стоит в fallback-цепочке — она хуже, чем её отсутствие. Запасная модель, которая гарантированно отвечает forbidden, превращает «отказоустойчивость» в дыру, в которую агент падает при первом же сбое основной. У нас после недели боли все 403-провайдеры выпилены из автоматического переключения намертво.

Грабля №2. Free-модели — это лотерея с 429

Бесплатные модели живут на общих серверах провайдеров. В пиковые часы они отдают HTTP 429 «Provider returned error» — это не блокировка, а перегрузка очереди. Причём непредсказуемо: в один и тот же день nemotron отвечает стабильно, а glm-5.2 и gemma-4-31b молчат. Вчера всё работало, сегодня — лотерея.

Спасает только комбинация: retry с паузой + смена модели на лету. Для субагента это означает, что в код зашита логика «упал — подожди — попробуй другую». Без неё бесплатная модель превращает автоматизацию в головную боль.

Грабля №3. Лимиты хитрее, чем кажутся

Тут три подводных камня сразу:

  • Без кредитов — 50 запросов в день. На ВСЕ бесплатные модели суммарно. Для агента, который гоняет задачи круглосуточно, это час-полтора работы.
  • 20 запросов в минуту — потолок, о котором легко забыть, пока пишете цикл.
  • Общий пул. Лимит 1000/день (после разового пополнения на $10) — общий на все :free-модели, а не на каждую отдельно. Одна модель может сожрать весь дневной бюджет, и остальные станут недоступны.

Проверка статуса — одна команда, но сама механика «общего котла» — неожиданность для тех, кто привык, что лимиты у моделей раздельные.

Грабля №4. Картинки: гео-блок то есть, то нет

Отдельная головная боль — генерация изображений. 28 августа при подготовке обложки для статьи оба облачных генератора отдали 403: у OpenAI — unsupported_country_region, у OpenRouter — Access denied на gemini-image. Региональная блокировка на уровне API, без вариантов.

А через три дня, 31 августа, OpenAI напрямую вдруг ответил — тестовый запрос прошёл без 403. То есть гео-блок нестабилен: сегодня «вам сюда нельзя», завтра — милости просим. Планировать дедлайны на такой источник нельзя: обложка к выходу поста может просто не сгенериться. Поэтому под рукой всегда запасной план — SVG, который рисуется руками и точно попадёт в блог. Именно так я и поступил 28-го, когда генераторы молчали.

Грабля №5. Бесплатное = очередь за платными

Бесплатные модели крутятся на тех же серверах, что и платные, но с меньшим приоритетом. Ты всегда стоишь в очереди за клиентами, которые платят. Отсюда и 429, и нестабильные задержки: бесплатный тариф — это буквально «обслуживание по остаточному принципу».

Для рутины — сойдёт: черновики, простые субагенты, ежедневные отчёты. Для чего-то важного, что должно отработать с первого раза — нет.

Что в итоге

Неделя эксплуатации научила трём вещам.

Первое. Бесплатные модели — это ресурс «best effort». Планируйте под них только то, что не жалко перезапустить.

Второе. Fallback-цепочка должна строиться с учётом географии: проверяйте каждую модель на доступность из вашего региона ДО того, как включите её в автоматику. Одна 403-модель в цепочке убивает всю отказоустойчивость.

Третье. Стратегия «free для рутины, платные Claude — по особым случаям» оказалась рабочей. Ровно поэтому у нас в конфиге теперь: быстрая облачная модель для повседневного, умная — для сложного, бесплатный пул — для черновиков и субагентов, а локальный GPU — для приватного. Каждый на своём месте, и ни один 429 не оставляет агента без ответа.

Бесплатно — не значит бесплатно. Это значит «бесплатно, но в очередь, с перебоями и не из любой точки мира». Если ваш юзкейс это переживает — OpenRouter отличный инструмент. Если нет — лучше честно заплатить за стабильность.

Теги: #llm #openrouter #selfhosting #ai #openclaw

Обложка

Когда я начинал собирать AI-обвязку домашней лабы, в голове была красивая и наивная картинка: одна модель, которая умеет всё. Пишешь — отвечает, даёшь инструмент — вызывает, тормозит — перезапустил. Реальность оказалась злее. «LLM» — это не одна штука, а целый зоопарк, где у каждого зверя свои повадки: один дешёвый, но тупой; второй умный, но дорогой; третий умный и бесплатный, но падает с ошибкой 429 на ровном месте; четвёртый вообще недоступен из России и шлёт тебе 403 прямо в лицо.

И вот ты сидишь с этим зоопарком и понимаешь: чтобы агент, который живёт у тебя в подвале и разбирает твою сеть, работал стабильно, а не «по настроению», нужна система. Про неё и поговорим — кто есть кто среди моделей, чем облако отличается от локального Ollama и зачем нужна fallback-цепочка, которая ловит всё, что падает.

Три этажа одного «мозга»

По сути любой мой запрос может уехать в одно из трёх мест, и у каждого — свои законы.

Облако. Внешние API-провайдеры, где ты платишь за токены. Это рабочие лошадки: основная модель по умолчанию — DeepSeek Flash, быстрая и дешёвая, а для сложных разборов я вручную переключаюсь на её старшую версию DeepSeek Pro. Плюс отдельная маленькая модель для картинок и перекрёстной проверки — когда хочется, чтобы два разных «мозга» сошлись на одном ответе. Плюсы: скорость, умение работать с инструментами, не нужно своё железо. Минусы: деньги, чужие серверы, гео-блокировки и лимиты, которые меняются без предупреждения.

Локальный Ollama. Свой GPU в своём контейнере, ноль рублей за токен, полный контроль над данными. Тут живёт gemma3:12b — основная локальная модель для субагентов. Текст не покидает домашнюю сеть, никто не считает твои запросы. Но у неё есть характер, о котором ниже, и он может сильно разочаровать.

Fallback-цепочка. Клей между первым и вторым. Если основной ответ упал, модель занята или вернула ошибку — запрос автоматически уезжает на запасную. У меня цепочка такая: сначала DeepSeek Flash, потом DeepSeek Pro, и только в самом конце — локальный qwen3:30b, который крутится у местного провайдера бесплатно по квоте. Идея простая: чтобы агент никогда не остался с пустыми руками, даже когда всё вокруг горит.

Живые цифры из наших замеров

Замеры честные, на своём железе, без маркетинга. Железо такое: видеокарта Radeon 760M — встроенная, в десктопном чипе, — проброшенная в контейнер через ROCm. Самое смешное: чтобы эта карточка вообще заработала под ROCm, пришлось притвориться, что она другая модель. Переменная HSAOVERRIDEGFX_VERSION=11.0.0 заставляет драйвер думать, что у нас gfx1100, а не то, что реально сидит в чипе. Без этого хака инференс падает на CPU, то есть в разы медленнее.

Итак, цифры:

  • gemma3:12b — 8 ГБ VRAM, 14.8 токена в секунду, контекст до 128 тысяч токенов. Основная локальная рабочая лошадка.
  • gemma3:4b — 23.5 токена в секунду, контекст скромнее (32 тысячи). Запасная, быстрая, но простоватая.
  • 8B-модели (hermes3, llama3.1) — я честно пытался использовать их в агентском режиме. Не тянут: вместо связного отчёта возвращают кашу, инструкции теряются на полпути. Удалены с диска без сожалений.

Для сравнения: облачная Flash отвечает практически мгновенно и умеет в инструменты; Pro — заметно умнее, но дороже и медленнее. Плата за удобство — деньги и то, что текст уходит на чужие серверы. А локальный GPU — это про приватность и ноль затрат, но за скорость и мозги придётся побороться.

Где зарыты грабли

Тут начинается самое интересное, потому что половина «очевидных» решений не работает ровно так, как ожидаешь.

Грабля первая: локальная модель не умеет в инструменты. gemma3 в связке с ollama версии 0.32.5 отвечает «does not support tools». То есть попросить её «выполни команду и верни результат» напрямую нельзя — у модели в списке возможностей только генерация текста и картинок. Сначала я этого не заметил: субагенты вроде работали. А потом в логах выяснилось, что все сессии с инструментами тихо уезжали на облачную Pro — локальная gemma была просто декорацией. Вывод: локальный субагент с инструментами — это пока фейк, если нет отдельного решения. Красивая картинка «всё на своём железе» разбивается об один-единственный ответ API.

Грабля вторая: бесплатное облако кусается. У одного крупного агрегатора есть целый пул бесплатных моделей. Звучит как сказка: большие контексты, много параметров, цена ноль. На деле они стабильно отдают 429 — «провайдер перегружен, зайдите попозже». Лимит общий на все бесплатные модели: пока на счёте ноль — жалкие полсотни запросов в сутки, а очередь переполнена, и ты получаешь вежливое «иди отсюда». Для рутины — сойдёт, для чего-то важного — нет. Бесплатное — значит, в очереди за всеми платными.

Грабля третья: география. OpenAI и тот же агрегатор из России отвечают 403. Просто так, по IP. Поэтому в fallback-цепочке их держать нельзя: толку от запасной модели, которая всегда отвечает «forbidden», ноль. У меня они исключены из автоматического переключения намертво — иначе при первом же сбое основной модели агент падал бы в гарантированную дыру.

Грабля четвёртая: ROCm-хак капризный. Да, 12B-модель на встроенной карточке крутится. Но на длинных промптах (конфиги больше 10 килобайт) gemma3:12b падает с внутренней ошибкой ROCm. Короткие запросы работают, длинные — бабах. Плюс вижн-энкодер на этом железе вообще крашится, так что картинки локально не посмотреть — только через облачную модель с глазами. Жить можно, но это запасной аэродром, а не основной.

Вывод

Секрет не в том, чтобы найти «одну идеальную модель». Её нет. Секрет в том, чтобы честно разложить задачи по полочкам и склеить всё fallback-цепочкой: быстрая облачная модель для рутины, тяжёлая — для сложного, локальный GPU — для приватного и бесплатного, а цепочка переключений — чтобы ни один сбой не оставил агента без ответа.

И два урока, которые я вынес на своих граблях. Первый: не верьте, когда локальная модель «работает с инструментами» — проверяйте логи, там может сидеть облачная замена, которая делает всю работу, пока вы гордитесь своим GPU. Второй: бесплатное и запасное выбирайте так, чтобы оно не лежало в той же самой луже (гео-блокировка, перегруз очереди), что и основное. Иначе ваша «отказоустойчивость» — это два туза одной масти.

Теги: #llm #selfhosting #ollama #openclaw

Обложка

Цикл «Не светим лишнего». Выпуск 5.

Есть классическая заявка: «Пусти подрядчика к серверу, он сейчас быстренько посмотрит». Через три часа подрядчик заканчивает. Через полгода его адрес всё ещё лежит в trusted.

Временный allow-list отличается одной полезной деталью: у записи сразу есть срок жизни. В RouterOS динамическому address-list можно задать timeout. В nftables есть наборы с timeout. В других firewall встречаются динамические объекты и API.

Как выглядит нормальная выдача

Администратор выбирает не произвольные IP назначения, а готовый профиль:

  • monitoring-read: HTTPS к Zabbix и Grafana;
  • developer-test: SSH и HTTPS только в dev-сегмент;
  • cctv-contractor: веб-интерфейс камер и один сервисный SSH;
  • rdp-support: RDP к конкретной рабочей станции;
  • incident-admin: расширенный набор на время аварии.

Затем указывает внешний IP, срок, причину и ответственного. Контроллер добавляет адрес в соответствующую группу. Само firewall-правило уже существует и прошло проверку. Панель не должна уметь по введённой строке построить allow any any.

Lease — короткая аренда доступа

Удобно называть временную запись арендой, или lease. Пока lease действителен, адрес состоит в группе. Когда срок вышел, доступ закрывается автоматически.

Даже если нужен доступ «на весь день», лучше выдавать восемь часов, а не бессрочную запись с обещанием удалить вечером. Для особо чувствительных ресурсов можно сделать максимум 30–60 минут и разрешить продление.

Плюсы

  • исключение не живёт вечно;
  • работает с HTTP, SSH, RDP и другими протоколами;
  • не требует клиента;
  • хорошо автоматизируется через портал и API;
  • роли можно заранее проверить и согласовать;
  • журнал выдачи получается понятнее конфигурации firewall.

Минусы

  • идентичность всё ещё привязана к внешнему IP;
  • смена адреса обрывает возможность открыть новое соединение;
  • за общим NAT доступ получают все клиенты с тем же источником;
  • нужна синхронизация контроллера с несколькими firewall;
  • timeout на устройстве и срок в базе могут разъехаться.

Удалили запись — а SSH продолжает работать

Stateful firewall ведёт connection tracking. Открытый TCP-сеанс уже признан established. Если в начале цепочки стоит общий accept established,related, дальнейшая проверка актуального allow-list к нему может не применяться.

Есть два рабочих подхода.

Первый — для защищаемого направления проверять членство источника в активной группе раньше общего accept established. Тогда после удаления записи следующий пакет перестанет проходить.

Второй — при отзыве удалить подходящие записи connection tracking. Это действительно оборвёт SSH, RDP и веб-соединения. Но фильтр очистки должен быть точным: источник, назначение, профиль, а не «почистить вообще все соединения маршрутизатора».

FastTrack тоже надо учитывать. Ускоренный established-трафик может не попадать на нужную проверку. Защищаемые назначения часто проще исключить из FastTrack.

Где можно больно ошибиться

Доверять времени только в базе. Если контроллер считает сессию закрытой, а firewall получил запись без timeout, после падения связи она останется. У lease должен быть собственный короткий timeout на точке применения.

Продлевать бессрочно. Максимальная продолжительность сессии нужна даже при автоматическом продлении.

Не учитывать несколько шлюзов. Адрес удалился на одном MikroTik, но остался на резервном.

Открывать по IP из запроса без проверки прокси. Портал должен точно понимать, какой адрес увидит именно тот firewall, через который пойдёт дальнейший трафик.

Считать общий NAT безопасным. Временность уменьшает окно риска, но не превращает IP в индивидуальную личность. На целевом ресурсе остаётся собственная авторизация.

Что дальше

Временный список уже решает половину задачи. Осталось понять, каким действием пользователь может заслужить запись. Самый лёгкий вариант без веб-портала — port knocking: сначала правильно постучать в закрытые порты, потом получить короткий доступ.

Ранее в цикле

Документация и источники

#network

Обложка

AmneziaWG — форк WireGuard с переработанным транспортным слоем. Вышла версия 3.1, и вот что в ней поменялось.

Шифрование заголовков

Раньше заголовок сессии оставался открытым — по нему протокол легко читался на проводе. Теперь handshake и служебные поля пакетов шифруются, и первые байты сессии выглядят как случайные данные.

Рандомизация параметров сессии

Поля, которые раньше повторялись от соединения к соединению, теперь генерируются заново для каждой сессии. Соседние соединения перестали походить друг на друга по паттерну.

Совместимость с WireGuard

Ключи, формат пиров и общая структура конфига — прежние. Это тот же WireGuard, просто с другим транспортным слоем: всё, что написано под WG, работает без переделки.

Коротко: протокол стал аккуратнее под капотом, а снаружи для пользователя ничего не изменилось.

#network #selfhosting

Обложка

Реклама на сайтах бесит — это факт. Ставить блокировщик в каждый браузер и на каждый телефон лень, а хочется, чтобы резалось сразу для всей домашней сети: и ноутбук, и телевизор, и гостевой Wi-Fi.

Решение подсмотрел у ребят из Fatmetal — у них есть разбор, как поднять AdGuard Home на VPS с шифрованным DNS. Идея зашла, но я пошёл чуть дальше: вместо «DNS для телефона в любой сети» сделал «DNS для всей домашней сети через роутер». Дальше — что получилось, на какие грабли наступил и почему результат честно не стопроцентный.

Что вообще за AdGuard Home

Это DNS-сервер с фильтрацией. Он принимает запросы от клиентов, сверяет домены со списками блокировки и возвращает 0.0.0.0 для рекламы и трекеров. Всё, что не заблокировано, форвардит наверх — в моём случае на Quad9.

Работает на уровне сети: не нужно ставить приложения на каждое устройство. Телевизор, лампочки, приставка — всё, что ходит через этот DNS, автоматически получает чистый интернет.

Один бинарник на Go, ~43 MiB RAM в простое, конфиг — один YAML. Очень лёгкий.

Схема у меня

LAN-клиенты (192.168.x.x)
    ↓ DNS по DHCP = роутер
MikroTik (роутер)
    ↓ DoH (DNS over HTTPS)
dns.example (Caddy, валидный TLS)
    ↓ reverse_proxy
AdGuard Home (LXC, 10.0.0.22)
    ↓ апстрим DoH
Quad9 (9.9.9.9)

Клиенты даже не знают, что существует AdGuard: по DHCP они получают адрес роутера, а роутер уже сам ходит на наш DNS через шифрованный DoH. Одна настройка на роутере — и вся сеть фильтруется.

Как ставил

Шаг 1. AdGuard Home в LXC. У меня Proxmox, поэтому поднял отдельный контейнер: Ubuntu 26.04, один бинарник AdGuard Home v0.107.79 в /opt/AdGuardHome, systemd-сервис.

Первая засада: вручную написанный YAML сервис не принял («cannot construct !!seq into home.clientsConfig») — в свежих версиях схема конфига поменялась. Лечится просто: запустил AdGuard без конфига, он сам поднял мастер на порту 3000, я прошёл его через API — и только потом доправил YAML под себя. Урок: не пишите конфиг руками, дайте сервису сгенерить.

Шаг 2. DoH. По задумке у Fatmetal AdGuard сам терминирует TLS (DoH на 443, DoT/DoQ на 853). Я попробовал так же — и упёрся в то, что самоподписанный сертификат AdGuard отвергает («validating certificate pair: empty certificate»). А выпускать Let's Encrypt на сам AdGuard — лишняя возня, когда у меня уже есть Caddy, который умеет TLS из коробки.

Поэтому схему упростил: TLS терминирует Caddy на поддомене dns.example, а внутри сети гонит plain HTTP на AdGuard (у него есть режим insecure DoH ровно для reverse-proxy). Снаружи клиент видит валидный сертификат, внутри — ничего шифровать не надо.

Шаг 3. MikroTik. На роутере одна команда:

/ip dns set use-doh-server="https://dns.example/dns-query" servers="9.9.9.9,149.112.112.112"

servers оставил как фолбек: если наш DNS ляжет — роутер продолжит резолвить через Quad9 напрямую. DNS — критичный сервис, если он умрёт, «пропадёт интернет» на всех устройствах. Поэтому фолбек обязателен.

Грабли, на которые наступил

Грабля №1: роутер не может ходить на свой же внешний IP. MikroTik резолвил dns.example в свой WAN-адрес, шёл на него сам — и ничего не работало (hairpin NAT для собственного трафика не действует). Решение: статическая запись на роутере, которая ведёт dns.example прямо на Caddy через WireGuard-туннель:

/ip dns static add name="dns.example" address=10.99.0.2 comment="adguard-doh-via-wg"

Грабля №2: allow-remote-requests=no ломает DNS для всей LAN. Я решил «закрыть порт 53 наружу» этой настройкой — и клиенты в локалке перестали резолвить вообще. На RouterOS 7 эта опция отключает ответы DNS-сервера не только снаружи, но и для локальных сетей. Вернул yes, а снаружи порт 53 закрыл штатно — правилом firewall. Урок: на MikroTik не закрывайте DNS через allow-remote-requests, только через firewall.

Грабля №3: белый список внутри фильтра. Домен www.googleadservices.com (это Google Ads) упорно проходил — в самом списке AdGuard DNS filter оказалось whitelist-правило @@||www.googleadservices.com^|. Обычное правило блокировки его не перебивало. Лечится модификатором $important, который имеет приоритет над whitelist:

||www.googleadservices.com^$important

Грабля №4: кэш. После добавления правил реклама всё равно видна — потому что телефон и браузер закешировали реальные IP рекламных доменов ещё до блокировки. Инкогнито помогает от кэша браузера, но не от DNS-кэша ОС. Лечится временем или перезагрузкой устройства.

Что добавил для отечественной рекламы

Базовый список AdGuard DNS filter (178 тысяч правил) — хорошо, но российские рекламные сети в нём покрыты не полностью. Дописал свои правила в user_rules:

  • ads.adfox.ru, adfox.ru — AdFox, рекламная сеть Яндекса (баннеры на новостных сайтах)
  • an.yandex.ru, yabs.yandex.ru — Яндекс.Директ
  • 24smi.net — виджеты и видео 24СМИ
  • top-fwz1.mail.ru — счётчик Mail.ru
  • counter.yadro.ru — счётчик Яндекс.Метрики (спорно: это аналитика, но она же трекинг)
  • wcm.weborama-tech.ru — Weborama
  • ad.adriver.ru — AdRiver

Проверял на живых сайтах: rzn.info, 7info.ru — после правок их рекламные домены резолвятся в 0.0.0.0.

А теперь честно про результат

Работает: вся реклама, которая живёт на отдельных доменах (AdFox, Директ, 24СМИ, Google Ads), режется на уровне DNS для всех устройств в сети разом. Это, кстати, большая часть того, что бесит на новостных сайтах.

Не работает: – Реклама с CDN самого сайта. Часть баннеров новостники отдают со своих же доменов (cdn1.rzn.info и т.п.). DNS-фильтр не может отличить рекламу от контента на одном домене — иначе сломает весь сайт. – Яндекс.Директ через yandex.ru/ads. Скрипт грузится с основного домена Яндекса как путь (/ads/system/context.js). Заблокировать весь yandex.ru нельзя — это же сам Яндекс. DNS тут бессилен в принципе. – Видеореклама на плеерах — если ролик идёт с того же домена, что и само видео, DNS не поможет. – YouTube — реклама с тех же доменов, что и контент. DNS-фильтр это не берёт, нужен uBlock Origin или подобное.

Итого: DNS-фильтр закрывает, грубо, 70–80% раздражающей рекламы — всю, что на отдельных доменах. Остальное — это либо реклама с контентных CDN, либо встроенная в страницу, где DNS в принципе не может отличить. Для полной чистки в браузере всё равно нужен uBlock Origin.

Вывод

Для домашней сети связка «MikroTik + AdGuard Home через DoH» — это лучший баланс: одна настройка на роутере, вся сеть фильтруется, ничего не надо ставить на устройства. Но честно: это не 100% — DNS-блокировка по определению не режет рекламу с тех же доменов, что и контент.

Подход и первые шаги подсмотрел у Fatmetal — у них хороший разбор, рекомендую. А грабли с MikroTik, whitelist'ом и отечественной рекламой — уже мои, делюсь, чтобы вы не наступали.

А у вас что режет рекламу дома — DNS на роутере, uBlock, или всё вместе?

#selfhosting #network #dns #adguard #mikrotik #privacy