agentleFS
vefmvaivefmvai/sysadmin/.claude/skills/finalize-vpn-routing/SKILL.md

finalize-vpn-routing

Skill1 starsChanged 3 months agoMITView on GitHub

Скилл-дирижёр: проверяет состояние уже начатой VPN-настройки на панели 3X-UI, находит что не доделано или сделано с ошибками, и доводит систему «умной маршрутизации» до конца — НЕ настраивает с нуля и НЕ дублирует логику, а диагностирует и дирижирует существующими скиллами. Снимает READ-ONLY диагноз VPN-стека (вход VLESS для устройств, выход upstream + балансир + observatory, гибкая маршрутизация «золотая середина», локальный прокси для программ на 127.0.0.1), сверяет с эталоном, показывает оператору чеклист «что есть / где дыры», и чинит дыры прогоном `/configure-vpn-routing` и `/setup-server-proxy` в правильном порядке. Финал — вердикт «система в идеальном состоянии» по чеклисту + smoke-инструкция. Для пользователя, у которого настройка зависла на полпути и непонятно что не так. Триггеры: «проверь и доведи маршрутизацию до конца», «доведи VPN до идеала», «у меня что-то не доделано в 3X-UI почини», «проверь что с настройкой VPN», «доведи систему умной маршрутизации», «finalize-vpn», «vpn doctor», «приведи VPN в порядок», «застрял на настройке маршрутизации». НЕ для установки панели — `/setup-vpn-panel`. НЕ для генерации клиентских конфигов — `/generate-client-config` (предложит как следующий шаг).

The file

Files
SKILL.md
<role> Я — дирижёр VPN-настройки. Когда оператор (часто новичок) застрял на полпути с маршрутизацией 3X-UI и не понимает, что не так, я: (1) снимаю фактическое состояние VPN-стека без изменений, (2) сверяю с эталоном «как должно быть», (3) показываю простым языком чеклист — что уже сделано и где дыры, (4) чиню дыры, дирижируя существующими скиллами (`/configure-vpn-routing`, `/setup-server-proxy`), (5) даю финальный вердикт «доведено до идеала». Я НЕ копирую логику этих скиллов и НЕ настраиваю с нуля — я диагност и дирижёр. Веду оператора за руку, спрашиваю минимум, объясняю что происходит (раздел 4.3 персоны). </role><context> Предполагается: - 3X-UI установлен (через `/setup-vpn-panel`), панель отвечает по HTTPS. - В `infra-config.json` секция `vpn.*` с `panel_url`, `panel_web_base_path`. - Креды панели в менеджере паролей под `3xui-panel-${SERVER_ALIAS}`. - Настройка маршрутизации НАЧАТА (возможно частично/с ошибками) — это и есть типичный вход. Если ничего не начато — скилл это увидит и проведёт настройку с нуля через те же подчинённые скиллы.

НЕ предполагается:

  • Установка панели (нет панели → отправляю на /setup-vpn-panel, не импровизирую).
  • Знание оператором структуры inbound/outbound/routing. Я показываю картину человеческим языком.
  • Что у оператора всё сломано — может быть, всё уже хорошо; тогда вердикт «идеал» и ничего не трогаю.</context>
<goals> После выполнения должно стать TRUE: - Снят READ-ONLY диагноз VPN-стека, оператору показан чеклист с ✅/❌. - Каждая ❌-дыра либо закрыта (прогоном подчинённого скилла с Yellow-брифингом), либо явно оставлена по решению оператора (с записью почему). - Итоговое состояние: вход VLESS для устройств, выход (upstream + при нескольких серверах балансир leastPing/probeInterval=5m), гибкая маршрутизация «золотая середина», локальный прокси для программ на 127.0.0.1 с понятной пометкой. - Финальный повторный диагноз показывает все ✅ (или зафиксированные осознанные исключения). - Оператору дана smoke-инструкция проверки. </goals>

Параметры

ПараметрRequiredDefaultОписание
SERVER_ALIASда—Имя сервера для менеджера паролей и inventory
PANEL_DOMAIN, PANEL_PORT, WEB_BASE_PATHдаиз vpn.* в configПараметры панели
ADMIN_LOGIN, PASSWORD_REFдаавтодетект из менеджераКреды панели
WANT_PROXYнетaskНужен ли локальный прокси для программ: yes/no/ask
PROXY_PORTнет1080Порт mixed-inbound прокси

Процедура

Шаг 0: Pre-check (STRICT)

Конфиг обязателен; секция vpn.* с panel_url/panel_web_base_path обязательна (иначе непонятно, к какой панели обращаться). Общий helper:

source "$SYSADMIN_ROOT/.claude/skills/_lib/find-config.sh"
find_sysadmin_config strict       # $CONFIG = infra-config.json (vpn.*)
find_brain_config || true         # $BRAIN_CONFIG = agent-config.json (secrets.manager)

# secrets.manager — агент-поле (ADR-0013): живёт в мозге ($BRAIN_CONFIG).
# Legacy-совместимость: если мозга нет — читаем из $CONFIG (старый единый формат).
get_agent_field() {  # $1=jq-путь, $2=default (путь одинаков в мозге и legacy)
  local v=""
  [ -n "${BRAIN_CONFIG:-}" ] && v=$(jq -r "$1 // empty" "$BRAIN_CONFIG" 2>/dev/null)
  [ -z "$v" ] && [ -n "${CONFIG:-}" ] && [ -f "${CONFIG:-}" ] && v=$(jq -r "$1 // empty" "$CONFIG" 2>/dev/null)
  [ -z "$v" ] && v="$2"
  echo "$v"
}

require_config_field "vpn.panel_url" \
    "3X-UI ещё не установлен. Сначала /setup-vpn-panel SSH_TARGET=... DOMAIN=..."
require_config_field "vpn.panel_web_base_path" \
    "3X-UI ещё не установлен. Сначала /setup-vpn-panel."

PANEL_URL=$(get_config_field vpn.panel_url)
PANEL_WEB_BASE_PATH=$(get_config_field vpn.panel_web_base_path)
PANEL_DOMAIN="${PANEL_DOMAIN:-$(echo "$PANEL_URL" | sed -E 's|https?://||; s|:.*$||')}"
PANEL_PORT="${PANEL_PORT:-$(echo "$PANEL_URL" | sed -E 's|https?://[^:]+:||; s|/.*$||')}"
WEB_BASE_PATH="${WEB_BASE_PATH:-$PANEL_WEB_BASE_PATH}"
SECRETS_MANAGER=$(get_agent_field '.secrets.manager' keychain)
# Папка инфры активного проекта (ADR-0013): её знает реестр projects[] в мозге.
# Legacy-совместимость: если мозга нет — старый infrastructure.root_path из $CONFIG.
INFRA_DIR="${ACTIVE_INFRA_ROOT:-}"
[ -z "$INFRA_DIR" ] && INFRA_DIR="$(get_config_field infrastructure.root_path)"

Если панель не отвечает (curl -sI ≠ 200) — STOP с конкретной причиной (возможно панель упала → предложить /health-check, или не установлена → /setup-vpn-panel).

Шаг 1: Получение пароля из менеджера

PASSWORD_REF вычисляется из secrets.manager и SERVER_ALIAS (как в /configure-vpn-routing Шаг 3): keychain:3xui-panel-${SERVER_ALIAS} и т.д.

Шаг 2: READ-ONLY диагноз (Green Zone, без брифинга)

PANEL_DOMAIN="$PANEL_DOMAIN" PANEL_PORT="$PANEL_PORT" WEB_BASE_PATH="$WEB_BASE_PATH" \
ADMIN_LOGIN="$ADMIN_LOGIN" PASSWORD_REF="$PASSWORD_REF" PROXY_PORT="$PROXY_PORT" \
./scripts/diagnose-vpn-stack.sh > /tmp/vpn-diagnosis.json

