From 9c2e134fc19eed1322fb461bd5c48b0407deaa89 Mon Sep 17 00:00:00 2001 From: Dmitry Dementev Date: Tue, 21 Jul 2026 11:15:27 -0400 Subject: [PATCH] =?UTF-8?q?fix(install):=20=D0=BF=D1=80=D0=B5=D0=B4=D0=BE?= =?UTF-8?q?=D1=82=D0=B2=D1=80=D0=B0=D1=89=D0=B5=D0=BD=D0=BE=20=D1=81=D0=B2?= =?UTF-8?q?=D0=BE=D1=80=D0=B0=D1=87=D0=B8=D0=B2=D0=B0=D0=BD=D0=B8=D0=B5=20?= =?UTF-8?q?=D0=BA=D0=B0=D1=82=D0=B0=D0=BB=D0=BE=D0=B3=D0=B0=20.local?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Зачем: - свежая установка могла превратить ~/.local в ссылку на пакет и записать Xray в репозиторий. - Что: - перед Stow теперь гарантируются настоящие ~/.local/bin и ~/.config/proxy-client без раскрытия посторонних ссылок. - добавлены регрессионные проверки свежего HOME и посторонней ссылки ~/.local. - README перестроены вокруг установки, выбора режима и ежедневного использования. - Проверка: - bash tests/test_install.sh. - bash tests/test_proxy_launchers.sh. - bash -n install.sh tests/test_install.sh. - git diff --cached --check. --- ...21-0743-proxy-client-05-ready-for-human.md | 14 +- README.md | 67 +-- install.sh | 8 + proxy-client/README.md | 426 ++++++++++++------ tests/test_install.sh | 27 ++ 5 files changed, 341 insertions(+), 201 deletions(-) diff --git a/.scratch/handoffs/20260721-0743-proxy-client-05-ready-for-human.md b/.scratch/handoffs/20260721-0743-proxy-client-05-ready-for-human.md index 865b97a..5eb67d1 100644 --- a/.scratch/handoffs/20260721-0743-proxy-client-05-ready-for-human.md +++ b/.scratch/handoffs/20260721-0743-proxy-client-05-ready-for-human.md @@ -1,6 +1,6 @@ # Handoff: `proxy-client` переименован, Ubuntu-приёмка пройдена -Обновлён: 2026-07-21 10:08 EDT. +Обновлён: 2026-07-21 11:13 EDT. ## Состояние задачи 05 @@ -79,6 +79,14 @@ CONNECT- и SOCKS5h-соединений без ошибок; две однов 200. Известный сбой первых соединений из XTLS/Xray-core#3673 не воспроизвёлся. Это не заменяет длительное наблюдение под обычной нагрузкой. +## Документация и установка + +Корневой README сокращён до обзора, а `proxy-client/README.md` перестроен по +пути читателя: установка, выбор режима, настройка, ежедневная работа, +диагностика и справочник. Установщик заранее создаёт настоящие `~/.local/bin` и +`~/.config/proxy-client`, чтобы Stow не сворачивал изменяемые каталоги в ссылки +на репозиторий. Это покрыто свежим HOME и посторонней ссылкой `~/.local`. + ## Следующий шаг Решить, обязательна ли ручная проверка на доступной системе из семейства РЕД ОС, @@ -87,6 +95,6 @@ Astra Linux или Alt Linux. Если нет, привести статус и ## Git -Переименование зафиксировано коммитом `6e431d8`. Обновления тикета и handoff после -успешной H3-приёмки ещё не закоммичены. Не включать посторонние неотслеживаемые +Переименование зафиксировано коммитом `6e431d8`, успешная H3-приёмка — +`bca90c1`. Не включать посторонние неотслеживаемые `agents/.agents/.skill-lock.json` и `scripts/setup-xray-proxy.sh`. diff --git a/README.md b/README.md index 6cfee0b..e136d18 100644 --- a/README.md +++ b/README.md @@ -97,67 +97,14 @@ export ZAI_API_KEY="..." # https://z.ai ### Прокси (`proxy-client`) -Linux/Bash-команды `proxy_on/off`, `pclaude`, `pcodex` и `myip` находятся в -самостоятельном пакете [`proxy-client`](proxy-client/README.md). Он поддерживает -явно выбранный внешний Hiddify или управляемый пользовательский Xray 26.3.27 с -профилями VLESS TCP/RAW + REALITY и XHTTP + TLS. Для отдельного подключения -сначала выполните `mkdir -p ~/.config/proxy-client`, затем -`stow proxy-client`. Команды `proxy-client install/start/stop/status` -работают без systemd, автозапуска и автоматического перехода между прокси. Без -конфига сохраняется внешний Hiddify `hproxy.local:12334`. +Linux/Bash-интерфейс `proxy-client` поддерживает внешний прокси и управляемый +пользовательский Xray. Без машинного конфига используется прежний Hiddify на +`hproxy.local:12334`; автоматического запуска Xray и переключения между режимами +нет. -Имя `hproxy.local` — прежний алиас хоста с внешним прокси. Windows и VS Code -Server продолжают использовать его напрямую. - -**Порты:** HTTP/HTTPS — `hproxy.local:12334`, SOCKS5 — `socks5://hproxy.local:12334`. - -**WSL NAT mode** (IP шлюза меняется при каждом запуске): - -```bash -# Через install.sh (интерактивно, ответить "y" на вопрос про wsl.conf) -./install.sh - -# Или вручную: -sudo tee -a /etc/wsl.conf <<'EOF' - -[boot] -command = "/path/to/dotfiles/scripts/setup-hproxy.sh" -EOF -``` - -После изменения `wsl.conf` — `wsl --shutdown`. Обновить без перезапуска: `sudo scripts/setup-hproxy.sh` или `update_hproxy`. - -**WSL mirrored mode** (`networkingMode=mirrored`) — имя резолвится из WSL через DNS/hosts хоста. Достаточно записи на стороне Windows: - -``` -# C:\Windows\System32\drivers\etc\hosts -192.168.1.100 hproxy.local -``` - -Проверка: `getent hosts hproxy.local` (запись в Linux `/etc/hosts` не обязательна). - -**Native Linux** — прокси на localhost, нужна запись в `/etc/hosts`: - -```bash -echo '127.0.0.1 hproxy.local' | sudo tee -a /etc/hosts -``` - -**VS Code Server** — `vscode/.vscode-server/server-env-setup` автоматически подхватывает `hproxy.local` и выставляет все proxy-переменные (HTTP_PROXY, HTTPS_PROXY, ALL_PROXY, NO_PROXY и lowercase-варианты). Если `hproxy.local` не резолвится — прокси не включается, запуск не блокируется. - -**Windows pwsh** — `proxy_on` / `proxy_off` / `myip` работают аналогично bash-версиям. - -**`pclaude` / `pcodex`** — явный запуск Claude/Codex CLI через прокси (bash и pwsh). Bash-версия делегирует проверку и запуск `proxy-client run`; Windows-версия сохраняет прежний адрес `hproxy.local:12334`. Таймаут — `PROXY_PREFLIGHT_TIMEOUT`, по умолчанию 2 c. Если прокси недоступен, клиент не запускается. Proxy-переменные видны только дочернему процессу и не остаются в сессии. Голые `claude`/`codex` не перекрываются и идут напрямую — для прокси нужен явный `p`-префикс. - -**Codex GUI на Windows** — chezmoi создает Start Menu ярлык `Codex Proxy`, который запускает Codex Windows App с proxy-переменными: - -```powershell -HTTP_PROXY=http://hproxy.local:12334 -HTTPS_PROXY=http://hproxy.local:12334 -ALL_PROXY=socks5://hproxy.local:12334 -NO_PROXY=hproxy.local,localhost,127.0.0.1,::1,[::1],.concept-software.ru -``` - -Ярлык вызывает `~/.local/bin/start-codex-proxy.ps1`. Скрипт также добавляет эти переменные в `WSLENV` с флагом `/u`: это штатный мост Windows → WSL, чтобы дочерние WSL-сессии, запущенные из Codex GUI, получили тот же proxy environment. +[Установка, выбор режима, WSL и ежедневное использование](proxy-client/README.md) +описаны рядом с пакетом. Windows PowerShell и ярлык `Codex Proxy` сохраняют +прежнюю интеграцию с `hproxy.local:12334`. ### Git baseline diff --git a/install.sh b/install.sh index 2168346..770e2b7 100755 --- a/install.sh +++ b/install.sh @@ -317,6 +317,14 @@ done migrate_zed_config_stow_symlink +if [ ! -L "$HOME/.local" ]; then + mkdir -p "$HOME/.local" +fi +if [ -d "$HOME/.local" ] && [ ! -L "$HOME/.local" ] \ + && [ ! -L "$HOME/.local/bin" ]; then + mkdir -p "$HOME/.local/bin" +fi + if [ ! -L "$HOME/.config" ]; then mkdir -p "$HOME/.config" fi diff --git a/proxy-client/README.md b/proxy-client/README.md index f29b9a7..6c26514 100644 --- a/proxy-client/README.md +++ b/proxy-client/README.md @@ -1,175 +1,325 @@ # proxy-client -Переносимый Linux/Bash-интерфейс для безопасного запуска команд через явно -настроенный внешний прокси или через управляемый пользовательский Xray. +`proxy-client` — переносимый Linux/Bash-интерфейс для запуска команд через +внешний прокси или через управляемый пользовательский Xray. Он добавляет команды +`proxy_on`, `proxy_off`, `pclaude` и `pcodex`, но не подменяет обычные `claude` +и `codex`. -CLI требует Python 3.8+ и использует только стандартную библиотеку. Он ничего не -устанавливает и не запускает без явной подкоманды. `start` использует первый -`xray` из `PATH`; скачивания и установки при запуске нет. +CLI требует Python 3.8+ и использует только стандартную библиотеку. Он не +запускает Xray и не переключает режим прокси без явной команды пользователя. -## Подключение +## Установка -В составе dotfiles: +### В составе dotfiles + +Полная установка подключает пакет и автоматически загружает Bash-функции в +новых интерактивных сессиях: ```bash cd ~/dotfiles -mkdir -p ~/.config/proxy-client +./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 ``` -Полный `./install.sh` выполняет тот же `stow` вместе с остальными пакетами, а -`.bash_custom` подключает модуль автоматически. +Если Bash-пакет dotfiles не установлен, добавьте подключение модуля в +`~/.bashrc`: -Без остальных dotfiles можно создать две ссылки: +```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 -printf '%s\n' 'source ~/.config/proxy-client/shell.bash' >> ~/.bashrc +ln -s /path/to/proxy-client/.config/proxy-client/examples \ + ~/.config/proxy-client/examples ``` -Вместо ссылок файлы можно скопировать в те же пути. Исполняемому файлу нужен -режим `chmod 755`. Каталог `~/.local/bin` должен входить в `PATH`. +Исполняемому файлу нужен режим `755`, а `~/.local/bin` должен входить в `PATH`. -## Машинный конфиг +### Машинный конфиг -Скопируйте пример нужного режима и отредактируйте его: +Формат строгий: одна секция `[proxy]` и пять обязательных ключей без повторов и +неизвестных полей: -```bash -mkdir -p ~/.config/proxy-client -cp ~/.config/proxy-client/examples/config.xray ~/.config/proxy-client/config -# или для внешнего Hiddify: -cp ~/.config/proxy-client/examples/config.external ~/.config/proxy-client/config -``` +- `type` — `external` или `xray`; +- `name` — имя для диагностики; +- `address` — IPv4, IPv6 без квадратных скобок или ASCII DNS-имя без схемы и + порта; +- `port` — TCP-порт локального входа; +- `no_proxy_extra` — дополнительные IP и домены через запятую, значение может + быть пустым. -Формат строгий: одна секция `[proxy]`, пять обязательных ключей без повторов и -неизвестных полей. - -```ini -[proxy] -type = external -name = Hiddify -address = hproxy.local -port = 12334 -no_proxy_extra = .example.internal,git.example.internal -``` - -`address` — IPv4, IPv6 без квадратных скобок или ASCII DNS-имя без схемы и -порта. `no_proxy_extra` — список через запятую; значение может быть пустым. Поддержка CIDR в `NO_PROXY` различается между программами, поэтому надёжнее -указывать точные IP и домены. +указывать точные IP и домены. Без машинного файла внешний режим дополнительно +включает `.concept-software.ru` в `NO_PROXY`. Для `type = xray` адрес обязан +быть адресом обратной петли, например `127.0.0.1` или `::1`. -Если файла нет, используется прежний внешний Hiddify на -`hproxy.local:12334`, включая `.concept-software.ru` в `NO_PROXY`. Это не -переключает тип прокси автоматически. +### Поддерживаемые профили -Для управляемого Xray задайте явный тип, loopback IP и нужный локальный порт: - -```ini -[proxy] -type = xray -name = Local Xray -address = 127.0.0.1 -port = 12334 -no_proxy_extra = .example.internal,git.example.internal -``` - -Секретный профиль хранится отдельно. Скопируйте синтетический пример, замените -его одной настоящей VLESS-ссылкой и закройте права конечного файла: - -```bash -cp ~/.config/proxy-client/examples/default.url ~/.config/proxy-client/default.url -chmod 600 ~/.config/proxy-client/default.url -``` - -Файл должен содержать ровно одну непустую строку. Можно передать другой файл -через `proxy-client start -f /path/to/profile.url`. Если это симлинк, проверяются -права конечного файла. - -## Команды - -```bash -proxy-client install [--replace] -proxy-client status -proxy-client start [-f PROFILE] -proxy-client stop -proxy-client env -proxy-client run -- COMMAND ARG... -proxy_on -proxy_off -pclaude [ARG...] -pcodex [ARG...] -myip -``` - -`install` без root устанавливает единственную поддержанную версию Xray -`26.3.27` в `~/.local/bin/xray`. Для `x86_64`/`amd64` используется официальный -`Xray-linux-64.zip`, для `aarch64`/`arm64` — `Xray-linux-arm64-v8a.zip`. -Остальные архитектуры отклоняются. CLI скачивает рядом файл `.dgst`, проверяет -единственную запись `SHA2-256= <64 lowercase hex>` в официальном -четырёхстрочном формате, извлекает `xray` в закрытый временный каталог внутри -`~/.local/bin`, проверяет `xray version` и только затем атомарно меняет -назначение. Дубликаты, uppercase, пропущенные и лишние записи отклоняются. -Архив и извлечённый бинарник ограничены 64 MiB, `.dgst` — 4 KiB; объявленный -`Content-Length` должен точно совпадать с фактически прочитанным размером. - -Существующая корректная версия `26.3.27` даёт успешный no-op без сети. Другой, -битый, неисполняемый файл или симлинк не заменяется без `--replace`; каталог не -заменяется никогда. Если после установки `PATH` выбирает не этот файл, команда -завершается с ошибкой и предлагает поставить `~/.local/bin` в начало `PATH`, -но проверенная установка сохраняется. Родительский симлинк принимается, только -если разрешённый каталог остаётся внутри `HOME`. Во время живого или -неподтверждённого managed-экземпляра установка запрещена: сначала выполните -`proxy-client stop`. - -Для `external` команды `status`, `env` и `run` проверяют настроенный адрес и -порт. Для `xray` они дополнительно требуют закрытое состояние именно того -супервизора и дочернего Xray, который запустил CLI. Один открытый порт или чужой -PID не принимается. `run` никогда не запускает Xray скрыто. - -`start` поддерживает только Xray `26.3.27`, сначала выполняет -`xray version` и `xray run -test`, затем остаётся на переднем плане. Используйте -отдельную панель tmux. После готовности один loopback-порт принимает HTTP и -SOCKS. `stop` ограниченно ждёт завершения супервизора и Xray, очищает служебные -файлы и возвращает исходный `start` в терминал. Команда `stop` работает и после -явного переключения машинного типа на `external`. CLI не создаёт systemd-службу, -не запускает Xray автоматически и не переключается между типами прокси. - -`run` передаёт восемь proxy-переменных только дочернему процессу и сохраняет -аргументы и код возврата. `proxy_on` атомарно применяет те же восемь переменных -к текущей Bash-сессии; `proxy_off` удаляет их. - -Таймаут проверки задаётся положительным числом секунд: - -```bash -export PROXY_PREFLIGHT_TIMEOUT=2 -``` - -Значение по умолчанию — 2 секунды. `env` при успехе печатает только восемь строк -`KEY=value`; для обычной диагностики используйте `status` или `myip`. - -## Поддерживаемые профили - -Поддерживаются только VLESS TCP/RAW с REALITY и VLESS XHTTP с TLS. Неизвестные, +Поддерживаются 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` ещё применяется, — +Последняя версия 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). -CLI такие версии не поддерживает и не устанавливает. +`proxy-client` эти версии не поддерживает и не устанавливает. -Сводка скрывает UUID и ключи. Содержимое XHTTP `path` не показывается — только -его длина. Сгенерированный JSON и состояние лежат в закрытом каталоге -`$XDG_STATE_HOME/proxy-client` либо `~/.local/state/proxy-client` и удаляются после -штатной остановки. Сбой диагностики внешнего IP через локальный HTTP-прокси -показывается как предупреждение и не останавливает уже готовый Xray. +### Проверяемая установка 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 показывается как предупреждение и +не останавливает уже готовый процесс. diff --git a/tests/test_install.sh b/tests/test_install.sh index 2f3250e..c412699 100755 --- a/tests/test_install.sh +++ b/tests/test_install.sh @@ -97,6 +97,10 @@ test_fresh_install_uses_home_target() { run_install "$repo_root" "$home_dir" env WSL_DISTRO_NAME= INSTALL_INTERACTIVE_MODE=never >"$fixture/install.out" [ -L "$home_dir/.bash_custom" ] || fail "Expected .bash_custom symlink in HOME" + [ -d "$home_dir/.local" ] || fail "Expected ~/.local directory" + [ ! -L "$home_dir/.local" ] || fail "Expected ~/.local to stay a real directory" + [ -d "$home_dir/.local/bin" ] || fail "Expected ~/.local/bin directory" + [ ! -L "$home_dir/.local/bin" ] || fail "Expected ~/.local/bin to stay a real directory" [ -x "$home_dir/.local/bin/proxy-client" ] || fail "Expected executable proxy-client CLI in HOME" [ -d "$home_dir/.config/proxy-client" ] || fail "Expected proxy-client config directory" [ ! -L "$home_dir/.config/proxy-client" ] || fail "Expected proxy-client config to stay outside the repository" @@ -221,6 +225,28 @@ test_does_not_migrate_unrelated_config_symlink() { assert_not_exists "$unrelated_config/proxy-client" } +test_does_not_follow_unrelated_local_symlink() { + local fixture repo_root home_dir unrelated_local target expected + fixture="$(setup_fixture)" + repo_root="$fixture/repo" + home_dir="$fixture/home" + unrelated_local="$fixture/unrelated-local" + mkdir -p "$home_dir" "$unrelated_local" + printf '%s\n' 'keep me' > "$unrelated_local/local.conf" + ln -s "$unrelated_local" "$home_dir/.local" + + # Установщик не должен создавать bin через произвольную ссылку ~/.local. + run_install "$repo_root" "$home_dir" \ + env WSL_DISTRO_NAME= INSTALL_INTERACTIVE_MODE=never >"$fixture/install.out" 2>&1 || true + + [ -L "$home_dir/.local" ] || fail "Expected unrelated ~/.local symlink to be preserved" + target="$(readlink -f "$home_dir/.local")" + expected="$(readlink -f "$unrelated_local")" + [ "$target" = "$expected" ] || fail "Unrelated ~/.local target changed" + assert_file_contains "$unrelated_local/local.conf" "keep me" + assert_not_exists "$unrelated_local/bin" +} + test_settings_local_is_symlinked_to_repo() { local fixture repo_root home_dir fixture="$(setup_fixture)" @@ -505,6 +531,7 @@ main() { test_migrates_legacy_zed_config_symlink test_stops_legacy_migration_when_listing_fails test_does_not_migrate_unrelated_config_symlink + test_does_not_follow_unrelated_local_symlink test_settings_local_is_symlinked_to_repo test_settings_local_backup_on_existing_file test_settings_local_dir_is_skipped