alle-proxy 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- alle_proxy-0.1.0/.github/workflows/ci.yml +35 -0
- alle_proxy-0.1.0/.github/workflows/publish.yml +77 -0
- alle_proxy-0.1.0/.gitignore +14 -0
- alle_proxy-0.1.0/LICENSE +21 -0
- alle_proxy-0.1.0/PKG-INFO +286 -0
- alle_proxy-0.1.0/README.md +266 -0
- alle_proxy-0.1.0/THIRD_PARTY_NOTICES.md +43 -0
- alle_proxy-0.1.0/assets/wordmark.svg +37 -0
- alle_proxy-0.1.0/docs/cli-reference.md +342 -0
- alle_proxy-0.1.0/docs/vpn-provider-research.md +66 -0
- alle_proxy-0.1.0/pyproject.toml +46 -0
- alle_proxy-0.1.0/scripts/gen_singbox_checksums.py +45 -0
- alle_proxy-0.1.0/src/alle/__init__.py +8 -0
- alle_proxy-0.1.0/src/alle/__main__.py +4 -0
- alle_proxy-0.1.0/src/alle/applog.py +73 -0
- alle_proxy-0.1.0/src/alle/cli.py +499 -0
- alle_proxy-0.1.0/src/alle/constants.py +28 -0
- alle_proxy-0.1.0/src/alle/credentials.py +84 -0
- alle_proxy-0.1.0/src/alle/daemon.py +193 -0
- alle_proxy-0.1.0/src/alle/engine.py +153 -0
- alle_proxy-0.1.0/src/alle/geo.py +45 -0
- alle_proxy-0.1.0/src/alle/locations.py +93 -0
- alle_proxy-0.1.0/src/alle/metrics.py +152 -0
- alle_proxy-0.1.0/src/alle/output.py +305 -0
- alle_proxy-0.1.0/src/alle/paths.py +16 -0
- alle_proxy-0.1.0/src/alle/probe.py +139 -0
- alle_proxy-0.1.0/src/alle/providers.py +301 -0
- alle_proxy-0.1.0/src/alle/reconnect.py +161 -0
- alle_proxy-0.1.0/src/alle/service.py +554 -0
- alle_proxy-0.1.0/src/alle/singbox.py +361 -0
- alle_proxy-0.1.0/src/alle/state.py +387 -0
- alle_proxy-0.1.0/src/alle/throughput.py +170 -0
- alle_proxy-0.1.0/src/alle/wgconf.py +173 -0
- alle_proxy-0.1.0/tests/conftest.py +16 -0
- alle_proxy-0.1.0/tests/test_auth_input.py +60 -0
- alle_proxy-0.1.0/tests/test_cli.py +295 -0
- alle_proxy-0.1.0/tests/test_credentials.py +38 -0
- alle_proxy-0.1.0/tests/test_daemon.py +47 -0
- alle_proxy-0.1.0/tests/test_engine.py +156 -0
- alle_proxy-0.1.0/tests/test_geo.py +30 -0
- alle_proxy-0.1.0/tests/test_locations.py +83 -0
- alle_proxy-0.1.0/tests/test_metrics.py +85 -0
- alle_proxy-0.1.0/tests/test_output.py +152 -0
- alle_proxy-0.1.0/tests/test_platform.py +53 -0
- alle_proxy-0.1.0/tests/test_probe.py +147 -0
- alle_proxy-0.1.0/tests/test_providers.py +244 -0
- alle_proxy-0.1.0/tests/test_reconnect.py +204 -0
- alle_proxy-0.1.0/tests/test_singbox.py +65 -0
- alle_proxy-0.1.0/tests/test_state.py +157 -0
- alle_proxy-0.1.0/tests/test_test.py +210 -0
- alle_proxy-0.1.0/tests/test_throughput.py +100 -0
- alle_proxy-0.1.0/tests/test_version.py +25 -0
- alle_proxy-0.1.0/tests/test_wgconf.py +99 -0
- alle_proxy-0.1.0/uv.lock +385 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on: [push, pull_request]
|
|
4
|
+
|
|
5
|
+
jobs:
|
|
6
|
+
lint:
|
|
7
|
+
runs-on: ubuntu-latest
|
|
8
|
+
steps:
|
|
9
|
+
- uses: actions/checkout@v7
|
|
10
|
+
- uses: actions/setup-python@v6
|
|
11
|
+
with:
|
|
12
|
+
python-version: "3.14"
|
|
13
|
+
- uses: astral-sh/setup-uv@v8.2.0
|
|
14
|
+
with:
|
|
15
|
+
cache-suffix: lint-py3.14
|
|
16
|
+
- run: uv sync --all-extras
|
|
17
|
+
- name: Check lint
|
|
18
|
+
run: uv run ruff check
|
|
19
|
+
|
|
20
|
+
test:
|
|
21
|
+
runs-on: ubuntu-latest
|
|
22
|
+
strategy:
|
|
23
|
+
matrix:
|
|
24
|
+
python-version: ["3.10", "3.11", "3.12", "3.13", "3.14"]
|
|
25
|
+
steps:
|
|
26
|
+
- uses: actions/checkout@v7
|
|
27
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
28
|
+
uses: actions/setup-python@v6
|
|
29
|
+
with:
|
|
30
|
+
python-version: ${{ matrix.python-version }}
|
|
31
|
+
- uses: astral-sh/setup-uv@v8.2.0
|
|
32
|
+
with:
|
|
33
|
+
cache-suffix: test-py${{ matrix.python-version }}
|
|
34
|
+
- run: uv sync --all-extras
|
|
35
|
+
- run: uv run pytest -q
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- "v*"
|
|
7
|
+
|
|
8
|
+
jobs:
|
|
9
|
+
build:
|
|
10
|
+
runs-on: ubuntu-latest
|
|
11
|
+
steps:
|
|
12
|
+
- uses: actions/checkout@v7
|
|
13
|
+
|
|
14
|
+
- uses: actions/setup-python@v6
|
|
15
|
+
with:
|
|
16
|
+
python-version: "3.14"
|
|
17
|
+
|
|
18
|
+
- name: Install uv
|
|
19
|
+
uses: astral-sh/setup-uv@v8.2.0
|
|
20
|
+
with:
|
|
21
|
+
cache-suffix: publish-py3.14
|
|
22
|
+
|
|
23
|
+
- name: Verify tag matches pyproject.toml version
|
|
24
|
+
run: |
|
|
25
|
+
tag="${GITHUB_REF_NAME#v}"
|
|
26
|
+
pkg=$(python -c "import tomllib; print(tomllib.load(open('pyproject.toml','rb'))['project']['version'])")
|
|
27
|
+
if [ "$tag" != "$pkg" ]; then
|
|
28
|
+
echo "::error::tag '$GITHUB_REF_NAME' (normalized '$tag') does not match pyproject.toml version '$pkg'"
|
|
29
|
+
exit 1
|
|
30
|
+
fi
|
|
31
|
+
|
|
32
|
+
- name: Build sdist + wheel
|
|
33
|
+
run: uv build
|
|
34
|
+
|
|
35
|
+
- name: Upload artifacts
|
|
36
|
+
uses: actions/upload-artifact@v7
|
|
37
|
+
with:
|
|
38
|
+
name: dist
|
|
39
|
+
path: dist/
|
|
40
|
+
|
|
41
|
+
publish-pypi:
|
|
42
|
+
needs: build
|
|
43
|
+
runs-on: ubuntu-latest
|
|
44
|
+
environment:
|
|
45
|
+
name: pypi
|
|
46
|
+
url: https://pypi.org/p/alle-proxy
|
|
47
|
+
permissions:
|
|
48
|
+
# Required for PyPI Trusted Publishing (OIDC).
|
|
49
|
+
# Configure the trusted publisher on PyPI before the first tag push.
|
|
50
|
+
id-token: write
|
|
51
|
+
steps:
|
|
52
|
+
- name: Download artifacts
|
|
53
|
+
uses: actions/download-artifact@v8
|
|
54
|
+
with:
|
|
55
|
+
name: dist
|
|
56
|
+
path: dist/
|
|
57
|
+
|
|
58
|
+
- name: Publish to PyPI
|
|
59
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
60
|
+
|
|
61
|
+
github-release:
|
|
62
|
+
needs: publish-pypi
|
|
63
|
+
runs-on: ubuntu-latest
|
|
64
|
+
permissions:
|
|
65
|
+
contents: write
|
|
66
|
+
steps:
|
|
67
|
+
- name: Download artifacts
|
|
68
|
+
uses: actions/download-artifact@v8
|
|
69
|
+
with:
|
|
70
|
+
name: dist
|
|
71
|
+
path: dist/
|
|
72
|
+
|
|
73
|
+
- name: Create GitHub Release
|
|
74
|
+
uses: softprops/action-gh-release@v3
|
|
75
|
+
with:
|
|
76
|
+
files: dist/*
|
|
77
|
+
generate_release_notes: true
|
alle_proxy-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 zydo and other alle contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: alle-proxy
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: The unofficial, universal VPN client: manage multiple VPN providers and locations in one place through a single sing-box process, with rule-based routing planned. CLI today; web UI and menu-bar GUI planned.
|
|
5
|
+
Project-URL: Homepage, https://github.com/zydo/alle
|
|
6
|
+
Project-URL: Issues, https://github.com/zydo/alle/issues
|
|
7
|
+
Author: zydo
|
|
8
|
+
License-Expression: MIT
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Keywords: gateway,nordvpn,proxy,sing-box,vpn,wireguard
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Classifier: Operating System :: MacOS
|
|
13
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Topic :: System :: Networking
|
|
16
|
+
Requires-Python: >=3.10
|
|
17
|
+
Requires-Dist: pycountry>=23.12
|
|
18
|
+
Requires-Dist: pyyaml>=6.0
|
|
19
|
+
Description-Content-Type: text/markdown
|
|
20
|
+
|
|
21
|
+
<p align="center">
|
|
22
|
+
<img src="assets/wordmark.svg" alt="alle" width="320">
|
|
23
|
+
</p>
|
|
24
|
+
|
|
25
|
+
<p align="center">
|
|
26
|
+
<a href="https://github.com/zydo/alle/actions/workflows/ci.yml"><img src="https://github.com/zydo/alle/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
|
|
27
|
+
<a href="https://pypi.org/project/alle-proxy/"><img src="https://img.shields.io/pypi/v/alle-proxy.svg" alt="PyPI"></a>
|
|
28
|
+
</p>
|
|
29
|
+
|
|
30
|
+
# alle
|
|
31
|
+
|
|
32
|
+
An unofficial but more powerful VPN client for multiple VPN providers.
|
|
33
|
+
|
|
34
|
+
# Why `alle`
|
|
35
|
+
|
|
36
|
+
Most VPN clients are built around one global idea: connect this device to a single
|
|
37
|
+
VPN server, then send everything through it until you disconnect or switch.
|
|
38
|
+
|
|
39
|
+
That is not enough when different resources need to appear from different regions
|
|
40
|
+
— a geo-fenced stream, a bank that blocks foreign IPs, a region-locked test
|
|
41
|
+
environment. Switching origins means disconnecting from one server and reconnecting
|
|
42
|
+
to another, and the official client on one machine usually cannot keep several
|
|
43
|
+
locations active at once anyway.
|
|
44
|
+
|
|
45
|
+
`alle` keeps multiple VPN exits live at the same time, from one provider or mixed
|
|
46
|
+
across several. Say you want a US exit, a UK exit, and a Japan exit at once —
|
|
47
|
+
NordVPN for the US and Japan, ProtonVPN for the UK:
|
|
48
|
+
|
|
49
|
+
```text
|
|
50
|
+
streaming + admin ──► `alle` ──► United States (NordVPN)
|
|
51
|
+
test runner ──► `alle` ──► Japan (NordVPN)
|
|
52
|
+
bank login ──► `alle` ──► United Kingdom (Proton VPN)
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Each app points at the exit it needs; they run concurrently and independently, so
|
|
56
|
+
opening the bank never disturbs the stream.
|
|
57
|
+
|
|
58
|
+
In short: not one global location you keep switching, but several exits alive at
|
|
59
|
+
once, each used where it is needed.
|
|
60
|
+
|
|
61
|
+
## What `alle` does
|
|
62
|
+
|
|
63
|
+
`alle` runs multiple VPN exits side by side. Each exit is exposed as its own
|
|
64
|
+
local HTTP+SOCKS proxy on `127.0.0.1:<port>`. A planned single HTTP+SOCKS entry
|
|
65
|
+
point will route traffic by rule to a VPN exit or to direct outbound with no
|
|
66
|
+
proxy. Instead of changing your whole machine's VPN location, you point each app,
|
|
67
|
+
browser profile, script, or test job at the path it needs.
|
|
68
|
+
|
|
69
|
+
Under the hood, `alle` manages one
|
|
70
|
+
[`sing-box`](https://github.com/SagerNet/sing-box) process. Each channel becomes
|
|
71
|
+
one local proxy inbound routed through one WireGuard VPN peer. Channels can come
|
|
72
|
+
from different providers, so a NordVPN exit and a Proton VPN `.conf` import can
|
|
73
|
+
run at the same time.
|
|
74
|
+
|
|
75
|
+
## Current status
|
|
76
|
+
|
|
77
|
+
`alle` is usable today as a CLI-first client for per-app/per-workflow VPN exits.
|
|
78
|
+
|
|
79
|
+
**Providers**
|
|
80
|
+
|
|
81
|
+
| Provider | Support |
|
|
82
|
+
| ---------- | ------------------------------------------------------------------------- |
|
|
83
|
+
| NordVPN | Token/API setup, location selection, automatic WireGuard channel creation |
|
|
84
|
+
| Proton VPN | WireGuard `.conf` import |
|
|
85
|
+
|
|
86
|
+
**Platforms**
|
|
87
|
+
|
|
88
|
+
| Platform | Support |
|
|
89
|
+
| -------- | --------- |
|
|
90
|
+
| macOS | Supported |
|
|
91
|
+
| Linux | Supported |
|
|
92
|
+
| Windows | Planned |
|
|
93
|
+
|
|
94
|
+
**Features**
|
|
95
|
+
|
|
96
|
+
| Phase | Status |
|
|
97
|
+
| ----------------- | ---------------------------------------------------------------------- |
|
|
98
|
+
| Core CLI | Providers, channels, per-channel proxies, status, tests, logs, metrics |
|
|
99
|
+
| Routing | Planned |
|
|
100
|
+
| Web UI | Planned |
|
|
101
|
+
| Desktop companion | Planned |
|
|
102
|
+
| Distribution | PyPI CLI package; native installers planned |
|
|
103
|
+
|
|
104
|
+
## Install
|
|
105
|
+
|
|
106
|
+
`alle` requires Python 3.10 or newer.
|
|
107
|
+
|
|
108
|
+
With `pip`:
|
|
109
|
+
|
|
110
|
+
```bash
|
|
111
|
+
python -m pip install alle-proxy
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
With `pipx`:
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
pipx install alle-proxy
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
With `uv` as an installed tool:
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
uv tool install alle-proxy
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
Or run it directly with `uvx`:
|
|
127
|
+
|
|
128
|
+
```bash
|
|
129
|
+
uvx --from alle-proxy alle --help
|
|
130
|
+
```
|
|
131
|
+
|
|
132
|
+
After installation:
|
|
133
|
+
|
|
134
|
+
```bash
|
|
135
|
+
alle version
|
|
136
|
+
alle --help
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
## Quick start
|
|
140
|
+
|
|
141
|
+
Add a provider, create a channel, start the runtime, then use the channel's local
|
|
142
|
+
proxy port.
|
|
143
|
+
|
|
144
|
+
```bash
|
|
145
|
+
alle providers add nordvpn
|
|
146
|
+
alle channels add nordvpn --country "United States"
|
|
147
|
+
alle start
|
|
148
|
+
alle channels ls
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
`alle channels ls` prints the local proxy port for each channel:
|
|
152
|
+
|
|
153
|
+
```text
|
|
154
|
+
PROVIDER NAME PORT COUNTRY CITY
|
|
155
|
+
-------- --------------- ------ ------------- ----------
|
|
156
|
+
NordVPN united_states_1 :53124 United States (Any City)
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
Use that port from any tool or app that supports an HTTP or SOCKS proxy:
|
|
160
|
+
|
|
161
|
+
```bash
|
|
162
|
+
curl -x http://127.0.0.1:53124 https://api.ipify.org
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
Check health and traffic:
|
|
166
|
+
|
|
167
|
+
```bash
|
|
168
|
+
alle status
|
|
169
|
+
alle test
|
|
170
|
+
alle metrics
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
**Provider setup**
|
|
174
|
+
|
|
175
|
+
`alle` supports two provider setup styles today:
|
|
176
|
+
|
|
177
|
+
**NordVPN** uses an access token:
|
|
178
|
+
|
|
179
|
+
```bash
|
|
180
|
+
alle providers add nordvpn
|
|
181
|
+
alle locations nordvpn
|
|
182
|
+
alle locations nordvpn --country "United States"
|
|
183
|
+
alle channels add nordvpn --country "United States" --city "Seattle"
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
**Proton VPN** uses WireGuard config files downloaded from Proton:
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
alle providers add protonvpn
|
|
190
|
+
alle channels add protonvpn --config ~/Downloads/wg-US-CA-842.conf
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
Re-importing the same `.conf` file updates that channel in place, keeping the
|
|
194
|
+
same channel id and local port.
|
|
195
|
+
|
|
196
|
+
**Common commands**
|
|
197
|
+
|
|
198
|
+
Useful commands after setup:
|
|
199
|
+
|
|
200
|
+
```bash
|
|
201
|
+
alle providers ls
|
|
202
|
+
alle channels ls
|
|
203
|
+
alle status
|
|
204
|
+
alle test
|
|
205
|
+
alle metrics
|
|
206
|
+
alle logs
|
|
207
|
+
alle stop
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
Most read commands support `--json` for scripts:
|
|
211
|
+
|
|
212
|
+
```bash
|
|
213
|
+
alle status --json
|
|
214
|
+
alle channels ls --json
|
|
215
|
+
alle metrics --json
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
For the complete command reference, see the
|
|
219
|
+
[CLI Reference](docs/cli-reference.md).
|
|
220
|
+
|
|
221
|
+
## Rule-based routing
|
|
222
|
+
|
|
223
|
+
To be implemented.
|
|
224
|
+
|
|
225
|
+
## How it works
|
|
226
|
+
|
|
227
|
+
- `alle` keeps its local state under `~/.alle/`, or under `$ALLE_HOME` when that
|
|
228
|
+
environment variable is set. This includes providers, channels, credentials,
|
|
229
|
+
metrics, generated config, logs, and runtime files.
|
|
230
|
+
|
|
231
|
+
- `alle` manages one [`sing-box`](https://github.com/SagerNet/sing-box) process
|
|
232
|
+
instead of starting one VPN process per channel. The generated config contains
|
|
233
|
+
one local HTTP+SOCKS inbound per channel.
|
|
234
|
+
|
|
235
|
+
- Each channel routes to one WireGuard peer. NordVPN channels are created from
|
|
236
|
+
the provider API; Proton VPN channels are created by importing a WireGuard
|
|
237
|
+
`.conf` file. After creation, both behave the same way.
|
|
238
|
+
|
|
239
|
+
- WireGuard is connectionless, so `alle` does not model channels as connected or
|
|
240
|
+
disconnected. A channel exists in config; its health comes from the latest
|
|
241
|
+
probe.
|
|
242
|
+
|
|
243
|
+
- Local proxy ports are assigned by the OS and stored in state. Use
|
|
244
|
+
`alle channels ls` to see the current ports.
|
|
245
|
+
|
|
246
|
+
- The background runtime applies state changes, keeps the `sing-box` process in
|
|
247
|
+
sync, probes channel health, and records per-channel traffic totals.
|
|
248
|
+
|
|
249
|
+
- `alle` uses a pinned upstream `sing-box` release and verifies its checksum
|
|
250
|
+
before running it.
|
|
251
|
+
|
|
252
|
+
## Security and privacy
|
|
253
|
+
|
|
254
|
+
- Provider credentials and WireGuard private keys are stored locally under
|
|
255
|
+
`~/.alle/` or `$ALLE_HOME`.
|
|
256
|
+
- Credential and state files are written with private file permissions where
|
|
257
|
+
supported by the OS.
|
|
258
|
+
- `alle` does not read provider tokens from environment variables; credentials
|
|
259
|
+
are added explicitly with `alle providers add`.
|
|
260
|
+
- `alle` downloads a pinned upstream `sing-box` release and verifies its checksum
|
|
261
|
+
before running it.
|
|
262
|
+
- Local proxy ports bind to loopback. Traffic only uses a VPN exit when an app is
|
|
263
|
+
pointed at one of those proxies.
|
|
264
|
+
|
|
265
|
+
## Roadmap and non-goals
|
|
266
|
+
|
|
267
|
+
Planned next steps:
|
|
268
|
+
|
|
269
|
+
- Rule-based routing through a single local HTTP+SOCKS entry point.
|
|
270
|
+
- More WireGuard-capable VPN providers. See
|
|
271
|
+
[VPN Provider Research](docs/vpn-provider-research.md).
|
|
272
|
+
- Web UI for managing channels and routing rules.
|
|
273
|
+
- Desktop companion with OS-level VPN integration.
|
|
274
|
+
- Windows support and broader distribution.
|
|
275
|
+
|
|
276
|
+
Non-goals:
|
|
277
|
+
|
|
278
|
+
- OpenVPN or IKEv2/IPsec support.
|
|
279
|
+
- VPN providers without usable WireGuard support, such as ExpressVPN, HideMyAss,
|
|
280
|
+
Perfect Privacy, Privado, SlickVPN, VPN.ac/VPNSecure, and Giganews.
|
|
281
|
+
- SOCKS5-only or unencrypted proxy providers.
|
|
282
|
+
- Bundling `sing-box` inside the Python package.
|
|
283
|
+
|
|
284
|
+
## License
|
|
285
|
+
|
|
286
|
+
MIT
|
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="assets/wordmark.svg" alt="alle" width="320">
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
<p align="center">
|
|
6
|
+
<a href="https://github.com/zydo/alle/actions/workflows/ci.yml"><img src="https://github.com/zydo/alle/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
|
|
7
|
+
<a href="https://pypi.org/project/alle-proxy/"><img src="https://img.shields.io/pypi/v/alle-proxy.svg" alt="PyPI"></a>
|
|
8
|
+
</p>
|
|
9
|
+
|
|
10
|
+
# alle
|
|
11
|
+
|
|
12
|
+
An unofficial but more powerful VPN client for multiple VPN providers.
|
|
13
|
+
|
|
14
|
+
# Why `alle`
|
|
15
|
+
|
|
16
|
+
Most VPN clients are built around one global idea: connect this device to a single
|
|
17
|
+
VPN server, then send everything through it until you disconnect or switch.
|
|
18
|
+
|
|
19
|
+
That is not enough when different resources need to appear from different regions
|
|
20
|
+
— a geo-fenced stream, a bank that blocks foreign IPs, a region-locked test
|
|
21
|
+
environment. Switching origins means disconnecting from one server and reconnecting
|
|
22
|
+
to another, and the official client on one machine usually cannot keep several
|
|
23
|
+
locations active at once anyway.
|
|
24
|
+
|
|
25
|
+
`alle` keeps multiple VPN exits live at the same time, from one provider or mixed
|
|
26
|
+
across several. Say you want a US exit, a UK exit, and a Japan exit at once —
|
|
27
|
+
NordVPN for the US and Japan, ProtonVPN for the UK:
|
|
28
|
+
|
|
29
|
+
```text
|
|
30
|
+
streaming + admin ──► `alle` ──► United States (NordVPN)
|
|
31
|
+
test runner ──► `alle` ──► Japan (NordVPN)
|
|
32
|
+
bank login ──► `alle` ──► United Kingdom (Proton VPN)
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Each app points at the exit it needs; they run concurrently and independently, so
|
|
36
|
+
opening the bank never disturbs the stream.
|
|
37
|
+
|
|
38
|
+
In short: not one global location you keep switching, but several exits alive at
|
|
39
|
+
once, each used where it is needed.
|
|
40
|
+
|
|
41
|
+
## What `alle` does
|
|
42
|
+
|
|
43
|
+
`alle` runs multiple VPN exits side by side. Each exit is exposed as its own
|
|
44
|
+
local HTTP+SOCKS proxy on `127.0.0.1:<port>`. A planned single HTTP+SOCKS entry
|
|
45
|
+
point will route traffic by rule to a VPN exit or to direct outbound with no
|
|
46
|
+
proxy. Instead of changing your whole machine's VPN location, you point each app,
|
|
47
|
+
browser profile, script, or test job at the path it needs.
|
|
48
|
+
|
|
49
|
+
Under the hood, `alle` manages one
|
|
50
|
+
[`sing-box`](https://github.com/SagerNet/sing-box) process. Each channel becomes
|
|
51
|
+
one local proxy inbound routed through one WireGuard VPN peer. Channels can come
|
|
52
|
+
from different providers, so a NordVPN exit and a Proton VPN `.conf` import can
|
|
53
|
+
run at the same time.
|
|
54
|
+
|
|
55
|
+
## Current status
|
|
56
|
+
|
|
57
|
+
`alle` is usable today as a CLI-first client for per-app/per-workflow VPN exits.
|
|
58
|
+
|
|
59
|
+
**Providers**
|
|
60
|
+
|
|
61
|
+
| Provider | Support |
|
|
62
|
+
| ---------- | ------------------------------------------------------------------------- |
|
|
63
|
+
| NordVPN | Token/API setup, location selection, automatic WireGuard channel creation |
|
|
64
|
+
| Proton VPN | WireGuard `.conf` import |
|
|
65
|
+
|
|
66
|
+
**Platforms**
|
|
67
|
+
|
|
68
|
+
| Platform | Support |
|
|
69
|
+
| -------- | --------- |
|
|
70
|
+
| macOS | Supported |
|
|
71
|
+
| Linux | Supported |
|
|
72
|
+
| Windows | Planned |
|
|
73
|
+
|
|
74
|
+
**Features**
|
|
75
|
+
|
|
76
|
+
| Phase | Status |
|
|
77
|
+
| ----------------- | ---------------------------------------------------------------------- |
|
|
78
|
+
| Core CLI | Providers, channels, per-channel proxies, status, tests, logs, metrics |
|
|
79
|
+
| Routing | Planned |
|
|
80
|
+
| Web UI | Planned |
|
|
81
|
+
| Desktop companion | Planned |
|
|
82
|
+
| Distribution | PyPI CLI package; native installers planned |
|
|
83
|
+
|
|
84
|
+
## Install
|
|
85
|
+
|
|
86
|
+
`alle` requires Python 3.10 or newer.
|
|
87
|
+
|
|
88
|
+
With `pip`:
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
python -m pip install alle-proxy
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
With `pipx`:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
pipx install alle-proxy
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
With `uv` as an installed tool:
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
uv tool install alle-proxy
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
Or run it directly with `uvx`:
|
|
107
|
+
|
|
108
|
+
```bash
|
|
109
|
+
uvx --from alle-proxy alle --help
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
After installation:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
alle version
|
|
116
|
+
alle --help
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
## Quick start
|
|
120
|
+
|
|
121
|
+
Add a provider, create a channel, start the runtime, then use the channel's local
|
|
122
|
+
proxy port.
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
alle providers add nordvpn
|
|
126
|
+
alle channels add nordvpn --country "United States"
|
|
127
|
+
alle start
|
|
128
|
+
alle channels ls
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
`alle channels ls` prints the local proxy port for each channel:
|
|
132
|
+
|
|
133
|
+
```text
|
|
134
|
+
PROVIDER NAME PORT COUNTRY CITY
|
|
135
|
+
-------- --------------- ------ ------------- ----------
|
|
136
|
+
NordVPN united_states_1 :53124 United States (Any City)
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Use that port from any tool or app that supports an HTTP or SOCKS proxy:
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
curl -x http://127.0.0.1:53124 https://api.ipify.org
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Check health and traffic:
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
alle status
|
|
149
|
+
alle test
|
|
150
|
+
alle metrics
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
**Provider setup**
|
|
154
|
+
|
|
155
|
+
`alle` supports two provider setup styles today:
|
|
156
|
+
|
|
157
|
+
**NordVPN** uses an access token:
|
|
158
|
+
|
|
159
|
+
```bash
|
|
160
|
+
alle providers add nordvpn
|
|
161
|
+
alle locations nordvpn
|
|
162
|
+
alle locations nordvpn --country "United States"
|
|
163
|
+
alle channels add nordvpn --country "United States" --city "Seattle"
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
**Proton VPN** uses WireGuard config files downloaded from Proton:
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
alle providers add protonvpn
|
|
170
|
+
alle channels add protonvpn --config ~/Downloads/wg-US-CA-842.conf
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
Re-importing the same `.conf` file updates that channel in place, keeping the
|
|
174
|
+
same channel id and local port.
|
|
175
|
+
|
|
176
|
+
**Common commands**
|
|
177
|
+
|
|
178
|
+
Useful commands after setup:
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
alle providers ls
|
|
182
|
+
alle channels ls
|
|
183
|
+
alle status
|
|
184
|
+
alle test
|
|
185
|
+
alle metrics
|
|
186
|
+
alle logs
|
|
187
|
+
alle stop
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
Most read commands support `--json` for scripts:
|
|
191
|
+
|
|
192
|
+
```bash
|
|
193
|
+
alle status --json
|
|
194
|
+
alle channels ls --json
|
|
195
|
+
alle metrics --json
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
For the complete command reference, see the
|
|
199
|
+
[CLI Reference](docs/cli-reference.md).
|
|
200
|
+
|
|
201
|
+
## Rule-based routing
|
|
202
|
+
|
|
203
|
+
To be implemented.
|
|
204
|
+
|
|
205
|
+
## How it works
|
|
206
|
+
|
|
207
|
+
- `alle` keeps its local state under `~/.alle/`, or under `$ALLE_HOME` when that
|
|
208
|
+
environment variable is set. This includes providers, channels, credentials,
|
|
209
|
+
metrics, generated config, logs, and runtime files.
|
|
210
|
+
|
|
211
|
+
- `alle` manages one [`sing-box`](https://github.com/SagerNet/sing-box) process
|
|
212
|
+
instead of starting one VPN process per channel. The generated config contains
|
|
213
|
+
one local HTTP+SOCKS inbound per channel.
|
|
214
|
+
|
|
215
|
+
- Each channel routes to one WireGuard peer. NordVPN channels are created from
|
|
216
|
+
the provider API; Proton VPN channels are created by importing a WireGuard
|
|
217
|
+
`.conf` file. After creation, both behave the same way.
|
|
218
|
+
|
|
219
|
+
- WireGuard is connectionless, so `alle` does not model channels as connected or
|
|
220
|
+
disconnected. A channel exists in config; its health comes from the latest
|
|
221
|
+
probe.
|
|
222
|
+
|
|
223
|
+
- Local proxy ports are assigned by the OS and stored in state. Use
|
|
224
|
+
`alle channels ls` to see the current ports.
|
|
225
|
+
|
|
226
|
+
- The background runtime applies state changes, keeps the `sing-box` process in
|
|
227
|
+
sync, probes channel health, and records per-channel traffic totals.
|
|
228
|
+
|
|
229
|
+
- `alle` uses a pinned upstream `sing-box` release and verifies its checksum
|
|
230
|
+
before running it.
|
|
231
|
+
|
|
232
|
+
## Security and privacy
|
|
233
|
+
|
|
234
|
+
- Provider credentials and WireGuard private keys are stored locally under
|
|
235
|
+
`~/.alle/` or `$ALLE_HOME`.
|
|
236
|
+
- Credential and state files are written with private file permissions where
|
|
237
|
+
supported by the OS.
|
|
238
|
+
- `alle` does not read provider tokens from environment variables; credentials
|
|
239
|
+
are added explicitly with `alle providers add`.
|
|
240
|
+
- `alle` downloads a pinned upstream `sing-box` release and verifies its checksum
|
|
241
|
+
before running it.
|
|
242
|
+
- Local proxy ports bind to loopback. Traffic only uses a VPN exit when an app is
|
|
243
|
+
pointed at one of those proxies.
|
|
244
|
+
|
|
245
|
+
## Roadmap and non-goals
|
|
246
|
+
|
|
247
|
+
Planned next steps:
|
|
248
|
+
|
|
249
|
+
- Rule-based routing through a single local HTTP+SOCKS entry point.
|
|
250
|
+
- More WireGuard-capable VPN providers. See
|
|
251
|
+
[VPN Provider Research](docs/vpn-provider-research.md).
|
|
252
|
+
- Web UI for managing channels and routing rules.
|
|
253
|
+
- Desktop companion with OS-level VPN integration.
|
|
254
|
+
- Windows support and broader distribution.
|
|
255
|
+
|
|
256
|
+
Non-goals:
|
|
257
|
+
|
|
258
|
+
- OpenVPN or IKEv2/IPsec support.
|
|
259
|
+
- VPN providers without usable WireGuard support, such as ExpressVPN, HideMyAss,
|
|
260
|
+
Perfect Privacy, Privado, SlickVPN, VPN.ac/VPNSecure, and Giganews.
|
|
261
|
+
- SOCKS5-only or unencrypted proxy providers.
|
|
262
|
+
- Bundling `sing-box` inside the Python package.
|
|
263
|
+
|
|
264
|
+
## License
|
|
265
|
+
|
|
266
|
+
MIT
|