Skip to content

Commit 6aaa93f

Browse files
committed
Add docs
1 parent cf15a51 commit 6aaa93f

4 files changed

Lines changed: 515 additions & 148 deletions

File tree

‎README.md‎

Lines changed: 34 additions & 148 deletions
Original file line numberDiff line numberDiff line change
@@ -1,170 +1,56 @@
11
# MegaProxyServer
22

3-
Ansible roles and an interactive Python launcher for hardened MegaProxy HTTPS and SSH servers.
3+
Provision and operate hardened HTTPS and SSH proxy servers with Ansible.
44

5-
The project supports multiple hosts, multiple users per service, HTTPS and SSH on the same host,
6-
ACME certificates for domains or public IP addresses, a probe-resistant HTTPS decoy, and arbitrary
7-
SSH jump chains. Jump pairs are not stored: any SSH-enabled host can be selected as the jump for
8-
any other SSH-enabled host when profiles are exported.
5+
MegaProxyServer manages multiple Debian/Ubuntu hosts from one inventory, keeps proxy users global,
6+
issues and renews TLS certificates, supports SNI-routed HTTPS chains and exports ready-to-import
7+
client configurations for MegaProxy, FoxyProxy and SuperProxy.
98

10-
Proxy users are global: the top-level `users.https` and `users.ssh` lists are applied to every host
11-
where the corresponding service is enabled. Credentials therefore cannot silently diverge between
12-
hosts. Inventories using the older per-host lists are migrated in memory; conflicting credentials
13-
for the same login are rejected instead of being chosen implicitly.
9+
Documentation: **[English](docs/en/README.md)** · **[Русский](docs/ru/README.md)**
1410

15-
## Requirements
11+
## Quick start
1612

17-
- macOS or Linux control machine with `uv`, OpenSSH and Python available;
18-
- a current Debian or Ubuntu server reachable by a sudo-capable SSH account;
19-
- TCP 80 reachable for ACME issuance and TCP 443 for HTTPS;
20-
- Certbot 5.4 or newer on servers using public-IP certificates.
21-
22-
All Python and Ansible dependencies are declared in `pyproject.toml`, locked in `uv.lock`, and
23-
installed by `uv`. Do not install them manually with pip.
24-
25-
## Start
13+
Requirements: macOS or Linux, `uv`, OpenSSH, and a Debian or Ubuntu server reachable through a
14+
sudo-capable SSH account.
2615

2716
```shell
28-
./mega-proxy
17+
./mega-proxy inventory
18+
./mega-proxy plan
19+
./mega-proxy apply
20+
./mega-proxy verify
2921
```
3022

31-
When no inventory exists, the launcher offers to create `inventory.yml` in the current directory
32-
or use another path. An external path is remembered in `inventory-path`. Both files, generated
33-
profiles and generated keys are excluded by `.gitignore`.
34-
35-
`vault-secrets` encrypts password fields with tagged inline Ansible Vault values while keeping
36-
hosts, ports, domains and flags editable as ordinary YAML. `mega-proxy` prompts for the Vault
37-
password when it encounters the first encrypted value. For unattended runs, set
38-
`ANSIBLE_VAULT_PASSWORD_FILE` to a protected password file. Subsequent inventory updates preserve
39-
field-level encryption. Whole-file Ansible Vault inventories remain readable and are converted to
40-
field-level encryption by `vault-secrets`.
41-
42-
Useful commands:
23+
For an existing inventory, pass `--inventory PATH`. Generate client files and display credentials:
4324

4425
```shell
45-
./mega-proxy inventory
46-
./mega-proxy check
47-
./mega-proxy --inventory ./inventory.yml validate
48-
./mega-proxy --inventory ./inventory.yml plan
49-
./mega-proxy --inventory ./inventory.yml apply
50-
./mega-proxy --inventory ./inventory.yml verify
51-
./mega-proxy --inventory ./inventory.yml jumps
52-
./mega-proxy --inventory ./inventory.yml summary
53-
./mega-proxy --inventory ./inventory.yml summary alice
54-
./mega-proxy --inventory ./inventory.yml remove-users
55-
./mega-proxy --inventory ./inventory.yml configs
56-
./mega-proxy --inventory ./inventory.yml export --all-jumps
26+
./mega-proxy configs
27+
./mega-proxy summary
5728
```
5829

