# proxy-client `proxy-client` — переносимый Linux/Bash-интерфейс для запуска команд через внешний прокси или через управляемый пользовательский Xray. Он добавляет команды `proxy_on`, `proxy_off`, `pclaude` и `pcodex`, но не подменяет обычные `claude` и `codex`. CLI требует Python 3.8+ и использует только стандартную библиотеку. Он не запускает Xray и не переключает режим прокси без явной команды пользователя. ## Установка ### В составе dotfiles Полная установка подключает пакет и автоматически загружает Bash-функции в новых интерактивных сессиях: ```bash cd ~/dotfiles ./install.sh ``` Установщик заранее создаёт `~/.local/bin` и `~/.config/proxy-client`, чтобы Stow размещал ссылки внутри них, а не превращал сами каталоги в ссылки на репозиторий. После установки откройте новый Bash или выполните: ```bash source ~/.bash_custom ``` ### Только пакет `proxy-client` ```bash cd ~/dotfiles mkdir -p ~/.local/bin ~/.config/proxy-client stow proxy-client source ~/.config/proxy-client/shell.bash ``` Если Bash-пакет dotfiles не установлен, добавьте подключение модуля в `~/.bashrc`: ```bash printf '%s\n' 'source ~/.config/proxy-client/shell.bash' >> ~/.bashrc ``` ## Как выбирается прокси Режим определяется только машинным файлом `~/.config/proxy-client/config`: | Машинный конфиг | Используется | Что запускать | |-----------------|-------------|---------------| | Файла нет | Hiddify на `hproxy.local:12334` | Ничего | | `type = external` | Указанный внешний прокси | Ничего | | `type = xray` | Управляемый локальный Xray | `proxy-client start` | Доступность процесса не меняет выбранный режим. Если в конфиге указан Xray, но он не запущен, `status`, `env`, `run`, `proxy_on`, `pclaude` и `pcodex` завершатся с ошибкой. Автоматического перехода на Hiddify или другой прокси нет. Текущий выбор и доступность проверяет команда: ```bash proxy-client status ``` ## Настройка режима ### Hiddify в Windows, команды в WSL Это режим по умолчанию. Если Hiddify доступен из WSL как `hproxy.local:12334`, создавать `config` не нужно: ```bash getent hosts hproxy.local proxy-client status pclaude --version ``` В WSL NAT mode IP Windows-шлюза меняется при перезапуске. Интерактивный `./install.sh` предлагает добавить обновление `hproxy.local` в `/etc/wsl.conf`. То же можно настроить вручную: ```ini [boot] command = "/path/to/dotfiles/scripts/setup-hproxy.sh" ``` После изменения выполните `wsl --shutdown` из Windows. Обновить адрес без перезапуска WSL можно так: ```bash sudo ~/dotfiles/scripts/setup-hproxy.sh # или после загрузки Bash-функций: update_hproxy ``` В NAT mode Hiddify должен слушать адрес, доступный через Windows-шлюз, а не только `127.0.0.1`. В [WSL mirrored mode](https://learn.microsoft.com/windows/wsl/networking#mirrored-mode-networking) (`networkingMode=mirrored`) Windows-сервисы доступны из WSL через `127.0.0.1`. Чтобы сохранить адрес по умолчанию, добавьте алиас в Windows hosts: ```text # C:\Windows\System32\drivers\etc\hosts 127.0.0.1 hproxy.local ``` Альтернатива — создать `config.external` с `address = 127.0.0.1`. В обоих случаях проверьте результат через `getent hosts hproxy.local` или `proxy-client status`. ### Другой внешний прокси Скопируйте пример и измените адрес, порт и локальные исключения: ```bash cp ~/.config/proxy-client/examples/config.external \ ~/.config/proxy-client/config ``` ```ini [proxy] type = external name = Office proxy address = proxy.example.internal port = 12334 no_proxy_extra = .example.internal,git.example.internal ``` Для внешнего прокси на той же Linux-машине можно указать `127.0.0.1` напрямую. ### Локальный Xray Создайте машинный конфиг: ```bash cp ~/.config/proxy-client/examples/config.xray \ ~/.config/proxy-client/config ``` Закрытый профиль должен содержать ровно одну VLESS-ссылку: ```bash cp ~/.config/proxy-client/examples/default.url \ ~/.config/proxy-client/default.url $EDITOR ~/.config/proxy-client/default.url chmod 600 ~/.config/proxy-client/default.url ``` Установите проверенную версию Xray без root: ```bash proxy-client install ``` Запустите Xray в отдельной панели tmux: ```bash proxy-client start ``` Другой закрытый профиль можно выбрать без замены `default.url`: ```bash proxy-client start -f ~/.config/proxy-client/work.url ``` Для переключения профиля сначала выполните `proxy-client stop`. Все файлы с настоящими VLESS-ссылками должны иметь права `600` и не должны попадать в Git. ## Ежедневное использование | Задача | Команда | Область действия | |--------|---------|------------------| | Запустить Claude через прокси | `pclaude [ARG...]` | Только дочерний процесс | | Запустить Codex через прокси | `pcodex [ARG...]` | Только дочерний процесс | | Запустить другую команду | `proxy-client run -- COMMAND ARG...` | Только дочерний процесс | | Включить прокси | `proxy_on` | Текущая Bash-сессия | | Выключить прокси | `proxy_off` | Текущая Bash-сессия | | Проверить прокси | `proxy-client status` | Без изменения окружения | | Получить proxy-переменные | `proxy-client env` | Машинный вывод в stdout | | Показать внешний IP | `myip` | С учётом текущего окружения | `run`, `pclaude` и `pcodex` передают дочернему процессу восемь вариантов `HTTP_PROXY`, `HTTPS_PROXY`, `ALL_PROXY` и `NO_PROXY`, включая имена в нижнем регистре. После завершения команды переменные не остаются в оболочке. `proxy_on` применяет те же переменные к текущей Bash-сессии только после успешной проверки прокси. `proxy_off` удаляет их. Обычные `claude` и `codex` не обёрнуты и не выполняют предварительную проверку, но после `proxy_on` наследуют прокси-переменные, как и любой другой дочерний процесс. ### Жизненный цикл Xray ```bash proxy-client install [--replace] proxy-client start [-f PROFILE] proxy-client status proxy-client stop ``` `start` сначала проверяет версию и конфигурацию Xray, затем остаётся на переднем плане. Systemd, фоновый автозапуск и скрытый запуск из `run` не используются. Один loopback-порт принимает HTTP CONNECT и SOCKS5. `stop` завершает управляемые процессы и удаляет созданные служебные файлы. Он работает и после изменения машинного типа на `external`. ## Диагностика Начните с проверки выбранного режима: ```bash proxy-client status ``` Для внешнего Hiddify в WSL проверьте имя и порт: ```bash getent hosts hproxy.local curl --proxy http://hproxy.local:12334 https://example.com curl --proxy socks5h://hproxy.local:12334 https://example.com ``` Для запущенного Xray можно дополнительно проверить созданный JSON: ```bash xray run -test -c \ "${XDG_STATE_HOME:-$HOME/.local/state}/proxy-client/client.json" ``` Если выбран `type = xray`, но процесс не запущен, запустите его отдельно — `proxy_on` и `run` этого не делают. Профиль XHTTP с ALPN `h3` требует доступного UDP-маршрута до сервера; автоматического перехода на H2 нет. Таймаут предварительной проверки по умолчанию равен двум секундам. Его можно изменить положительным числом: ```bash export PROXY_PREFLIGHT_TIMEOUT=5 ``` ## Справочник ### Ручное подключение без Stow Можно создать ссылки на CLI, Bash-модуль и примеры либо скопировать те же файлы: ```bash mkdir -p ~/.local/bin ~/.config/proxy-client ln -s /path/to/proxy-client/.local/bin/proxy-client ~/.local/bin/proxy-client ln -s /path/to/proxy-client/.config/proxy-client/shell.bash \ ~/.config/proxy-client/shell.bash ln -s /path/to/proxy-client/.config/proxy-client/examples \ ~/.config/proxy-client/examples ``` Исполняемому файлу нужен режим `755`, а `~/.local/bin` должен входить в `PATH`. ### Машинный конфиг Формат строгий: одна секция `[proxy]` и пять обязательных ключей без повторов и неизвестных полей: - `type` — `external` или `xray`; - `name` — имя для диагностики; - `address` — IPv4, IPv6 без квадратных скобок или ASCII DNS-имя без схемы и порта; - `port` — TCP-порт локального входа; - `no_proxy_extra` — дополнительные IP и домены через запятую, значение может быть пустым. Поддержка CIDR в `NO_PROXY` различается между программами, поэтому надёжнее указывать точные IP и домены. Без машинного файла внешний режим дополнительно включает `.concept-software.ru` в `NO_PROXY`. Для `type = xray` адрес обязан быть адресом обратной петли, например `127.0.0.1` или `::1`. ### Поддерживаемые профили Поддерживаются VLESS TCP/RAW с REALITY и VLESS XHTTP с TLS. Неизвестные, повторные и несовместимые query-параметры отклоняются. XHTTP поддерживает ALPN `http/1.1`, `h2` и `h3`; `extra` должен быть JSON-объектом без повторных ключей. Xray 26.3.27 использует `pcs` и `vcn`, а устаревшие `allowInsecure` и `insecure` не переносит. Истинное legacy-значение даёт предупреждение, но обычная проверка сертификата остаётся включённой. Последняя версия Xray, где `allowInsecure` ещё применяется, — [25.12.8](https://github.com/XTLS/Xray-core/releases/tag/v25.12.8); опция удалена в [26.2.6](https://github.com/XTLS/Xray-core/releases/tag/v26.2.6). `proxy-client` эти версии не поддерживает и не устанавливает. ### Проверяемая установка Xray `proxy-client install` устанавливает Xray 26.3.27 в `~/.local/bin/xray`. Для `x86_64`/`amd64` используется `Xray-linux-64.zip`, для `aarch64`/`arm64` — `Xray-linux-arm64-v8a.zip`; остальные архитектуры отклоняются. CLI скачивает официальный архив и файл `.dgst`, проверяет SHA-256, ограничения размера и фактическую версию бинарника, а затем атомарно заменяет назначение. Корректная уже установленная версия даёт no-op без сети. Другой файл или симлинк не заменяется без `--replace`; каталог не заменяется никогда. `start` использует первый `xray` из `PATH` и принимает только версию 26.3.27. Если `PATH` выбирает другой бинарник, команда сообщает об ошибке. Во время живого или неподтверждённого управляемого процесса установка запрещена. ### Файлы и безопасность | Путь | Назначение | |------|------------| | `~/.config/proxy-client/config` | Несекретный машинный выбор режима | | `~/.config/proxy-client/default.url` | Закрытая VLESS-ссылка, права `600` | | `~/.config/proxy-client/examples/` | Синтетические примеры без секретов | | `$XDG_STATE_HOME/proxy-client/` или `~/.local/state/proxy-client/` | Состояние и сгенерированный JSON | Сводка скрывает UUID и ключи, а для XHTTP показывает только длину `path`. Служебный каталог закрыт для других пользователей и очищается после штатной остановки Xray. Сбой определения внешнего IP показывается как предупреждение и не останавливает уже готовый процесс.