From 181a610fbbc18e4f045cb55a7bb7baa47869e0ff Mon Sep 17 00:00:00 2001 From: Andrey Prokopyuk Date: Sun, 11 Oct 2026 17:27:14 +0300 Subject: [PATCH] Align documentation and inventory examples with current behavior --- README.md | 10 ++++++-- docs/en/README.md | 55 ++++++++++++++++++++++++++++++------------- docs/ru/README.md | 54 +++++++++++++++++++++++++++++++----------- docs/ru/config-api.md | 20 +++++++++------- docs/ru/transports.md | 20 +++++++++++----- inventory.example.yml | 2 -- 6 files changed, 113 insertions(+), 48 deletions(-) diff --git a/README.md b/README.md index dd31cb3..79a2cdc 100644 --- a/README.md +++ b/README.md @@ -27,11 +27,14 @@ administrative key on your computer before confirming provisioning. See the ### Manage servers from another machine -Requirements: macOS or Linux, Python 3.12+, `uv`, OpenSSH, and a Debian or Ubuntu server reachable through a +Requirements: macOS or Linux, Git, Python 3.12+, `uv`, OpenSSH, and a Debian or Ubuntu server reachable through a sudo-capable SSH account. ```shell +git clone https://github.com/andre487/MegaProxyServer.git +cd MegaProxyServer ./mega-proxy inventory +./mega-proxy bootstrap ./mega-proxy plan ./mega-proxy apply ./mega-proxy verify @@ -84,7 +87,10 @@ See [`inventory.example.yml`](inventory.example.yml) and the ``` This runs Ruff, pytest, Python byte-compilation and Ansible syntax checks with dependencies locked -in `uv.lock`. +in `uv.lock`. Separate GitHub Actions jobs test real GOST/nginx and Ubuntu/Debian LXD +provisioning; `check` does not run these integrations. See the +[English](docs/en/README.md#development-and-troubleshooting) or +[Russian](docs/ru/README.md#разработка-и-диагностика) guide for coverage and `main` protection. ## License diff --git a/docs/en/README.md b/docs/en/README.md index ad144a4..dd7aa0b 100644 --- a/docs/en/README.md +++ b/docs/en/README.md @@ -14,7 +14,7 @@ open a shell, TTY, subsystem, remote forwarding or tunnel device. ## Requirements -The control machine needs macOS or Linux, `uv`, OpenSSH and Python 3.12+. Managed machines need a +The control machine needs macOS or Linux, Git, `uv`, OpenSSH and Python 3.12+. Managed machines need a current Debian or Ubuntu release and a sudo-capable SSH account. Open TCP 443 for HTTPS and TCP 80 during standalone ACME validation in both the provider firewall and the host firewall. @@ -73,6 +73,8 @@ key paths. Local setup handles one server; multi-host management is described be ### Manage from another machine ```shell +git clone https://github.com/andre487/MegaProxyServer.git +cd MegaProxyServer ./mega-proxy inventory ./mega-proxy bootstrap ./mega-proxy plan @@ -87,7 +89,9 @@ at any time with `--inventory PATH`. The wizard supports an initial password or a separate SSH key. Bootstrap prompts for the password without echoing it. The password is kept only in a private temporary connection file, removed after Ansible exits. Verify the server fingerprint and add its key to `known_hosts` first. Load -passphrase-protected administrative keys with `ssh-add`. +passphrase-protected administrative keys with `ssh-add`; deriving or validating the public key +also uses `ssh-keygen -y`, which can ask for the passphrase separately. Unattended apply requires +this step to work without an interactive prompt. `bootstrap` creates the administrator and sudo access, checks a fresh key-only login and `sudo -n`, then disables root and password-based administrative login. It verifies access again after SSH @@ -147,12 +151,14 @@ provide metadata for personalized delivery; the current `export` and `configs` c `services.ssh.generate_profile` defaults to false and selects hosts for direct SSH profiles in `export`, `configs` and the configuration API. Administrative SSH uses `admin` settings separately. -The wizard asks whether to publish direct SSH profiles. `enabled: false` also +The wizard asks whether to publish direct SSH profiles, defaulting to yes; omitting the field +in hand-written YAML still defaults to false. `enabled: false` also disables an existing proxy: HTTPS stops GOST, HAProxy and the renewal timer; SSH denies the `megaproxy` group and closes its sessions while preserving administrative SSH. Keep the disabled service in YAML: an absent service is unmanaged. Firewall records its own rules and revokes retired ports on the next full apply, preserving -other rules. An initial upgrade records existing configured ports before later changes. +other rules. An initial upgrade records existing configured ports before later changes; +older open ports already absent from inventory are not discovered automatically. Only accounts whose primary group is `megaproxy` may be modified or removed; new proxy accounts are created in that group. Administrative/bootstrap accounts, @@ -167,7 +173,7 @@ Bootstrap verifies the new login before revoking the old key; mismatched public and private keys are rejected. Inventory and exports are replaced atomically with mode `0600`. Export validation -runs before replacing an existing file; unknown country codes become empty strings. +runs before replacing an existing file; country codes outside `[A-Z]{2}` become empty strings. Port conflicts and HTTPS without routes are rejected before connecting to a host. Docker cleanup only removes old GOST/Certbot images, without global prune operations. HTTPS chains verify the exit certificate and hostname. CI uses a local CA to test @@ -180,8 +186,9 @@ or unavailable exits, without external domains or ACME for these checks. | true | false | Provision SSH proxy users; use the host only in declared jump pairs | | false | any | Deny proxy access, close proxy sessions and omit profiles; jump pairs cannot reference this host | -Setting `enabled: false` skips the role; it does not remove previously provisioned accounts or -stop the server's SSH daemon. To revoke an account, use `remove-users` and `apply`. +Disabling SSH retains proxy accounts but denies their access; it does not stop the server's SSH +daemon. To delete an account, use `remove-users` and `apply`. A tagged apply must include +`firewall` to reconcile ports, for example `apply --tags ssh,https,firewall`. ```yaml hosts: @@ -244,8 +251,11 @@ first, then server-side chains. HTTPS and SSH services and all chain/jump pairs require a nonblank `title`. Names are read directly from inventory; no names are derived from host identifiers. -For country flags, start host identifiers with a two-letter country code followed by `_`, such as -`de_entry` and `us_exit`. Explicit HTTPS chain pairs supply the exit country in `country_code`. +Direct HTTPS country codes come from the first segment of the host identifier after removing +an optional `proxy_` prefix: `de_entry` and `proxy_de` yield `DE`. Identifiers such as `px-de` +yield an empty code. Codes must match two uppercase letters; no country registry is consulted. +Explicit HTTPS chain pairs require `country_code`; jump pairs can override the exit's inferred +code. Direct SSH and SOCKS5 profiles currently have an empty country code. The code is a display hint; use the client connection test to check the observed exit country. HTTPS and jump profile IDs use logical host/route identifiers and the account, so changing a title or endpoint preserves those IDs. Direct SSH IDs also use the host and account. SOCKS5 exports still derive IDs from their names. @@ -259,9 +269,9 @@ Set a knock host per HTTPS proxy using `services.https.probe_resistance.knock`: probe_resistance: enabled: true mode: local_decoy - knock: [px-knock.jethelix.ru] + knock: [knock.example.com] ``` -The first host becomes `browser.knockHost` in API and MegaProxy file profiles. +When probe resistance is enabled, the first host becomes `browser.knockHost` in API and MegaProxy file profiles. Chain routes inherit the entry setting unless the pair overrides `probe_resistance`. The setup wizard asks for the knock hostname when probe resistance is enabled. Apply HTTPS settings to the proxy hosts and update the config API bundle after changing it. @@ -276,6 +286,9 @@ Masked routes serve a static site using GOST's built-in loopback file server. A Python script generates a random heading and abstract SVG once. Repeated `apply` runs keep the site; remove `/opt/megaproxy/decoy/index.html` to regenerate it on the next `apply`. The page includes `noindex,nofollow`; `/robots.txt` contains `User-agent: *` and `Disallow: /`. +Only `enabled` and `knock` currently affect masking. The inventory model accepts `mode`, +`status_code` and `site_title`, but they do not select another response mode +or control the generated site's title. ## HTTPS certificates and chains @@ -300,7 +313,7 @@ clients to allow an invalid proxy certificate. The default `.generated/configs` directory contains: -- `MegaProxy.json`: HTTPS, direct SSH for hosts with `services.ssh.generate_profile: true`, and explicitly configured SSH/HTTPS jump profiles; +- `MegaProxy.json`: HTTPS, enabled MASQUE/SOCKS5 transports, direct SSH for hosts with `services.ssh.generate_profile: true`, and explicitly configured SSH/HTTPS jump profiles; - `FoxyProxy.json`: HTTPS profiles; - `SuperProxy.txt`: HTTPS URLs with the Super Proxy v1 header; - `ProxyList.txt`: URL-encoded HTTPS proxy URLs. @@ -383,8 +396,10 @@ SNI routes remain usable through the HTTPS-only export formats. SSH jump profile ### Client limits and diagnostics -The Android client forwards TCP application traffic; general UDP and QUIC forwarding are not -implemented. SSH keys protected by a passphrase are unsupported. DNS, per-app routing, failover +HTTPS and SSH forward TCP; MASQUE and SOCKS5 also forward UDP in compatible Android builds. +Availability depends on the installed client release; see its +[transport guide](https://github.com/andre487/AndroidMegaProxy#current-limitations). +SSH keys protected by a passphrase are unsupported. DNS, per-app routing, failover and Android Always-on VPN are configured in the app. Exported profiles do not enable failover. Use **Test** to distinguish proxy setup, destination access and exit-IP failures. It contacts @@ -449,8 +464,16 @@ directory is suitable for machine-local integrations such as px-manager. ## Development and troubleshooting -`./mega-proxy check` runs Ruff, pytest, byte-compilation and Ansible syntax checks. CI runs the same -suite; integration jobs provision isolated Ubuntu/Debian LXD systems. +`./mega-proxy check` runs Ruff, pytest, byte-compilation and Ansible syntax checks. CI runs this +suite on Python 3.12 and 3.14. Separate integration jobs run real GOST and nginx on loopback +and provision Ubuntu 24.04 plus two Debian 12 LXD guests. They cover SSH Jump, credential +rotation, account removal, proxy disable/re-enable, firewall cleanup and administrative access. +They use temporary credentials and self-signed or local-CA certificates; they do not test +production DNS, public ACME issuance or an Android device. These jobs are not run by `check`. + +`main` requires a pull request, all five CI checks, an up-to-date branch and resolved +conversations. Force pushes and deletion are forbidden, including for administrators; +approval by a second person is not required. The required check names match the workflows. - **ACME fails:** check DNS, TCP 80 and provider firewall rules. - **A chain domain serves an old certificate:** run `apply --limit ENTRY --tags https`, then inspect diff --git a/docs/ru/README.md b/docs/ru/README.md index 368ca36..0a49bf4 100644 --- a/docs/ru/README.md +++ b/docs/ru/README.md @@ -14,7 +14,7 @@ HTTPS обслуживает GOST в контейнере закреплённо ## Требования -Управляющей машине нужны macOS или Linux, `uv`, OpenSSH и Python 3.12+. Управляемым машинам — +Управляющей машине нужны macOS или Linux, Git, `uv`, OpenSSH и Python 3.12+. Управляемым машинам — актуальный Debian или Ubuntu и SSH-пользователь с `sudo`. Откройте TCP 443 для HTTPS и TCP 80 на время standalone-проверки ACME как в firewall провайдера, так и на самом сервере. @@ -76,6 +76,8 @@ Inventory, ключи и экспорты остаются на сервере; ### Управление с другой машины ```shell +git clone https://github.com/andre487/MegaProxyServer.git +cd MegaProxyServer ./mega-proxy inventory ./mega-proxy bootstrap ./mega-proxy plan @@ -91,6 +93,8 @@ Inventory, ключи и экспорты остаются на сервере; скрыто при bootstrap и не сохраняется в постоянном inventory; временный файл подключения удаляется после запуска Ansible. До запуска проверьте fingerprint сервера и добавьте его ключ в `known_hosts`. Для административного ключа с парольной фразой предварительно используйте `ssh-add`. +Получение и проверка публичного ключа также используют `ssh-keygen -y`, который может +отдельно запросить парольную фразу. Для unattended apply этот шаг должен работать без запроса. `bootstrap` создаёт администратора с ключом и sudo, проверяет независимое подключение и `sudo -n`, затем отключает root и парольный административный вход. После перечитывания SSH-конфигурации @@ -154,14 +158,16 @@ HTTPS-пользователям; удаление SSH-аккаунта такж `services.ssh.generate_profile` по умолчанию false: выбирает хосты для прямых SSH-профилей в `export`, `configs` и API. Административный SSH отдельно задаётся через `admin`. -Мастер отдельно спрашивает, публиковать ли прямые SSH-профили. `enabled: false` +Мастер отдельно спрашивает, публиковать ли прямые SSH-профили, предлагая «да»; +при отсутствии поля в ручном YAML действует false. `enabled: false` отключает уже настроенный прокси: для HTTPS останавливает GOST, HAProxy и таймер renewal; для SSH запрещает вход группе `megaproxy` и закрывает её сессии, сохраняя административный SSH. Удалять службу из YAML вместо `enabled: false` не следует: отсутствующая служба не управляется. Firewall запоминает управляемые правила и удаляет устаревшие при следующем полном apply; остальные правила сохраняются. Первый apply после обновления запоминает существующие настроенные порты перед -последующими изменениями. +последующими изменениями; ранее открытые порты, уже отсутствующие в inventory, +автоматически не обнаруживаются. SSH-аккаунты могут изменяться и удаляться только если их основная группа — `megaproxy`; новые аккаунты создаются в этой группе. `removed_ssh` не допускает @@ -176,7 +182,8 @@ SSH-аккаунты могут изменяться и удаляться то ключа; несовпадающая пара публичного и приватного ключей отклоняется. Инвентарь и экспорт записываются атомарно с правами `0600`. Экспорт проверяется -до замены прежнего файла; неизвестный код страны становится пустой строкой. +до замены прежнего файла; код страны, не соответствующий двум латинским буквам в верхнем +регистре, становится пустой строкой. Справочник стран не проверяется. Конфликты портов и HTTPS без маршрутов отклоняются до подключения к хосту. Docker cleanup удаляет только старые образы GOST/Certbot, без глобального prune. HTTPS-цепочки проверяют сертификат и имя выхода. CI использует локальную CA и @@ -189,8 +196,10 @@ HTTPS-цепочки проверяют сертификат и имя выхо | true | false | Настройка SSH-прокси; использование хоста только в явных jump-парах | | false | любое | Вход прокси-аккаунтам запрещается, сессии закрываются, профили не генерируются; jump-пары не допускаются | -`enabled: false` пропускает роль, но не удаляет ранее созданные аккаунты и не останавливает -SSH-демон сервера. Для отзыва аккаунта используйте `remove-users` и `apply`. +Отключение SSH сохраняет прокси-аккаунты, но запрещает им доступ; SSH-демон сервера +продолжает работать. Для удаления аккаунта используйте `remove-users` и `apply`. +При применении с тегами включите `firewall`, чтобы обновить порты, например +`apply --tags ssh,https,firewall`. ```yaml hosts: @@ -253,8 +262,11 @@ MASQUE и SOCKS5 относятся к первой группе. Переста Для HTTPS- и SSH-сервисов и всех chain/jump-пар обязателен непустой `title`. Названия берутся непосредственно из inventory; из имён хостов они не вычисляются. -Для флагов стран начинайте идентификаторы хостов с двухбуквенного кода страны и `_`, например -`de_entry` и `us_exit`. В явных HTTPS-парах код страны выхода задаётся через `country_code`. +Код страны прямого HTTPS берётся из первого сегмента имени хоста после удаления +необязательного префикса `proxy_`: `de_entry` и `proxy_de` дают `DE`, а `px-de` — пустой +код. Допускаются две латинские буквы в верхнем регистре; справочник стран не проверяется. +В серверных HTTPS-парах `country_code` обязателен; jump-пары могут переопределять код, +полученный из имени выхода. У прямых SSH- и SOCKS5-профилей код страны сейчас пустой. Это подпись для отображения; фактическую страну выхода проверяйте тестом соединения в приложении. ID HTTPS- и jump-профилей формируются из логических хостов, маршрутов и аккаунта: изменение title или endpoint сохраняет ID. ID прямых SSH также зависят от хоста и аккаунта; в общем экспорте только ID SOCKS5 @@ -269,9 +281,9 @@ Knock host задаётся для каждого HTTPS-прокси через probe_resistance: enabled: true mode: local_decoy - knock: [px-knock.jethelix.ru] + knock: [knock.example.com] ``` -Первый хост попадает в `browser.knockHost` в API и файловом экспорте MegaProxy. +При включённом маскировании первый хост попадает в `browser.knockHost` в API и файловом экспорте MegaProxy. Серверные цепочки наследуют настройку входного узла, если пара не переопределяет `probe_resistance`. Мастер запрашивает knock host при включении маскирования. После изменения примените HTTPS-настройки на прокси и обновите bundle конфигурационного API. @@ -287,6 +299,9 @@ Probe resistance подавляет обычный запрос аутентиф абстрактную SVG-картинку. Повторный `apply` сохраняет сайт; удаление `/opt/megaproxy/decoy/index.html` приводит к новой генерации при следующем `apply`. Страница содержит `noindex,nofollow`, а `/robots.txt` — `User-agent: *` и `Disallow: /`. +Сейчас на маскирование влияют только `enabled` и `knock`. Поля `mode`, `status_code` +и `site_title` принимаются моделью inventory, но не выбирают другой режим ответа +и не задают заголовок генерируемого сайта. ## HTTPS-сертификаты и chains @@ -311,7 +326,7 @@ SAN, расширяет сертификат и перезапускает GOST, По умолчанию `.generated/configs` содержит: -- `MegaProxy.json`: HTTPS, прямые SSH хостов с `services.ssh.generate_profile: true` и явно заданные SSH/HTTPS jump-профили; +- `MegaProxy.json`: HTTPS, включённые MASQUE/SOCKS5, прямые SSH хостов с `services.ssh.generate_profile: true` и явно заданные SSH/HTTPS jump-профили; - `FoxyProxy.json`: HTTPS-профили; - `SuperProxy.txt`: HTTPS URL с заголовком Super Proxy v1; - `ProxyList.txt`: URL-кодированные HTTPS-прокси. @@ -392,7 +407,9 @@ failover, и заменяет настройки профилей. После и ### Ограничения клиента и диагностика -Android-клиент передаёт TCP-трафик приложений; произвольный UDP и QUIC не поддерживаются. +HTTPS и SSH передают TCP; MASQUE и SOCKS5 также передают UDP в совместимых сборках Android. +Доступность зависит от установленной версии клиента; см. его +[ограничения транспортов](https://github.com/andre487/AndroidMegaProxy#current-limitations). SSH-ключи с парольной защитой не поддерживаются. DNS, маршрутизация по приложениям, failover и Android Always-on VPN настраиваются в приложении. Экспортированные профили не включают failover. @@ -460,8 +477,17 @@ inventory после каждого успешно настроенного хо ## Разработка и диагностика -`./mega-proxy check` запускает Ruff, pytest, byte-compilation и проверку синтаксиса Ansible. CI -выполняет тот же набор; интеграционные jobs разворачивают изолированные Ubuntu/Debian LXD-системы. +`./mega-proxy check` запускает Ruff, pytest, byte-compilation и проверку синтаксиса Ansible. +CI выполняет этот набор на Python 3.12 и 3.14. Отдельные интеграционные jobs проверяют +настоящие GOST и nginx на loopback, а также Ubuntu 24.04 и два Debian 12 в LXD. +Они покрывают SSH Jump, ротацию реквизитов, удаление пользователей, отключение и повторное +включение прокси, очистку firewall и сохранение административного доступа. +Используются временные реквизиты и self-signed или локальная CA; публичный ACME, production +DNS и Android-устройство этими проверками не покрываются. Команда `check` их не запускает. + +Для `main` обязательны PR, все пять проверок CI, актуальная база и закрытые обсуждения. +Force push и удаление запрещены, включая администратора; одобрение второго человека +не требуется. Имена обязательных проверок соответствуют именам jobs в workflows. - **Ошибка ACME:** проверьте DNS, TCP 80 и firewall провайдера. - **Chain-домен отдаёт старый сертификат:** выполните `apply --limit ENTRY --tags https`, затем diff --git a/docs/ru/config-api.md b/docs/ru/config-api.md index 9f6cdb8..ab6cb79 100644 --- a/docs/ru/config-api.md +++ b/docs/ru/config-api.md @@ -67,8 +67,10 @@ hosts: `enabled` по умолчанию true и управляет настройкой и проверкой SSH-прокси на сервере. При false SSH-профили для хоста не генерируются, ссылки на него в jump-парах отклоняются. -Этот флаг не отключает административный SSH и не удаляет ранее созданные аккаунты: -роль SSH-прокси просто пропускается. Для отзыва аккаунта используйте `remove-users` и `apply`. +После `apply` с тегом `ssh` доступ группы `megaproxy` запрещается и её сессии закрываются. +Административный SSH сохраняется, существующие прокси-аккаунты остаются на сервере. +Для удаления аккаунта используйте `remove-users` и `apply`; для закрытия устаревших +портов включите тег `firewall` или выполните полный `apply`. Названия прямых SSH-профилей берутся из обязательного `services.ssh.title`. API выдаёт title без логина; общий экспорт добавляет ` / логин`, как для HTTPS. @@ -193,8 +195,9 @@ API-адресов соответствует ограничению прото `X-MegaProxy-Client: browser_chromium` и `browser_firefox` выбирают HTTPS и совместимые SOCKS5-профили; SSH/jump/MASQUE-профили и Android-поля в этот ответ не включаются. Chromium не получает SOCKS5 с реквизитами; для Firefox проверяется лимит 255 UTF-8 байт. -Значения `android` и `android_megaproxy` выбирают Android-проекцию без SOCKS5, IPv6 endpoints -и browser-полей. Без заголовка или с неизвестным значением возвращается общий формат v8. +Значения `android` и `android_megaproxy` выбирают Android-проекцию без IPv6 endpoints +и browser-полей; SOCKS5 и MASQUE сохраняются. Для них требуется совместимая версия клиента. +Без заголовка или с неизвестным значением возвращается общий формат v8. Заголовок клиента не расширяет права на SSH-аккаунты. `X-MegaProxy-Version` — версия приложения клиента. ETag учитывает пользователя, выбранный @@ -297,18 +300,19 @@ curl --fail --silent --show-error --basic --netrc-file ./credentials.netrc \ Локальный тест с настоящим nginx и временным доверенным тестовым сертификатом: ```sh -uv run python tests/integration/config_api.py --nginx /path/to/nginx +uv run --frozen python tests/integration/config_api.py --nginx /path/to/nginx ``` Он проверяет HTTPS, canonical v8, ETag после аутентификации, robots.txt, буквальное сравнение -путей и ответы 403/noindex. В рабочие API-пакеты не входят полный inventory, административные +путей, неоднозначные и некорректные заголовки Authorization, rate limit и ответы 403/noindex. +Тест также запускается в GitHub Actions. В рабочие API-пакеты не входят полный inventory, административные ключи, исходные пути SSH-ключей или машинные пароли HTTPS-цепочек. Работающий API получает пароль и расшифрованные SSH-секреты в памяти во время авторизованного запроса. Knock host для замаскированного HTTPS-прокси задаётся в inventory: -`services.https.probe_resistance.knock: [px-knock.jethelix.ru]`. -Первый хост списка становится `browser.knockHost` в API и файловом экспорте MegaProxy; +`services.https.probe_resistance.knock: [knock.example.com]`. +При включённом маскировании первый хост списка становится `browser.knockHost` в API и файловом экспорте MegaProxy; для MASQUE он не применяется. Мастер настройки запрашивает его при включении маскирования. Серверные цепочки наследуют настройку entry, если у пары нет своего `probe_resistance`. После изменения примените HTTPS-настройки на прокси и обновите bundle API. diff --git a/docs/ru/transports.md b/docs/ru/transports.md index 561fba1..f57451d 100644 --- a/docs/ru/transports.md +++ b/docs/ru/transports.md @@ -44,7 +44,8 @@ HTTPS и MASQUE доступны на одном hostname и номере пор HTTP/3 включается только на прямых маршрутах. Серверные SNI-цепочки остаются HTTPS/TCP и не получают MASQUE или `preferHttp3`: GOST 3.3.0 передаёт некорректный Extended CONNECT при собственном исходящем CONNECT-UDP. Это ограничение не разрешает превращать -цепочку в прямой маршрут. В нашем inventory HTTP/3 на хостах `cpx-*` выключен. +цепочку в прямой маршрут. `http3: true` требует `direct: true` на хосте; +серверные chain-маршруты этого хоста по-прежнему работают только через TCP. Клиентские HTTPS_JUMP-профили могут описывать два прямых HTTPS/MASQUE endpoint; их поддержку и fallback реализует клиент согласно контракту MegaProxyConfig. Такие профили генерируются из `settings.https_jump_pairs`; `preferHttp3` включается @@ -69,7 +70,8 @@ SOCKS5 публикуется на прямом endpoint хоста; серве Firewall открывает TCP `port` и заданный диапазон UDP-relay. Число одновременно выделенных relay-портов ограничено размером диапазона; измените диапазон, если его -недостаточно. На отключённом SOCKS5 listener и эти правила не создаются. +недостаточно. После отключения SOCKS5 и применения настроек listener удаляется; +роль firewall удаляет ранее записанные управляемые правила. API автоматически выдаёт SOCKS5-профили только для включённых хостов. Firefox и Android получают профили с реквизитами; Chromium их пропускает, поскольку не @@ -88,17 +90,23 @@ Android получают профили с реквизитами; Chromium их Изменения флагов нужно применить и на прокси, и на серверах конфигов. `--limit` обновляет только выбранные машины. Отключение listener прекращает доступ; роль -firewall добавляет необходимые правила, но не удаляет ранее созданные правила. +firewall добавляет необходимые правила и удаляет устаревшие управляемые правила. +При использовании тегов включите `firewall`, например `apply --tags https,firewall`. +Первый apply после обновления записывает текущие порты в `/etc/megaproxy/firewall.json`: +ранее открытые, но уже отсутствующие в inventory порты автоматически не обнаруживаются. Тесты генерации и совместимости входят в `./mega-proxy check`. Проверка реального GOST 3.3.0 локально и в CI: ```sh -uv run python tests/integration/transports.py --gost /path/to/gost +uv run --frozen python tests/integration/transports.py --gost /path/to/gost +uv run --frozen python tests/integration/https.py --gost /path/to/gost ``` -Она проверяет SOCKS5 TCP/UDP, обязательную аутентификацию, диапазон relay-портов, -MASQUE TCP/UDP, доверенный TLS и отказ при неверных реквизитах. +Первый тест проверяет SOCKS5 TCP/UDP, обязательную аутентификацию, диапазон relay-портов, +MASQUE TCP/UDP, доверенный TLS и отказ при неверных реквизитах. Второй проверяет +HTTPS knock, маскировку, серверные цепочки и TLS внутри HTTPS Jump, включая отказ при +неверных машинных реквизитах, имени сертификата или недоступности выхода. В тестах используются временные ключи и реквизиты; публичные серверы не требуются. Исходные настройки: [MASQUE GOST](https://gost.run/reference/handlers/masque/), diff --git a/inventory.example.yml b/inventory.example.yml index 6483645..fada48b 100644 --- a/inventory.example.yml +++ b/inventory.example.yml @@ -42,8 +42,6 @@ hosts: certbot_version: v5.4.0 probe_resistance: enabled: false - mode: disabled - site_title: Personal site # Set a hostname when enabling probe resistance; the first host is exported as browser.knockHost. knock: [] ssh: