fix(install): предотвращено сворачивание каталога .local
- Зачем: - свежая установка могла превратить ~/.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.
This commit is contained in:
1 parent
bca90c1d21
commit
9c2e134fc1
5 files changed
+341
-201
No files matched your search
@@ -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`.
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
+288
-138
@@ -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 показывается как предупреждение и
|
||||
не останавливает уже готовый процесс.
|
||||
@@ -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
|
||||
|
||||
Reference in new issue
Block a user