- Зачем: - требовалось подтвердить нижнюю версию Python и исключить переполнение /tmp тестовыми данными. - Что: - добавлен полный прогон под системным Python и CPython 3.8 через uv. - исправлены переносимость тестового Xray, уборка временных файлов и документация задачи 05. - добавлен список локальных навыков, исключаемых из Git. - Проверка: - bash tests/test_xray_proxy_full.sh.
173 lines
9.8 KiB
Markdown
173 lines
9.8 KiB
Markdown
# xray-proxy
|
||
|
||
Переносимый Linux/Bash-интерфейс для безопасного запуска команд через явно
|
||
настроенный внешний прокси или через управляемый пользовательский Xray.
|
||
|
||
CLI требует Python 3.8+ и использует только стандартную библиотеку. Он ничего не
|
||
устанавливает и не запускает без явной подкоманды. `start` использует первый
|
||
`xray` из `PATH`; скачивания и установки при запуске нет.
|
||
|
||
## Подключение
|
||
|
||
В составе dotfiles:
|
||
|
||
```bash
|
||
cd ~/dotfiles
|
||
stow xray-proxy
|
||
source ~/.config/xray-proxy/shell.bash
|
||
```
|
||
|
||
Полный `./install.sh` выполняет тот же `stow` вместе с остальными пакетами, а
|
||
`.bash_custom` подключает модуль автоматически.
|
||
|
||
Без остальных dotfiles можно создать две ссылки:
|
||
|
||
```bash
|
||
mkdir -p ~/.local/bin ~/.config/xray-proxy
|
||
ln -s /path/to/xray-proxy/.local/bin/xray-proxy ~/.local/bin/xray-proxy
|
||
ln -s /path/to/xray-proxy/.config/xray-proxy/shell.bash \
|
||
~/.config/xray-proxy/shell.bash
|
||
printf '%s\n' 'source ~/.config/xray-proxy/shell.bash' >> ~/.bashrc
|
||
```
|
||
|
||
Вместо ссылок файлы можно скопировать в те же пути. Исполняемому файлу нужен
|
||
режим `chmod 755`. Каталог `~/.local/bin` должен входить в `PATH`.
|
||
|
||
## Машинный конфиг
|
||
|
||
Скопируйте пример и отредактируйте его:
|
||
|
||
```bash
|
||
mkdir -p ~/.config/proxy
|
||
cp ~/.config/xray-proxy/examples/config ~/.config/proxy/config
|
||
```
|
||
|
||
Формат строгий: одна секция `[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 и домены.
|
||
|
||
Если файла нет, используется прежний внешний 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/xray-proxy/examples/default.url ~/.config/xray-proxy/default.url
|
||
chmod 600 ~/.config/xray-proxy/default.url
|
||
```
|
||
|
||
Файл должен содержать ровно одну непустую строку. Можно передать другой файл
|
||
через `xray-proxy start -f /path/to/profile.url`. Если это симлинк, проверяются
|
||
права конечного файла.
|
||
|
||
## Команды
|
||
|
||
```bash
|
||
xray-proxy install [--replace]
|
||
xray-proxy status
|
||
xray-proxy start [-f PROFILE]
|
||
xray-proxy stop
|
||
xray-proxy env
|
||
xray-proxy 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-экземпляра установка запрещена: сначала выполните
|
||
`xray-proxy 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. Неизвестные,
|
||
повторные и несовместимые 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).
|
||
CLI такие версии не поддерживает и не устанавливает.
|
||
|
||
Сводка скрывает UUID и ключи. Содержимое XHTTP `path` не показывается — только
|
||
его длина. Сгенерированный JSON и состояние лежат в закрытом каталоге
|
||
`$XDG_STATE_HOME/xray-proxy` либо `~/.local/state/xray-proxy` и удаляются после
|
||
штатной остановки. Сбой диагностики внешнего IP через локальный HTTP-прокси
|
||
показывается как предупреждение и не останавливает уже готовый Xray.
|