59-
`configs` writes four sensitive import files to `.generated/configs` by default:
60-
61-
- `MegaProxy.json` — HTTPS, direct SSH, and every dynamic SSH Jump combination;
62-
- `FoxyProxy.json` — HTTPS entries only;
63-
- `SuperProxy.txt` — HTTPS entries only, with the Super Proxy v1 header;
64-
- `ProxyList.txt` — URL-encoded HTTPS proxy URLs.
65-
66-
Choose another directory with `configs --output-dir PATH`. Directories use mode `0700` and files
67-
use mode `0600`. Generation is idempotent and never contacts configured servers.
68-
69-
`summary` prints endpoints once, followed by global HTTPS and SSH credential lists. With a login
70-
as its first positional argument, only exact matches are shown. Key-only SSH accounts show the
71-
private-key path instead of a password; administrative accounts are included too. This command deliberately writes plaintext secrets to
72-
stdout; do not run it in CI or redirect it to an unprotected file.
73-
74-
`remove-users` selects one or more global proxy accounts. HTTPS accounts are removed from every
75-
generated GOST configuration; SSH accounts are additionally retained in a global inventory
76-
tombstone list so the next `apply` deletes the corresponding system accounts and root-owned
77-
authorized-key files from every SSH-enabled host.
78-
79-
Use `--limit HOST` and `--tags common,admin,firewall,ssh,https` with plan, apply, or verify. Always run
80-
`plan` before applying to an existing server and keep the current administrative SSH session open.
81-
82-
After a successful `apply`, executable `.hooks/post-config-change` and files in
83-
`.hooks/post-config-change.d/` are run in name order. The ignored `.hooks` directory is intended for
84-
machine-local integrations and secrets. Hooks receive `MEGAPROXY_INVENTORY`,
85-
`MEGAPROXY_ANSIBLE_INVENTORY`, `MEGAPROXY_ROOT`, and `MEGAPROXY_EVENT`. Use `--no-hooks` before or
86-
after the command to skip them, for example `./mega-proxy apply --no-hooks`.
87-
88-
## HTTPS
30+
Inventory and generated exports contain secrets. Keep them private and do not commit them.
8931

90-
HTTPS uses a pinned GOST v3 container, TLS 1.2/1.3, Basic authentication and HTTP/2 CONNECT. Invalid
91-
credentials receive a decoy page instead of the identifying `407 Proxy Authentication Required`
92-
response. Domain deployments also reject missing or unrelated SNI before exposing a certificate.
93-
GOST's API, metrics, profiling and destination access logs are not exposed.
32+
## Highlights
9433

95-
Domain certificates use Certbot standalone ACME. Public-IP certificates use Let's Encrypt's
96-
short-lived profile and therefore require reliable automatic renewal. Self-signed certificates are
97-
an explicit fallback and require disabling certificate validation in MegaProxy.
34+
- HTTPS CONNECT proxy with TLS 1.2/1.3 and probe-resistant decoy responses
35+
- ACME certificates for DNS names and public IP addresses, plus a self-signed fallback
36+
- SNI-based HTTPS chains through independently selected entry and exit servers
37+
- Restricted SSH forwarding accounts and dynamic SSH jump profiles
38+
- Global HTTPS and SSH users, with safe removal across every managed host
39+
- Inline Ansible Vault encryption that leaves non-secret inventory settings readable
40+
- Idempotent provisioning and integration tests on Ubuntu and Debian
9841

99-
Use a neutral hostname rather than one containing `proxy`, `vpn`, or `gost`. Probe resistance hides
100-
the proxy role from unauthenticated scans; it cannot hide the IP or prevent IP/SNI-based blocking.
42+
See [`inventory.example.yml`](inventory.example.yml) and the
43+
[English](docs/en/README.md) or [Russian](docs/ru/README.md) guide for all options.
10144

102-
### HTTPS chains and SNI routing
45+
## Development
10346

