Skip to content

Commit fc117bc

Browse files
authored
Configure explicit proxy profiles, titles and knock hosts (#5)
* Configure explicit proxy profiles, titles and knock hosts * Set explicit titles in LXD integration inventory
1 parent 0d5d537 commit fc117bc

28 files changed

Lines changed: 929 additions & 174 deletions

‎README.md‎

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,11 @@ Install the client using its [installation guide](https://github.com/andre487/An
5656
transfer `.generated/configs/MegaProxy.json` privately, and import it in the app. Select a profile,
5757
run **Test**, verify any SSH host-key prompt, then connect and approve Android VPN access.
5858

59-
The current server exporter produces JSON v7, accepted by the current Android v8 importer.
60-
Server-side SNI chains are exported as ordinary HTTPS profiles. The app also supports client-side
61-
**HTTPS with Jump**, which must currently be configured in the app. See the
59+
The exporter produces JSON v7 for basic profiles and v8 when HTTPS Jump, HTTP/3 or SOCKS5
60+
is configured; the configuration API always returns v8. Server-side SNI chains are ordinary
61+
HTTPS profiles. Client-side SSH and HTTPS Jump profiles use only declared inventory pairs.
62+
Direct SSH profiles require `services.ssh.generate_profile: true` (default: false).
63+
See the [complete jump inventory example](inventory.jumps.example.yml) and the
6264
[English](docs/en/README.md#android-megaproxy) or [Russian](docs/ru/README.md#android-megaproxy)
6365
guide for chain setup and reimport behavior.
6466

@@ -67,7 +69,7 @@ guide for chain setup and reimport behavior.
6769
- HTTPS CONNECT proxy with TLS 1.2/1.3 and optional probe-resistant decoy responses
6870
- ACME certificates for DNS names and public IP addresses, plus a self-signed fallback
6971
- SNI-based HTTPS chains through independently selected entry and exit servers
70-
- Restricted SSH forwarding accounts and dynamic SSH jump profiles
72+
- Restricted SSH forwarding accounts and explicit SSH and HTTPS jump profiles
7173
- Global HTTPS and SSH users, with safe removal across every managed host
7274
- Inline Ansible Vault encryption that leaves non-secret inventory settings readable
7375
- Idempotent provisioning and integration tests on Ubuntu and Debian

‎docs/en/README.md‎

Lines changed: 108 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -141,15 +141,104 @@ matched automatically. Unknown accounts and duplicates fail inventory validation
141141
may be linked to multiple HTTPS users; removing an SSH account also removes its links. These links
142142
provide metadata for personalized delivery; the current `export` and `configs` commands still export all users.
143143

144+
### SSH service and profile selection
145+
146+
`services.ssh.enabled` defaults to true and controls SSH proxy provisioning and verification.
147+
`services.ssh.generate_profile` defaults to false and selects hosts for direct SSH profiles in
148+
`export`, `configs` and the configuration API. Administrative SSH uses `admin` settings separately.
149+
150+
| enabled | generate_profile | Result |
151+
| --- | --- | --- |
152+
| true | true | Provision SSH proxy users and publish direct SSH profiles |
153+
| true | false | Provision SSH proxy users; use the host only in declared jump pairs |
154+
| false | any | Skip SSH proxy provisioning/verification and profile generation; jump pairs cannot reference this host |
155+
156+
Setting `enabled: false` skips the role; it does not remove previously provisioned accounts or
157+
stop the server's SSH daemon. To revoke an account, use `remove-users` and `apply`.
158+
159+
```yaml
160+
hosts:
161+
de_proxy:
162+
# address and admin as in inventory.example.yml
163+
services:
164+
ssh:
165+
title: DE
166+
enabled: true
167+
generate_profile: true
168+
```
169+
170+
Direct SSH titles use the required `services.ssh.title` field.
171+
The API omits the login; file exports append ` / login`, as for HTTPS.
172+
173+
### Explicit client-side jump pairs
174+
175+
```yaml
176+
settings:
177+
ssh_jump_pairs:
178+
- entry: de_proxy
179+
exit: us_proxy
180+
title: SSH DE -> US
181+
country_code: US
182+
https_jump_pairs:
183+
- entry: de_proxy
184+
exit: us_proxy
185+
title: HTTPS DE -> US
186+
country_code: US
187+
```
188+
189+
`entry` is the first hop; `exit` is the destination. SSH Jump uses the same account from
190+
`users.ssh` on both hops. `export` and `configs` generate one profile per SSH account;
191+
the API uses only accounts linked through the HTTPS user's `ssh_users`. No per-hop login
192+
is configured in a pair. Both SSH services must be enabled, but `generate_profile` may be false.
193+
HTTPS Jump uses the current HTTPS user's credentials on both hops and requires two enabled
194+
direct HTTPS endpoints. It does not require `https_chains_enabled` or a chain domain.
195+
196+
For both jump lists, `title` is required and `country_code` is optional.
197+
The country defaults to the exit's code. An explicit country must
198+
be two uppercase letters. Empty lists create no jump profiles; no combinations are inferred.
199+
Unknown hosts, disabled services, repeated pairs and identical entry/exit hosts fail validation.
200+
`./mega-proxy jumps` lists configured SSH pairs for each account. The legacy `--all-jumps`
201+
export flag is accepted but never enables undeclared pairs.
202+
203+
See [inventory.jumps.example.yml](../../inventory.jumps.example.yml) for a complete example.
204+
`https_chain_pairs` is separate: it creates server-side SNI routes with individual hostnames,
205+
exported as ordinary HTTPS profiles. See [inventory.chains.example.yml](../../inventory.chains.example.yml).
206+
207+
### Profile order
208+
209+
The API and MegaProxy JSON list direct HTTPS, direct SSH, `https_chain_pairs`,
210+
`https_jump_pairs`, then `ssh_jump_pairs`. Direct profiles follow inventory host order;
211+
pairs follow their respective list order. MASQUE and SOCKS5 belong to the first group.
212+
Reordering preserves IDs. FoxyProxy, SuperProxy and ProxyList list direct HTTPS routes
213+
first, then server-side chains.
214+
215+
### Profile names and countries
216+
217+
HTTPS and SSH services and all chain/jump pairs require a nonblank `title`.
218+
Names are read directly from inventory; no names are derived from host identifiers.
219+
144220
For country flags, start host identifiers with a two-letter country code followed by `_`, such as
145221
`de_entry` and `us_exit`. Explicit HTTPS chain pairs supply the exit country in `country_code`.
146222
The code is a display hint; use the client connection test to check the observed exit country.
147-
Give exported profiles distinct names: their IDs are derived from those names.
148-
149-
An empty `https_chain_pairs` enables all compatible directed entry/exit combinations; a non-empty
150-
list limits routes to the declared pairs. Each exit needs separate machine credentials in
151-
`chain_password`, which are excluded from client exports. Chain titles use the pair title, then
152-
the entry service title, then a name derived from the inventory host identifier.
223+
HTTPS and jump profile IDs use logical host/route identifiers and the account, so changing a
224+
title or endpoint preserves those IDs. Direct SSH IDs also use the host and account. SOCKS5 exports still derive IDs from their names.
225+
226+
`https_chain_pairs` creates only declared entry/exit routes; an empty list creates no server-side
227+
chains. Each exit needs separate machine credentials in
228+
`chain_password`, which are excluded from client exports. Chain titles use the required pair `title`.
229+
230+
Set a knock host per HTTPS proxy using `services.https.probe_resistance.knock`:
231+
```yaml
232+
probe_resistance:
233+
enabled: true
234+
mode: local_decoy
235+
knock: [px-knock.jethelix.ru]
236+
```
237+
The first host becomes `browser.knockHost` in API and MegaProxy file profiles.
238+
Chain routes inherit the entry setting unless the pair overrides `probe_resistance`.
239+
The setup wizard asks for the knock hostname when probe resistance is enabled.
240+
Apply HTTPS settings to the proxy hosts and update the config API bundle after changing it.
241+
MASQUE profiles do not use knock hosts.
153242

154243
Probe resistance suppresses the normal authentication challenge and can break browser clients
155244
that wait for `407` before sending credentials. Keep it disabled unless tested with the required
@@ -184,7 +273,7 @@ clients to allow an invalid proxy certificate.
184273

185274
The default `.generated/configs` directory contains:
186275

187-
- `MegaProxy.json`: HTTPS, direct SSH and every dynamic SSH jump profile;
276+
- `MegaProxy.json`: HTTPS, direct SSH for hosts with `services.ssh.generate_profile: true`, and explicitly configured SSH/HTTPS jump profiles;
188277
- `FoxyProxy.json`: HTTPS profiles;
189278
- `SuperProxy.txt`: HTTPS URLs with the Super Proxy v1 header;
190279
- `ProxyList.txt`: URL-encoded HTTPS proxy URLs.
@@ -200,12 +289,10 @@ equal peers. See the [inventory example](../../inventory.config-api.example.yml)
200289
verification, password-encrypted SSH secrets, client projections, bootstrap subscriptions and
201290
authenticated ETags. `/robots.txt` is public; other paths and invalid credentials return 403.
202291

203-
Compatibility was reviewed on 2026-09-08 against AndroidMegaProxy
204-
[revision c8190e9](https://github.com/andre487/AndroidMegaProxy/tree/c8190e97b705a2c4578d278c40a690e97c5d5f27).
205-
The client [importer](https://github.com/andre487/AndroidMegaProxy/blob/c8190e97b705a2c4578d278c40a690e97c5d5f27/app/src/main/java/net/megaproxy487/data/ConfigTransfer.kt)
206-
accepts the JSON produced by this repository's [exporter](../../src/megaproxy_server/export.py):
207-
the server currently writes schema `net.megaproxy487.config` v7; the app writes v8 and reads v1–v8.
208-
Changing the server's version number alone would not add HTTPS jump profiles.
292+
The [exporter](../../src/megaproxy_server/export.py) writes schema `net.megaproxy487.config`
293+
v7 for basic HTTPS/SSH profiles and v8 when `https_jump_pairs`, HTTP/3 or SOCKS5 is configured.
294+
MASQUE profiles require HTTP/3. The configuration API always returns canonical v8 and filters
295+
profiles for the requested client; browser projections omit SSH, jump and MASQUE profiles.
209296

210297
### Import and connect
211298

@@ -232,9 +319,11 @@ cannot carry that setting. Prefer ACME certificates for normal operation.
232319
### Updating imported profiles
233320

234321
Repeat `configs` after server or credential changes, then reimport the JSON. Matching IDs update
235-
existing profiles; new IDs add profiles. IDs remain stable while generated profile names remain
236-
unchanged. Renaming a host, login or HTTPS title can change IDs. Distinct routes must not share the
237-
same generated name: duplicate IDs are rejected by the Android importer.
322+
existing profiles; new IDs add profiles. Generated HTTPS, MASQUE and jump IDs depend on logical
323+
host/route identifiers and accounts; changing their title, country or endpoint preserves IDs.
324+
Renaming an inventory host or account changes those IDs. Direct SSH IDs also use logical host/account identifiers. SOCKS5 exports derive
325+
IDs from names; renaming those profiles changes IDs. The API uses logical identities for all
326+
generated profiles. Additional manual profiles must supply unique IDs.
238327

239328
The app offers optional removal of local profiles missing from the file; they are not deleted
240329
automatically. Removing a profile on the phone does not revoke access: use `remove-users` and
@@ -251,7 +340,7 @@ empty, reimport can require host-key confirmation again.
251340
| Route | Setup | What the phone imports |
252341
| --- | --- | --- |
253342
| Server-side SNI chain | Configure entry/exit and DNS using the chain inventory example, then apply | An ordinary `HTTPS` profile pointing to the entry's chain hostname; GOST selects the exit |
254-
| Client-side HTTPS with Jump | Provision two direct HTTPS endpoints, then create **HTTPS with Jump** in the app | Not generated by MegaProxyServer; the app stores it as `HTTPS_JUMP` in JSON v8 |
343+
| Client-side HTTPS with Jump | Provision two direct HTTPS endpoints and configure `settings.https_jump_pairs` | A `HTTPS_JUMP` profile in JSON v8 |
255344

256345
For **HTTPS with Jump**, enter the exit in the main proxy fields and the entry in **Jump HTTPS
257346
proxy**. Use global HTTPS user credentials on each hop; machine `chain_password` credentials belong
@@ -262,7 +351,8 @@ Each hop verifies its own certificate. This mode does not require a chain domain
262351
See the client's [HTTPS with Jump guide](https://github.com/andre487/AndroidMegaProxy#https-with-jump).
263352
Client-side HTTPS jump profiles require a v8-capable app; older clients reject v8 files. Server-side
264353
SNI routes remain usable through the HTTPS-only export formats. SSH jump profiles are generated by
265-
`configs`; for a separate JSON export, request them with `./mega-proxy export --all-jumps`.
354+
`configs` and `export` from `settings.ssh_jump_pairs`. Both jump lists default to empty;
355+
`--all-jumps` is a compatibility flag and never generates undeclared combinations.
266356

267357
### Client limits and diagnostics
268358

0 commit comments

Comments
 (0)