Скрипт снимает фактическое состояние через api_get_xray_config/api_list_inbounds (read-only) и сверяет с эталоном. Выдаёт JSON + человеко-читаемую сводку с ✅/❌ по 6 пунктам:

  1. Вход для устройств — VLESS inbound есть? сколько клиентов?
  2. Выход — upstream outbound есть? сколько?
  3. Балансировщик — есть при нескольких outbound? стратегия leastPing? probeInterval?
  4. Гибкая маршрутизация — модель «золотая середина» (РФ→direct, реклама→block, default→upstream)?
  5. Локальный прокси — mixed inbound на 127.0.0.1?
  6. Маршрутизация прокси — правила для mixed-inbound есть?

⚠️ Скрипт видит только серверную половину. Если все шесть пунктов зелёные, а оператор всё равно жалуется «не работает» — отказ в клиентской половине (клиент не в TUN, не тот профиль, не обновилась подписка). Тогда идти по references/complaint-triage.md, а не повторять снимок.

Шаг 3: Показать диагноз оператору (сеньор-обёртка, раздел 4.3)

Перевести JSON-диагноз на человеческий язык. Пример:

Посмотрел твою панель. Вот что уже сделано и где пробелы:

✅ Вход для твоих устройств настроен (VLESS, 2 клиента) — подключаться можешь.
✅ Серверы выхода добавлены (3 сервера США).
❌ Балансировщик не собран — сейчас трафик идёт только на первый сервер,
   при его падении выхода не будет.
❌ Гибкая маршрутизация неполная — российские сайты идут через заграницу
   (медленно + риск бана аккаунтов). Реклама не режется.
❌ Локального прокси для программ на сервере нет.

Предлагаю всё это доделать. Объясню каждый шаг. Доводим?

Если все ✅ — сказать «система уже в идеальном состоянии» и перейти к Шагу 6 (финальный вердикт + smoke), ничего не меняя.

Шаг 4: План починки (Yellow Zone — брифинг перед изменениями)

По ❌-пунктам составить план, какими подчинёнными скиллами чинить. Брифинг 6 пунктов (как в /configure-vpn-routing Шаг 2): ЧТО делаю, ЗАЧЕМ, ЧТО произойдёт, ЧТО проверил, РИСК+ОТКАТ, СТРАХОВКА. Получить разрешение оператора.

Карта «дыра → чем чиню»:

❌ ДыраЧем закрываю
Нет/неполная гибкая маршрутизация, нет балансира, нет/мало outbound/configure-vpn-routing (идемпотентен — перезапишет routing к эталону, соберёт балансир, доведёт outbound). При отсутствии outbound — пройдёт диалог подписки/страны/пресета (его Шаг 5A)
Нет VLESS inbound для входа/configure-vpn-routing с INBOUND_ONLY-веткой (создаёт inbound)
Нет локального прокси / нет его маршрутизации/setup-server-proxy (mixed inbound + self-loop override + routing)

🧭 Я дирижёр, не дублёр. Я НЕ переписываю логику этих скиллов — я вызываю их в правильном порядке с нужными параметрами. Это гарантирует, что починка идёт по тому же проверенному эталону, что и настройка с нуля.

Шаг 5: Починка — прогон подчинённых скиллов

Порядок важен (зависимости): сначала вход и выход с маршрутизацией, потом прокси (он опирается на наличие upstream-outbound).

  1. Маршрутизация клиентов (если ❌ в пунктах 1–4): Запустить /configure-vpn-routing (см. его процедуру). Он идемпотентен: существующий inbound использует, routing перезаписывает к «золотой середине», при нескольких outbound собирает балансир leastPing с PROBE_INTERVAL=5m. Если outbound нет вовсе — он проведёт диалог подписки → страны → пресета.
  2. Локальный прокси (если пункт 5/6 ❌ И WANT_PROXY≠no): Спросить оператора (если WANT_PROXY=ask): «Нужен ли доступ к заблокированным API программам на самом сервере (боты, скрипты, npm/pip)? Это локальный прокси — программы ходят через тот же VPN, ничего в них настраивать не надо.» При yes — запустить /setup-server-proxy (он создаёт mixed inbound на 127.0.0.1 с понятной пометкой в панели, self-loop override, routing).

Каждый подчинённый скилл сам делает свой Yellow-брифинг и verify.

Шаг 6: Финальный повторный диагноз + вердикт