104-
When `settings.https_chains_enabled` is enabled, HTTPS hosts may opt into `chain_entry` and
105-
`chain_exit`. Every valid directed entry-to-exit pair is generated automatically. HAProxy listens
106-
on the single public HTTPS port, inspects TLS SNI without terminating TLS, and forwards each name to
107-
a dedicated loopback GOST listener. For example, `proxy_ru -> proxy_nl` becomes
108-
`proxy-ru-via-proxy-nl.<https_chain_domain>`; underscores are converted to DNS-safe hyphens.
109-
110-
All generated names must resolve to their entry host before `apply`. Chain hosts require domain
111-
ACME certificates; Certbot expands the entry certificate to include every generated SNI hostname.
112-
The exit authenticates entry nodes with a generated machine password that is never included in
113-
summary or client exports. Client exports expose chain routes as ordinary HTTPS proxies on port 443.
114-
An explicit `title` on an `https_chain_pairs` item names that route in client exports and px-manager;
115-
without it, the entry HTTPS service `title` is used. When the service title is also absent, it is
116-
derived from the inventory host name.
117-
118-
## SSH
119-
120-
The inventory distinguishes the provider's initial `bootstrap_user` from the permanent administrator.
121-
The wizard defaults the administrator name to the local OS user and installs the selected public key
122-
whether that account is new or already exists. After a successful full apply, `bootstrap_user` is
123-
removed from inventory automatically and subsequent runs connect as the permanent administrator.
124-
Keep the initial SSH session open until a new administrative login has been tested.
125-
126-
SSH proxy accounts are separate from the administrative account. They cannot open a shell, TTY,
127-
subsystem, agent forwarding, X11, remote forwarding, or a tunnel device. They can only create local
128-
`direct-tcpip` channels. Key authentication is preferred; generated keys are dedicated Ed25519 keys
129-
without a passphrase because MegaProxy currently accepts only unencrypted private keys.
130-
131-
SSH remains recognizable as SSH. Passwords and private keys are included in exported client
132-
profiles, so inventory, `.secrets`, and `.generated` must be treated as sensitive data.
133-
134-
Root SSH login is disabled completely. Password and keyboard-interactive login are disabled globally;
135-
password authentication is enabled only inside the restricted `megaproxy` group. Key-only proxy
136-
accounts have a locked password, so that exception applies effectively only to proxy accounts whose
137-
inventory authentication type is `password`. The administrator is key-only and receives sudo access.
138-
139-
## Jump chains
140-
141-
There is intentionally no `jump_pairs` section. Given SSH hosts A, B, and C, the CLI can produce all
142-
directed combinations `A -> B`, `A -> C`, `B -> A`, and so on. A host is never its own jump. Each
143-
side may use a different user and authentication method.
144-
145-
This flexible model cannot apply pair-specific `PermitOpen` or source-IP firewall rules. Those
146-
restrictions require declaring exact pairs and contradict dynamic chains. Every SSH account remains
147-
restricted to local TCP forwarding and no interactive session.
148-
149-
## Security notes
47+
```shell
48+
./mega-proxy check
49+
```
15050

151-
- Inventory and exports have mode `0600`, but are plaintext local secrets, not a secret manager.
152-
- Use one account/key per person or device so credentials can be revoked independently.
153-
- Verify SSH host fingerprints in MegaProxy through a trusted channel on first connection.
154-
- Review `.generated/megaproxy-profiles.json` before transferring it and delete it after import.
155-
- Provider firewalls must match the host firewall; the project only manages UFW inside the VM.
156-
- Administrative SSH ports are allowed before UFW is enabled to reduce lockout risk.
51+
This runs Ruff, pytest, Python byte-compilation and Ansible syntax checks with dependencies locked
52+
in `uv.lock`.
15753

158-
See `inventory.example.yml` for the complete data shape.
159-
160-
## Continuous integration
161-
162-
The GitHub Actions workflow runs the same `./mega-proxy check` command available locally. It verifies
163-
Ruff, pytest, Python byte-compilation, and Ansible syntax on every push and pull request using the
164-
locked dependency set. It needs no inventory, secrets, network hosts, or privileged containers.
54+
## License
16555

166-
`Host provisioning` additionally creates an isolated privileged LXD system and applies the real
167-
playbook. It checks systemd, Docker, UFW, SSH forwarding, GOST, the HTTPS decoy, authenticated
168-
CONNECT, and a second idempotent run. Ubuntu 24.04 runs on pushes and pull requests. A scheduled or
169-
manually dispatched Debian 12 job provisions two hosts and verifies an SSH Jump tunnel between
170-
them. CI uses self-signed TLS because hosted runners do not have a stable public address for ACME.
56+
See [LICENSE](LICENSE).

0 commit comments

Comments
 (0)