sh-xray — единый VPN-шлюз (skill-hub xray) для всех AI-навыков
Один общий SOCKS5-прокси (xray-core) с НЕ-российской нодой и smart-routing
(РУ/CN → напрямую, остальное → за рубеж). Пишет общий указатель
~/.xray-gate/state.json, который читают ВСЕ навыки (паттерн open_client._apply_proxy).
Системный трафик НЕ трогает (только opt-in инструменты через ALL_PROXY) — РУ-сервисы не ломаются.
Команды
CLI xray-gate — на clikit (даёт --json/--help/--version):
xray-gate install # xray binary + geoip/geosite (качает с GitHub-релиза XTLS/Xray-core)
xray-gate test # выбрать рабочую НЕ-RU ноду (проверка реального выхода через ipinfo.io)
xray-gate start [--port N] # поднять + записать ~/.xray-gate/state.json (порт по умолч. 10810)
xray-gate status # alive + live exit country
xray-gate stop
xray-gate ensure # self-heal: поднять, если процесс умер (после reboot/краша)
xray-gate onboard # детект окружения (прокси/движки) + per-service карта routing.json
xray-gate ensure-reachable <service|--url URL> # оркестратор доступности (см. ниже); exit 0/3/1
xray-gate autostart # Windows Task Scheduler: ensure каждые 10 мин (переживает reboot)
xray-gate autostart --remove
xray-gate add-sub <url> # своя VLESS-подписка (vless/base64; авто-обновление по интервалу подписки)
Оркестратор доступности ensure_reachable (единая точка встраивания)
Одна функция вместо ручной цепочки probe→detect→byedpi→Gateway — для встраивания gate в КАЖДЫЙ сервис-навык на установке/старте. Проверяет доступность цели и эскалирует: существующий egress (системный прокси + скан локальных прокси-портов Hiddify/v2rayN/clash/…
- уже поднятые движки) → byedpi (РКН-DPI, sni-dpi) → xray-демон+подписка (гео/тупик).
from xray_gate import ensure_reachable
res = ensure_reachable("notebooklm") # или ensure_reachable(url="https://…/", ok_codes=(200,302))
if res.ok: proxy = res.proxy # None → напрямую; иначе socks5h/http
elif res.need_subscription: ... # агент просит подписку → xray-gate add-sub <url> (пакет НЕ падает)
else: ... # тупик: res.detail / res.tried
ReachResult: ok, engine ("local|direct|system|byedpi|xray"), proxy, bind,
exit_country (ЗАМЕРЕННАЯ страна выхода), need_subscription, block_kind, detail,
tried (лог попыток). Предикаты has_subscription() /
subscription_configured() — есть ли рабочая подписка/нода (вместо sys.exit). CLI:
xray-gate ensure-reachable <service|--url URL> [--no-byedpi] [--no-xray] (exit 0 — доступно,
3 — нужна подписка, 1 — тупик).
Без установки китов (свежая машина, handoff-бандл) — тот же набор через dep-free ядро:
python xray_gate/_core.py <команда> (чистый stdlib, никаких зависимостей). Именно его
дёргает watchdog (ensure каждые 10 мин), чтобы self-heal не зависел от китов.
Российский адрес для российских сервисов (движок local)
Слово «напрямую» раньше значило «мимо НАШЕГО прокси»: проба шла curl --noproxy "*".
Системный TUN-адаптер (Hiddify, Outline, WARP) заворачивает такой трафик маршрутами,
и --noproxy про него ничего не знает. Замер на машине владельца:
| канал | адрес | страна | оператор |
|---|---|---|---|
| direct (через TUN) | 212.34.142.82 |
NL | AS216071 SERVERS TECH FZCO |
| физический адаптер | 81.177.232.243 |
RU | AS48176 MTS PJSC |
То есть правило «RU-сервис ходит напрямую» не выполнялось вообще: VK, OK, Дзен, RuTube,
VC.ru видели голландский адрес — капча, internal-error, 401.
Обход без прав администратора, без правки маршрутов и без вмешательства в чужие процессы: исходящий сокет привязывается к адресу физического адаптера (Windows strong host model — маршрут туннеля к такому сокету неприменим). Наружу это отдано обычным proxy-URL, поэтому навыкам не нужна новая сантехника:
from xray_gate import ensure_reachable
res = ensure_reachable("vk")
res.engine # "local"
res.proxy # "socks5h://127.0.0.1:10812"
res.exit_country # "RU" — ЗАМЕРЕНО, а не настроено
Замерить все каналы разом: xray-gate egress [--up] → таблица «канал → адрес → страна»
(direct / физический / локальный прокси / шлюз). Снять: xray-gate egress-stop.
Переопределить адрес привязки: XRAY_GATE_BIND_IP=<ip>.
РУ-плечо smart-routing самого шлюза и пула (РУ/CN → direct) тоже привязано — раньше его
direct уходил в тот же туннель.
Построен на Китах (S-kits)
sh-xray — НЕ кит, а супернавык/сервис, который строится на китах:
clikit даёт человеческий CLI (xray_gate/cli.py), librarykit.config_util — атомарную
запись общих указателей (~/.xray-gate/state.json, ~/.xray-gate/routing.json). Ядро-движок
(xray_gate/_core.py, бывший top-level gateway.py) намеренно остаётся на чистом stdlib —
у обоих kit-обращений есть stdlib-фолбэк, поэтому self-heal работает даже без китов.
gateway-роутер потребляет egress sh-xray через свой ProxyProvider (читает ~/.xray-gate/state.json).
Переживает перезагрузку
autostart ставит задачу планировщика (ensure каждые 10 мин, StartWhenAvailable). После reboot
старый pid мёртв → ensure поднимает xray заново (при старте/в течение ~10 мин). ~/.xray-gate/state.json
обновляется новым pid, все навыки снова ходят через прокси. Без autostart — поднимать вручную start.
Общий указатель ~/.xray-gate/state.json
{"http_proxy": "http://127.0.0.1:10811", "all_proxy": "socks5h://127.0.0.1:10810", "node": "...", "backend": "xray-gate"}
Потребители читают его и ходят через ОДИН egress (важно: один IP для логина И API, иначе Google убивает сессию).
Всё хозяйство рантайма — под ~/.xray-gate/ (state.json/routing.json/byedpi/zapret/бинарь).
Потребление в проектах (egress «из коробки»)
xray-gate — источник пути (его знает он, не нейтральный librarykit-корень). Потребитель ставит его как egress-расширение и берёт прокси у его адаптеров. Установка (на PyPI НЕТ — из git):
uv add --optional egress "s-xray-gate @ git+https://gitlab.com/s-skills/s-xray-gate.git" # запишет в pyproject+lock
uv sync --extra egress # или: pip install git+https://gitlab.com/s-skills/s-xray-gate.git
4 способа взять прокси (нет указателя/шлюз не поднят → None → проект идёт напрямую):
import xray_gate.adapters as eg
httpx.Client(proxy=eg.httpx_proxy()) # socks5h://127.0.0.1:10810
sess = eg.requests_session() # requests.Session с прокси
browser.launch(proxy=eg.playwright_proxy()) # {"server":"socks5://..."}
TelegramClient(s, api_id, api_hash, proxy=eg.telethon_proxy())
# через нейтральный librarykit-транспорт (проект на китах):
from librarykit import HttpClient, HttpxTransport
HttpClient(HttpxTransport(proxy=eg.httpx_proxy()), auth, errmap)
# env-wide (subprocess/curl/любой ALL_PROXY-клиент):
from xray_gate import apply_to_env; apply_to_env("notebooklm") # по карте ~/.xray-gate/routing.json
# zero-dep (без установки пакета — просто JSON):
import json, pathlib
proxy = json.loads((pathlib.Path.home()/".xray-gate"/"state.json").read_text())["all_proxy"]
Реальный пример-потребитель — bublictr (adapters/_common/browser.py): BUBLICTR_BROWSER_PROXY=shxray
→ xray_gate.adapters.playwright_proxy().
Портативность / другие устройства
install качает xray-core сам. add-sub <url> + test подберёт не-RU ноду. Так работает на любой машине/агенте.
Замечание по нодам
Качество зависит от подписки. Нестабильная нода → таймауты (xray ретраит, но лучше иметь несколько не-RU нод).
status показывает live exit; test перевыбирает рабочую.
Metadata
Release files for s-xray-gate 0.3.6
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| s_xray_gate-0.3.6.tar.gz | 116.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| s_xray_gate-0.3.6-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 215.3 kB
Release files / s_xray_gate-0.3.6.tar.gz
| Download URL | s_xray_gate-0.3.6.tar.gz |
|---|---|
| Size | 116.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
b348f6378a009214b690ffcc67ff87142b0adc9d032b8a0f10920ff156c94333
|
|
BLAKE2b-256 checksum How to use checksums |
78d10641ecccf2e5300951d1454f0ce4ca4b08c91e70f61d2868f75e6ed0d5f6
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.26 {"installer":{"name":"uv","version":"0.11.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / s_xray_gate-0.3.6-py3-none-any.whl
| Download URL | s_xray_gate-0.3.6-py3-none-any.whl |
|---|---|
| Size | 99.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
eb71953896c0b2afe6e13ab363a72d11033ae0848dc3ff296606b263b32c5916
|
|
BLAKE2b-256 checksum How to use checksums |
151252fb9b4293c86a24105c63bfd3535d9b7e59994b9d7623fbc2725656dec8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.11.26 {"installer":{"name":"uv","version":"0.11.26","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|