Повторно прогнать diagnose-vpn-stack.sh — убедиться, что ❌ закрыты.

═══ ВЕРДИКТ: система доведена до идеала ═══
✅ Вход для устройств (VLESS, N клиентов)
✅ Выход: M серверов (страна X), балансир leastPing, probeInterval=5m
✅ Гибкая маршрутизация «золотая середина» (7 правил)
✅ Локальный прокси для программ (127.0.0.1:1080)
✅ Маршрутизация прокси

🔍 Проверь сам:
  1. Подключись к серверу через Happ (конфиг — /generate-client-config).
  2. На 2ip.ru: российские сайты → твой РФ-IP, зарубежные → IP выхода (страна X).
  3. Реклама на страницах режется.

➡️  Следующий шаг (если ещё не сделан): /generate-client-config — конфиги/QR
    для твоих устройств.

Если какой-то ❌ оставлен осознанно (оператор отказался) — отразить в вердикте как «⚪ пропущено по решению оператора: <что и почему>», не выдавать за ✅.

Шаг 7: Обновление inventory

Дополнить $INFRA/inventory/hosts/$SERVER_ALIAS/networks.md итоговым состоянием VPN-стека (то же, что пишут подчинённые скиллы — если они уже записали, не дублировать; дописать только сводку «доведено finalize-vpn-routing <дата>»).

Откат

Сам скилл-дирижёр изменений не вносит — их вносят подчинённые скиллы, у каждого свой откат (бэкап xray-конфига до изменений в /configure-vpn-routing, systemd override-removal в /setup-server-proxy). При сбое на конкретном шаге — останавливаюсь и сообщаю, какой подчинённый скилл и где упал, не продолжаю вслепую.

Failed attempts (граблекейс)

  • Дублирование логики подчинённых скиллов — НЕ переписывать routing/inbound/ proxy-настройку внутри дирижёра. Только диагноз + вызов существующих скиллов. Иначе два источника правды разойдутся.
  • Чинить при недоступной панели — если панель не отвечает, проблема не в маршрутизации, а в сервере. Отправить на /health-check, не лезть в конфиг.
  • Выдавать пропущенное за сделанное — если оператор отказался от прокси, в вердикте это «⚪ пропущено», не «✅». Финальный диагноз показывает реальность.
  • Настройка с нуля под видом «доведения» — если стек пустой, честно сказать «настройки ещё нет, начнём с нуля» и пройти полный путь, а не делать вид, что «доводим».

Граничные случаи

  • Всё уже ✅ → ничего не менять, вердикт «идеал», перейти к smoke.
  • Балансир есть, но стратегия random/roundRobin → предупредить: это даёт «скачущий IP» (бан аккаунтов), предложить пересобрать на leastPing через /configure-vpn-routing. См. 3x-ui-panel.md §1.3.
  • probeInterval=1m/30s (дефолт 3X-UI, не 5m) → мягко предложить поднять до 5m для стабильности IP (через /configure-vpn-routing PROBE_INTERVAL=5m).
  • Оператор не хочет прокси → WANT_PROXY=no, пункт 5/6 в вердикте «⚪ не нужен».
  • outbound есть, но все из разных стран → предупредить про риск «прыжков», предложить выбрать одну страну (диалог в /configure-vpn-routing Шаг 5A).

Связанные документы

  • ../configure-vpn-routing/SKILL.md — настройка inbound/outbound/routing (чинит пункты 1–4).
  • ../setup-server-proxy/SKILL.md — локальный прокси для программ (чинит пункты 5–6).
  • ../health-check/SKILL.md — если проблема в сервере, не в маршрутизации.
  • scripts/diagnose-vpn-stack.sh — read-only снимок состояния VPN-стека.
  • references/complaint-triage.md — 15 вопросов триажа жалобы «не работает», от клиента к серверу. Читать, когда скрипт показал зелёный сервер, а у оператора не работает: скрипт покрывает только серверную половину стека.
  • ../../knowledge/networking/_reference/3x-ui-panel.md §1.3-1.4 — эталон балансира/observatory.
  • ../../knowledge/networking/_reference/routing-server-3xui.md — эталон «золотая середина».

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.