v2portal 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.
- v2portal-0.1.0/PKG-INFO +11 -0
- v2portal-0.1.0/README.md +483 -0
- v2portal-0.1.0/pyproject.toml +28 -0
- v2portal-0.1.0/setup.cfg +4 -0
- v2portal-0.1.0/src/v2portal.egg-info/PKG-INFO +11 -0
- v2portal-0.1.0/src/v2portal.egg-info/SOURCES.txt +101 -0
- v2portal-0.1.0/src/v2portal.egg-info/dependency_links.txt +1 -0
- v2portal-0.1.0/src/v2portal.egg-info/entry_points.txt +2 -0
- v2portal-0.1.0/src/v2portal.egg-info/requires.txt +7 -0
- v2portal-0.1.0/src/v2portal.egg-info/top_level.txt +1 -0
- v2portal-0.1.0/src/v2raycli/__init__.py +3 -0
- v2portal-0.1.0/src/v2raycli/__main__.py +4 -0
- v2portal-0.1.0/src/v2raycli/app.py +3146 -0
- v2portal-0.1.0/src/v2raycli/backup.py +172 -0
- v2portal-0.1.0/src/v2raycli/config.py +78 -0
- v2portal-0.1.0/src/v2raycli/connection.py +298 -0
- v2portal-0.1.0/src/v2raycli/diagnostics.py +42 -0
- v2portal-0.1.0/src/v2raycli/engines/__init__.py +48 -0
- v2portal-0.1.0/src/v2raycli/engines/base.py +79 -0
- v2portal-0.1.0/src/v2raycli/engines/binary.py +326 -0
- v2portal-0.1.0/src/v2raycli/engines/singbox.py +622 -0
- v2portal-0.1.0/src/v2raycli/engines/xray.py +439 -0
- v2portal-0.1.0/src/v2raycli/errors.py +16 -0
- v2portal-0.1.0/src/v2raycli/exchange.py +249 -0
- v2portal-0.1.0/src/v2raycli/firewall.py +185 -0
- v2portal-0.1.0/src/v2raycli/geo.py +56 -0
- v2portal-0.1.0/src/v2raycli/models.py +265 -0
- v2portal-0.1.0/src/v2raycli/outbounds/__init__.py +1 -0
- v2portal-0.1.0/src/v2raycli/outbounds/groups.py +782 -0
- v2portal-0.1.0/src/v2raycli/outbounds/manual.py +257 -0
- v2portal-0.1.0/src/v2raycli/outbounds/vpn.py +98 -0
- v2portal-0.1.0/src/v2raycli/routing/__init__.py +1 -0
- v2portal-0.1.0/src/v2raycli/routing/rules.py +121 -0
- v2portal-0.1.0/src/v2raycli/runner.py +102 -0
- v2portal-0.1.0/src/v2raycli/servers.py +458 -0
- v2portal-0.1.0/src/v2raycli/service.py +115 -0
- v2portal-0.1.0/src/v2raycli/storage.py +494 -0
- v2portal-0.1.0/src/v2raycli/subs/__init__.py +1 -0
- v2portal-0.1.0/src/v2raycli/subs/fetcher.py +93 -0
- v2portal-0.1.0/src/v2raycli/subs/health.py +78 -0
- v2portal-0.1.0/src/v2raycli/subs/parser.py +307 -0
- v2portal-0.1.0/src/v2raycli/subs/share.py +681 -0
- v2portal-0.1.0/src/v2raycli/test/__init__.py +1 -0
- v2portal-0.1.0/src/v2raycli/test/latency.py +929 -0
- v2portal-0.1.0/src/v2raycli/traffic.py +70 -0
- v2portal-0.1.0/src/v2raycli/tui/__init__.py +1 -0
- v2portal-0.1.0/src/v2raycli/tui/app_screen.py +99 -0
- v2portal-0.1.0/src/v2raycli/tui/connection_screen.py +89 -0
- v2portal-0.1.0/src/v2raycli/tui/groups_screen.py +44 -0
- v2portal-0.1.0/src/v2raycli/tui/manage.py +422 -0
- v2portal-0.1.0/src/v2raycli/tui/routing_screen.py +260 -0
- v2portal-0.1.0/src/v2raycli/tui/servers_screen.py +136 -0
- v2portal-0.1.0/src/v2raycli/tui/settings_screen.py +117 -0
- v2portal-0.1.0/src/v2raycli/tui/test_screen.py +88 -0
- v2portal-0.1.0/src/v2raycli/tui/widgets.py +128 -0
- v2portal-0.1.0/tests/test_acceptance_flow.py +170 -0
- v2portal-0.1.0/tests/test_app.py +411 -0
- v2portal-0.1.0/tests/test_autoupdate.py +124 -0
- v2portal-0.1.0/tests/test_backup.py +192 -0
- v2portal-0.1.0/tests/test_binary.py +279 -0
- v2portal-0.1.0/tests/test_cli_commands.py +783 -0
- v2portal-0.1.0/tests/test_cli_surface.py +83 -0
- v2portal-0.1.0/tests/test_code_quality.py +45 -0
- v2portal-0.1.0/tests/test_config.py +21 -0
- v2portal-0.1.0/tests/test_config_gen.py +1032 -0
- v2portal-0.1.0/tests/test_connection_errors.py +247 -0
- v2portal-0.1.0/tests/test_controller.py +174 -0
- v2portal-0.1.0/tests/test_diagnostics.py +37 -0
- v2portal-0.1.0/tests/test_engine.py +21 -0
- v2portal-0.1.0/tests/test_errors.py +59 -0
- v2portal-0.1.0/tests/test_exchange.py +286 -0
- v2portal-0.1.0/tests/test_fetcher.py +148 -0
- v2portal-0.1.0/tests/test_firewall.py +226 -0
- v2portal-0.1.0/tests/test_geo.py +48 -0
- v2portal-0.1.0/tests/test_graph_flows.py +149 -0
- v2portal-0.1.0/tests/test_groups.py +523 -0
- v2portal-0.1.0/tests/test_health.py +96 -0
- v2portal-0.1.0/tests/test_latency.py +659 -0
- v2portal-0.1.0/tests/test_manual.py +135 -0
- v2portal-0.1.0/tests/test_models.py +65 -0
- v2portal-0.1.0/tests/test_parser.py +195 -0
- v2portal-0.1.0/tests/test_resolve_refs.py +179 -0
- v2portal-0.1.0/tests/test_routing.py +176 -0
- v2portal-0.1.0/tests/test_runner.py +124 -0
- v2portal-0.1.0/tests/test_servers.py +891 -0
- v2portal-0.1.0/tests/test_service.py +100 -0
- v2portal-0.1.0/tests/test_share.py +217 -0
- v2portal-0.1.0/tests/test_storage.py +362 -0
- v2portal-0.1.0/tests/test_temp_server.py +59 -0
- v2portal-0.1.0/tests/test_traffic.py +184 -0
- v2portal-0.1.0/tests/test_tui_connection.py +201 -0
- v2portal-0.1.0/tests/test_tui_groups.py +53 -0
- v2portal-0.1.0/tests/test_tui_manage.py +95 -0
- v2portal-0.1.0/tests/test_tui_pty.py +93 -0
- v2portal-0.1.0/tests/test_tui_routing.py +348 -0
- v2portal-0.1.0/tests/test_tui_servers.py +111 -0
- v2portal-0.1.0/tests/test_tui_settings.py +72 -0
- v2portal-0.1.0/tests/test_tui_test_screen.py +93 -0
- v2portal-0.1.0/tests/test_tui_widgets.py +98 -0
- v2portal-0.1.0/tests/test_verify_acceptance.py +25 -0
- v2portal-0.1.0/tests/test_verify_engines.py +41 -0
- v2portal-0.1.0/tests/test_vpn.py +77 -0
- v2portal-0.1.0/tests/test_vpn_connect.py +117 -0
v2portal-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: v2portal
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Interactive v2ray CLI client (sing-box + xray-core) with subscriptions, groups, and split routing
|
|
5
|
+
Requires-Python: >=3.10
|
|
6
|
+
Requires-Dist: prompt_toolkit>=3.0
|
|
7
|
+
Requires-Dist: rich>=13.0
|
|
8
|
+
Requires-Dist: httpx[socks]>=0.26
|
|
9
|
+
Requires-Dist: platformdirs>=3.0
|
|
10
|
+
Provides-Extra: dev
|
|
11
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
v2portal-0.1.0/README.md
ADDED
|
@@ -0,0 +1,483 @@
|
|
|
1
|
+
# v2raycli
|
|
2
|
+
|
|
3
|
+
Non-interactive CLI client for v2ray proxy management. It wraps two proxy
|
|
4
|
+
engines — **sing-box** (default) and **xray-core** — behind a single config,
|
|
5
|
+
and lets you add subscriptions/proxies, chain or balance them, test latency,
|
|
6
|
+
and run inbound servers from the command line.
|
|
7
|
+
|
|
8
|
+
Runs on **Linux**, **Windows**, and **Termux (Android)**.
|
|
9
|
+
|
|
10
|
+
## Features
|
|
11
|
+
|
|
12
|
+
- **Dual engine** — sing-box (default) + xray-core, resolved per profile/group.
|
|
13
|
+
xray is used automatically for `ssr` and the `leastLoad` strategy.
|
|
14
|
+
- **Subscriptions** — paste a subscription URL or raw base64/plain payload;
|
|
15
|
+
import, update (deleted nodes are pruned), test a single subscription, and
|
|
16
|
+
auto-update on a schedule (`auto_update_days`).
|
|
17
|
+
- **Protocols** — vmess, vless, trojan, ss, ssr, socks, http, wireguard,
|
|
18
|
+
hysteria2, tuic, plus raw JSON configs. OpenVPN / OpenConnect via the system
|
|
19
|
+
clients.
|
|
20
|
+
- **Groups** — `balancer` (latency / random / roundRobin / leastLoad) and
|
|
21
|
+
`chain` (proxy through proxy).
|
|
22
|
+
- **Split routing** — domain/keyword/regex rules, IP CIDR, and geoip/geosite.
|
|
23
|
+
Rules can target any profile, subscription, group, or server, plus
|
|
24
|
+
`direct` or `block`. Stale rules are auto-cleaned when a profile, group,
|
|
25
|
+
or server is deleted.
|
|
26
|
+
- **LAN proxy inbound** — sing-box serves SOCKS5 *and* HTTP on one port;
|
|
27
|
+
xray exposes SOCKS5 plus HTTP CONNECT on adjacent ports, with optional
|
|
28
|
+
username/password auth.
|
|
29
|
+
- **Outbound testing** — `--probe` separately measures endpoint ICMP/TCP
|
|
30
|
+
reachability with DNS/refusal/timeout classification; `--ws-test` validates
|
|
31
|
+
WS/WSS handshake and ping/pong; `--test` measures real proxy request delay
|
|
32
|
+
through the engine.
|
|
33
|
+
- **Traffic stats** — cumulative per-profile/group up/down usage (sing-box),
|
|
34
|
+
recorded when a server stops.
|
|
35
|
+
- **Config on disk** — a single JSON file in your platform config dir.
|
|
36
|
+
|
|
37
|
+
## Install
|
|
38
|
+
|
|
39
|
+
### pip (Linux / macOS / Termux)
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
pip install .
|
|
43
|
+
# or, for development:
|
|
44
|
+
pip install -e .[dev]
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
> **Tip:** If the `v2raycli` command is not found after install, use
|
|
48
|
+
> `python -m v2raycli` as a fallback, or install with `pipx install .`
|
|
49
|
+
> (install pipx first: `pip install pipx`). `pipx` handles PATH setup
|
|
50
|
+
> automatically.
|
|
51
|
+
|
|
52
|
+
### Termux (Android)
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
pkg update && pkg install python
|
|
56
|
+
pip install .
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
The engine binaries (sing-box / xray) download automatically to
|
|
60
|
+
`~/.config/v2raycli/bin` on first use, with arm64 assets on Termux.
|
|
61
|
+
|
|
62
|
+
> Note: OpenVPN / OpenConnect may require root on Android and are not
|
|
63
|
+
> chainable/balanceable — they run the system client directly.
|
|
64
|
+
|
|
65
|
+
### Windows
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
pip install .
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
After installing, the `v2raycli` command is placed in Python's `Scripts`
|
|
72
|
+
directory (e.g. `%LOCALAPPDATA%\Python\pythonX.Y-64\Scripts`). If the
|
|
73
|
+
command is not found, **one of these will work**:
|
|
74
|
+
|
|
75
|
+
1. Add the `Scripts` folder to your system `PATH` permanently:
|
|
76
|
+
```powershell
|
|
77
|
+
[Environment]::SetEnvironmentVariable(
|
|
78
|
+
"Path",
|
|
79
|
+
$env:Path + ";" + [IO.Path]::Combine([Environment]::GetFolderPath("LocalApplicationData"), "Python", "python$([Environment]::Version.ToString(3))", "Scripts"),
|
|
80
|
+
"User"
|
|
81
|
+
)
|
|
82
|
+
```
|
|
83
|
+
Then restart your terminal.
|
|
84
|
+
|
|
85
|
+
2. Or use `python -m v2raycli` instead of `v2raycli` — this always works
|
|
86
|
+
regardless of PATH.
|
|
87
|
+
|
|
88
|
+
Config lives in `%APPDATA%\v2raycli`. Engine binaries download to
|
|
89
|
+
`%APPDATA%\v2raycli\bin`. When LAN sharing is enabled, allow the program
|
|
90
|
+
through the Windows firewall.
|
|
91
|
+
|
|
92
|
+
### PyInstaller (single folder)
|
|
93
|
+
|
|
94
|
+
A spec is included:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
pip install pyinstaller
|
|
98
|
+
pyinstaller v2raycli.spec
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Engine binaries and geo assets still download on first run.
|
|
102
|
+
|
|
103
|
+
## Quickstart
|
|
104
|
+
|
|
105
|
+
The primary interface is non-interactive and safe for scripts. Run
|
|
106
|
+
`v2raycli --help` or `v2raycli COMMAND --help` for the complete tree. The
|
|
107
|
+
interactive TUI (run `v2raycli` with no arguments) is a modern rich-styled
|
|
108
|
+
panel UI with screens for Connect, a Servers dashboard (live status +
|
|
109
|
+
start/stop), a Groups tree, Subscriptions, Test, Routing, and Settings:
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
v2raycli status
|
|
113
|
+
v2raycli profile list
|
|
114
|
+
v2raycli subscription list
|
|
115
|
+
v2raycli group list
|
|
116
|
+
v2raycli group tree
|
|
117
|
+
v2raycli test latency all
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Every mutating command uses explicit arguments and writes the config only after
|
|
121
|
+
validation. The full command layout is:
|
|
122
|
+
|
|
123
|
+
```text
|
|
124
|
+
profile list | add | rename | edit | remove | export
|
|
125
|
+
subscription list | add | edit | rename | update | remove (aliases: sub, subscriptions)
|
|
126
|
+
group list | add | tree | edit | remove | add-member | remove-member (alias: groups)
|
|
127
|
+
server list | add | edit | start | stop | restart | remove (alias: sv)
|
|
128
|
+
routing list | mode | add | move | enable | disable | remove
|
|
129
|
+
backup create | list | restore
|
|
130
|
+
settings show/set app settings, engine update
|
|
131
|
+
config show | export | import (backup/restore)
|
|
132
|
+
service install | uninstall
|
|
133
|
+
test latency | endpoint | websocket
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
**One ID space, auto-detected references.** Every entity — profile,
|
|
137
|
+
subscription, group, server — has a unique ID from a single counter. Any
|
|
138
|
+
command that takes a *target reference* accepts a **profile, subscription,
|
|
139
|
+
group, or server ID** and detects the type automatically. References are
|
|
140
|
+
resolved at use time: a subscription always contributes its *current*
|
|
141
|
+
profiles, nested groups expand recursively (with dedup and cycle protection),
|
|
142
|
+
and a server member resolves to a socks/http profile through its local
|
|
143
|
+
inbound — so updated subscriptions flow everywhere automatically.
|
|
144
|
+
|
|
145
|
+
Examples:
|
|
146
|
+
|
|
147
|
+
```bash
|
|
148
|
+
# Add a manual profile
|
|
149
|
+
v2raycli profile add socks office-proxy 127.0.0.1 1080
|
|
150
|
+
v2raycli profile add share us-node 'vless://...'
|
|
151
|
+
v2raycli profile edit ID --name "Office proxy" --host 10.0.0.2
|
|
152
|
+
|
|
153
|
+
# Import a subscription
|
|
154
|
+
v2raycli subscription add my-provider https://example.com/sub
|
|
155
|
+
v2raycli subscription edit SUB_ID --name 'Renamed provider'
|
|
156
|
+
v2raycli profile list --subscription SUB_ID
|
|
157
|
+
|
|
158
|
+
# Groups accept profiles, subscriptions, groups, and servers (auto-detected)
|
|
159
|
+
v2raycli group add balancer fastest PROFILE_A SUB_ID GROUP_B SERVER_ID --strategy latency
|
|
160
|
+
v2raycli group add chain chained PROFILE_A PROFILE_B
|
|
161
|
+
v2raycli group edit GROUP_ID --strategy random
|
|
162
|
+
|
|
163
|
+
# Render the nested group/subscription/server hierarchy
|
|
164
|
+
v2raycli group tree
|
|
165
|
+
|
|
166
|
+
# Add a running server as a local socks/http profile
|
|
167
|
+
v2raycli profile add server via-server SERVER_ID
|
|
168
|
+
|
|
169
|
+
# Start a proxy server on a port — REF is auto-detected
|
|
170
|
+
v2raycli server add --port 1080 REF --name 'US proxy'
|
|
171
|
+
v2raycli server edit SERVER_ID --outbound REF
|
|
172
|
+
v2raycli server start SERVER_ID
|
|
173
|
+
|
|
174
|
+
# Servers run in the background and survive terminal close
|
|
175
|
+
v2raycli server list
|
|
176
|
+
v2raycli sv stop SERVER_ID
|
|
177
|
+
v2raycli sv restart --all
|
|
178
|
+
|
|
179
|
+
# View and change settings
|
|
180
|
+
v2raycli settings
|
|
181
|
+
v2raycli settings test-url
|
|
182
|
+
v2raycli settings mixed-port 1081
|
|
183
|
+
v2raycli settings default-engine xray
|
|
184
|
+
v2raycli settings engine update both
|
|
185
|
+
|
|
186
|
+
# Update all subscriptions, filter profiles by kind
|
|
187
|
+
v2raycli subscription update --all
|
|
188
|
+
v2raycli profile list --kind socks
|
|
189
|
+
|
|
190
|
+
# Test by group, subscription, or profile ID
|
|
191
|
+
v2raycli test latency GROUP_ID
|
|
192
|
+
v2raycli test endpoint SUB_ID
|
|
193
|
+
|
|
194
|
+
# Routing rules can target any reference
|
|
195
|
+
v2raycli routing add block --domain 'keyword:ads'
|
|
196
|
+
v2raycli routing add direct --geoip cn
|
|
197
|
+
v2raycli routing add proxy --domain netflix.com --target SUB_ID
|
|
198
|
+
|
|
199
|
+
# Multiple servers on different ports
|
|
200
|
+
v2raycli server add --port 1081 GROUP_ID --protocol http --name 'Balancer'
|
|
201
|
+
v2raycli server start --all
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### Engine updates
|
|
205
|
+
|
|
206
|
+
Engine updates are never automatic. Use `v2raycli settings engine update sing-box`,
|
|
207
|
+
`v2raycli settings engine update xray`, or `v2raycli settings engine update both`. Only binaries
|
|
208
|
+
configured with `binary_path: "auto"` are replaceable; custom and system paths
|
|
209
|
+
are protected. Downloads are staged, version-checked, atomically replaced, and
|
|
210
|
+
rolled back if verification fails. For restricted networks, pass an ephemeral
|
|
211
|
+
proxy with `--proxy` on the update command (e.g. `v2raycli settings engine update both --proxy
|
|
212
|
+
socks5://127.0.0.1:1080`); it is never stored.
|
|
213
|
+
|
|
214
|
+
### Auto-update
|
|
215
|
+
|
|
216
|
+
Set `auto_update_days` on a subscription to have it re-fetched automatically
|
|
217
|
+
on startup when stale (never updated, or older than N days). Fetch failures are
|
|
218
|
+
logged and skipped — they never block startup. Disable per-run with
|
|
219
|
+
`--no-auto-update`.
|
|
220
|
+
|
|
221
|
+
### Subscription health
|
|
222
|
+
|
|
223
|
+
On startup the CLI warns (to stderr) about expired subscriptions and those
|
|
224
|
+
expiring within 7 days. `v2raycli health` prints a table of expiry status and
|
|
225
|
+
traffic used for every enabled subscription.
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
## Adding proxies
|
|
229
|
+
|
|
230
|
+
You can add proxies via CLI:
|
|
231
|
+
|
|
232
|
+
| Type | What it asks for |
|
|
233
|
+
|---|---|
|
|
234
|
+
| Subscription | URL (also `file://` and `paste://` accepted) |
|
|
235
|
+
| Share link | a `vmess://`, `vless://`, `trojan://`, `ss://`, `ssr://`, `hysteria2://`, `tuic://`, `wireguard://`, `socks://`, `http://` link |
|
|
236
|
+
| Socks / HTTP | server address, port, optional username/password |
|
|
237
|
+
| WireGuard | private key, address, peers |
|
|
238
|
+
| Hysteria2 / TUIC | server, auth, TLS/transport options |
|
|
239
|
+
| Raw config | paste a v2ray/xray outbound JSON object (uses xray engine) |
|
|
240
|
+
| OpenVPN | config file path or inline config + args |
|
|
241
|
+
| OpenConnect | server + args |
|
|
242
|
+
|
|
243
|
+
## Groups
|
|
244
|
+
|
|
245
|
+
- **Balancer** — pick references (profiles, subscriptions, groups, servers)
|
|
246
|
+
and a strategy (`latency`, `random`, `roundRobin`, `leastLoad`).
|
|
247
|
+
`leastLoad` forces xray-core. Everything resolves dynamically.
|
|
248
|
+
A lone profile is rejected — a single profile is not a group.
|
|
249
|
+
- **Chain** — pick an ordered list; traffic flows through each in order.
|
|
250
|
+
- Groups can **nest**: a balancer can contain other groups. A server
|
|
251
|
+
member resolves to a socks/http profile pointing at that server's local
|
|
252
|
+
inbound ("localhost calling") — traffic physically passes through it.
|
|
253
|
+
Members are resolved recursively at use time, deduplicated, and cycles
|
|
254
|
+
(group→group and server→group→server) are rejected.
|
|
255
|
+
- `v2raycli group tree` renders the whole hierarchy — top-level groups with
|
|
256
|
+
their members (profiles, subscriptions and their current nodes, servers,
|
|
257
|
+
nested groups) plus any subscription/server/profile no group references.
|
|
258
|
+
- VPN profiles cannot join balancers/chains.
|
|
259
|
+
|
|
260
|
+
A **subscription used as a target** (server outbound, routing rule, group
|
|
261
|
+
member) resolves as a strategy-based balancer over its *current*
|
|
262
|
+
profiles — refresh the subscription and the target follows automatically.
|
|
263
|
+
|
|
264
|
+
## Split routing
|
|
265
|
+
|
|
266
|
+
In **split** mode, the first matching rule wins. Rules can target a specific
|
|
267
|
+
profile, group, `direct` (bypass proxy), or `block` (drop traffic).
|
|
268
|
+
|
|
269
|
+
### CLI
|
|
270
|
+
|
|
271
|
+
```bash
|
|
272
|
+
# Switch to split mode
|
|
273
|
+
v2raycli routing mode split
|
|
274
|
+
|
|
275
|
+
# Block ads
|
|
276
|
+
v2raycli routing add block --domain keyword:ads
|
|
277
|
+
v2raycli routing add block --geosite category-ads-all
|
|
278
|
+
|
|
279
|
+
# Bypass local and Chinese IPs
|
|
280
|
+
v2raycli routing add direct --ip 192.168.0.0/16
|
|
281
|
+
v2raycli routing add direct --geoip cn --geoip private
|
|
282
|
+
|
|
283
|
+
# Route specific sites through a profile, group, or server
|
|
284
|
+
v2raycli routing add proxy --domain netflix.com --target PROFILE_ID
|
|
285
|
+
v2raycli routing add proxy --geosite gfw --target GROUP_ID
|
|
286
|
+
v2raycli routing add proxy --domain intranet.corp --target SERVER_ID
|
|
287
|
+
|
|
288
|
+
# List all rules
|
|
289
|
+
v2raycli routing list
|
|
290
|
+
v2raycli routing list --json
|
|
291
|
+
|
|
292
|
+
# Reorder rules (first match wins)
|
|
293
|
+
v2raycli routing move RULE_ID up
|
|
294
|
+
v2raycli routing move RULE_ID down
|
|
295
|
+
|
|
296
|
+
# Remove a rule
|
|
297
|
+
v2raycli routing remove RULE_ID
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
### Match types
|
|
301
|
+
|
|
302
|
+
| Matcher | Syntax | Example |
|
|
303
|
+
|---|---|---|
|
|
304
|
+
| Domain (exact) | `--domain example.com` | `--domain netflix.com` |
|
|
305
|
+
| Domain (keyword) | `--domain keyword:ads` | `--domain keyword:ads` |
|
|
306
|
+
| Domain (regex) | `--domain regex:^x\\.` | `--domain regex:^ads\\.` |
|
|
307
|
+
| Domain (geosite) | `--domain geosite:category` | `--domain geosite:gfw` |
|
|
308
|
+
| IP/CIDR | `--ip 10.0.0.0/8` | `--ip 192.168.0.0/16` |
|
|
309
|
+
| GeoIP | `--geoip cn` | `--geoip cn --geoip private` |
|
|
310
|
+
| GeoSite | `--geosite category-ads-all` | `--geosite gfw` |
|
|
311
|
+
|
|
312
|
+
### Target any reference
|
|
313
|
+
|
|
314
|
+
Proxy rules can target any profile, subscription, group, or server by ID —
|
|
315
|
+
not just the server's default outbound. A server target routes matching
|
|
316
|
+
traffic through that server's local inbound. This lets you route different
|
|
317
|
+
traffic through different outbounds:
|
|
318
|
+
|
|
319
|
+
```bash
|
|
320
|
+
# Route Netflix through a US profile
|
|
321
|
+
v2raycli routing add proxy --domain netflix.com --target US_PROFILE_ID
|
|
322
|
+
|
|
323
|
+
# Route streaming through a low-latency balancer group
|
|
324
|
+
v2raycli routing add proxy --geosite streaming --target BALANCER_GROUP_ID
|
|
325
|
+
|
|
326
|
+
# No --target: the rule follows the server's own outbound
|
|
327
|
+
v2raycli routing add proxy --domain example.com
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
### Automatic cleanup
|
|
331
|
+
|
|
332
|
+
When you delete a profile or group, any routing rules targeting it are
|
|
333
|
+
automatically removed — no broken configs.
|
|
334
|
+
|
|
335
|
+
### Geo assets
|
|
336
|
+
|
|
337
|
+
On sing-box, `geosite:`/`geoip:` entries compile to rule-sets that
|
|
338
|
+
auto-download from SagerNet/sing-geosite and SagerNet/sing-geoip. On xray,
|
|
339
|
+
`geoip.dat`/`geosite.dat` download to `geo/` (found via `XRAY_LOCATION_ASSET`).
|
|
340
|
+
|
|
341
|
+
## LAN sharing
|
|
342
|
+
|
|
343
|
+
By default `allow_lan` is enabled — the inbound listens on `0.0.0.0` so other
|
|
344
|
+
devices on your network can use `socks5://<your-ip>:1080` /
|
|
345
|
+
`http://<your-ip>:1080`. Optionally enable inbound auth (username/password).
|
|
346
|
+
|
|
347
|
+
## Traffic stats
|
|
348
|
+
|
|
349
|
+
Enable **Settings → Traffic stats** (or set `settings.traffic_api: true` in the
|
|
350
|
+
config) to have sing-box expose its Clash API on `127.0.0.1`
|
|
351
|
+
(`traffic_api_port`, default 9090). The CLI polls cumulative up/down bytes and
|
|
352
|
+
adds them to the server's outbound target when the server stops. Works with
|
|
353
|
+
sing-box (the default engine); xray has no Clash-compatible HTTP API so its
|
|
354
|
+
traffic is not counted.
|
|
355
|
+
|
|
356
|
+
## Run as a service
|
|
357
|
+
|
|
358
|
+
Keep all enabled servers running across reboots (no ad-hoc `connect` command
|
|
359
|
+
— connections are servers):
|
|
360
|
+
|
|
361
|
+
```bash
|
|
362
|
+
v2raycli server add --port 1080 REF
|
|
363
|
+
v2raycli server start --all
|
|
364
|
+
v2raycli service install
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
- **Linux** — writes a systemd *user* unit to
|
|
368
|
+
`~/.config/systemd/user/v2raycli.service`; enable it with
|
|
369
|
+
`systemctl --user enable --now v2raycli`.
|
|
370
|
+
- **Termux** — writes a `termux-services` run script to
|
|
371
|
+
`~/.termux/sv/v2raycli/run`; enable with `sv-enable v2raycli`.
|
|
372
|
+
|
|
373
|
+
Remove it with `v2raycli service uninstall`.
|
|
374
|
+
|
|
375
|
+
## Engine selection
|
|
376
|
+
|
|
377
|
+
- **sing-box** is the default and serves most protocols plus `latency`/`random`/
|
|
378
|
+
`roundRobin`. WireGuard profiles are emitted as sing-box **endpoints** (the
|
|
379
|
+
format since 1.13, where the WireGuard outbound was removed) and can be
|
|
380
|
+
chained, balanced and routed to like any other outbound.
|
|
381
|
+
- **xray-core** is used automatically for `ssr` and `leastLoad`.
|
|
382
|
+
- Override per profile/group, or change the global default in Settings.
|
|
383
|
+
|
|
384
|
+
### Routing guide: per-destination proxy selection
|
|
385
|
+
|
|
386
|
+
You can route different traffic through different outbounds using split routing
|
|
387
|
+
rules. Here's a practical setup:
|
|
388
|
+
|
|
389
|
+
```bash
|
|
390
|
+
# Enable split routing
|
|
391
|
+
v2raycli routing mode split
|
|
392
|
+
|
|
393
|
+
# Route Epic Games traffic through a Berlin profile
|
|
394
|
+
v2raycli routing add proxy --domain epicgames.com --target BERLIN_PROFILE_ID
|
|
395
|
+
v2raycli routing add proxy --domain fortnite.com --target BERLIN_PROFILE_ID
|
|
396
|
+
|
|
397
|
+
# Route YouTube traffic through a balancer group
|
|
398
|
+
v2raycli routing add proxy --domain youtube.com --target GROUP_1_ID
|
|
399
|
+
v2raycli routing add proxy --domain googlevideo.com --target GROUP_1_ID
|
|
400
|
+
|
|
401
|
+
# Route everything else through a subscription (auto-detected as a member)
|
|
402
|
+
v2raycli group add balancer default SUB_ID_A SUB_ID_2
|
|
403
|
+
|
|
404
|
+
# Route Russian websites directly (no proxy)
|
|
405
|
+
v2raycli routing add direct --geoip ru
|
|
406
|
+
v2raycli routing add direct --geosite ru
|
|
407
|
+
|
|
408
|
+
# Block ads globally
|
|
409
|
+
v2raycli routing add block --geosite category-ads-all
|
|
410
|
+
|
|
411
|
+
# Review your rules
|
|
412
|
+
v2raycli routing list
|
|
413
|
+
```
|
|
414
|
+
|
|
415
|
+
Rules are evaluated in order; the first match wins. Use `v2raycli routing move`
|
|
416
|
+
to reorder them.
|
|
417
|
+
|
|
418
|
+
## Troubleshooting
|
|
419
|
+
|
|
420
|
+
- **Port in use** — change the port with `v2raycli settings mixed-port <port>`.
|
|
421
|
+
- **"binary not found"** — binaries download on first use; if download fails,
|
|
422
|
+
set `engines.<name>.binary_path` in the config to a local binary, or
|
|
423
|
+
`"system"` to use one on `PATH`.
|
|
424
|
+
- **LAN unreachable** — check the firewall (Windows) and that devices share the
|
|
425
|
+
network.
|
|
426
|
+
- **Geo rules silent** — sing-box auto-downloads rule-sets, and xray's
|
|
427
|
+
`geoip.dat`/`geosite.dat` download to `geo/` on first use (both need
|
|
428
|
+
network).
|
|
429
|
+
- **VPN client missing** — install `openvpn` / `openconnect` and ensure it's on
|
|
430
|
+
`PATH`.
|
|
431
|
+
- **`v2raycli` command not found after `pip install .`** — the script is in
|
|
432
|
+
Python's `Scripts` directory which may not be on `PATH`. Fix: use
|
|
433
|
+
`python -m v2raycli`, add `Scripts` to your `PATH`, or reinstall with
|
|
434
|
+
`pipx install .`.
|
|
435
|
+
|
|
436
|
+
## Config layout
|
|
437
|
+
|
|
438
|
+
Config is JSON at `<config-dir>/config.json`. Derived dirs under the same base:
|
|
439
|
+
|
|
440
|
+
- `runtime/` — generated engine configs and test results
|
|
441
|
+
- `bin/` — downloaded engine binaries
|
|
442
|
+
- `geo/` — xray `geoip.dat`/`geosite.dat` assets (sing-box rule-sets are
|
|
443
|
+
cached by the engine)
|
|
444
|
+
- `backup/` — automatic config backups
|
|
445
|
+
|
|
446
|
+
## Development
|
|
447
|
+
|
|
448
|
+
```bash
|
|
449
|
+
pip install -e .[dev]
|
|
450
|
+
pytest
|
|
451
|
+
python scripts/verify_acceptance.py --json
|
|
452
|
+
```
|
|
453
|
+
|
|
454
|
+
GitHub Actions runs the pytest suite and the credential-free acceptance smoke
|
|
455
|
+
on Python 3.10, 3.11, and 3.12 for pushes and pull requests. Live engine,
|
|
456
|
+
remote-node, and platform walkthroughs remain separate from CI.
|
|
457
|
+
|
|
458
|
+
Read-only platform diagnostics (does not load or modify the config, download
|
|
459
|
+
binaries, or start processes):
|
|
460
|
+
|
|
461
|
+
```bash
|
|
462
|
+
python scripts/verify_platform.py
|
|
463
|
+
python scripts/verify_platform.py --json
|
|
464
|
+
```
|
|
465
|
+
|
|
466
|
+
Credential-free orchestration smoke (subscription import, split routing,
|
|
467
|
+
connection switching, test dispatch, cleanup, and OpenVPN/OpenConnect argv
|
|
468
|
+
validation;
|
|
469
|
+
does not download engines or contact remote nodes):
|
|
470
|
+
|
|
471
|
+
```bash
|
|
472
|
+
python scripts/verify_acceptance.py
|
|
473
|
+
python scripts/verify_acceptance.py --json
|
|
474
|
+
```
|
|
475
|
+
|
|
476
|
+
Live engine verification (downloads sing-box + xray, runs their own config
|
|
477
|
+
checks, and exercises the proxy end-to-end):
|
|
478
|
+
|
|
479
|
+
```bash
|
|
480
|
+
python scripts/verify_engines.py
|
|
481
|
+
# If GitHub access requires a local HTTP/SOCKS proxy:
|
|
482
|
+
python scripts/verify_engines.py --proxy socks5://127.0.0.1:10808
|
|
483
|
+
```
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "v2portal"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Interactive v2ray CLI client (sing-box + xray-core) with subscriptions, groups, and split routing"
|
|
9
|
+
requires-python = ">=3.10"
|
|
10
|
+
dependencies = [
|
|
11
|
+
"prompt_toolkit>=3.0",
|
|
12
|
+
"rich>=13.0",
|
|
13
|
+
"httpx[socks]>=0.26",
|
|
14
|
+
"platformdirs>=3.0",
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
[project.optional-dependencies]
|
|
18
|
+
dev = ["pytest>=7.0"]
|
|
19
|
+
|
|
20
|
+
[project.scripts]
|
|
21
|
+
v2portal = "v2raycli.app:main"
|
|
22
|
+
|
|
23
|
+
[tool.setuptools.packages.find]
|
|
24
|
+
where = ["src"]
|
|
25
|
+
|
|
26
|
+
[tool.pytest.ini_options]
|
|
27
|
+
pythonpath = ["src"]
|
|
28
|
+
testpaths = ["tests"]
|
v2portal-0.1.0/setup.cfg
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: v2portal
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Interactive v2ray CLI client (sing-box + xray-core) with subscriptions, groups, and split routing
|
|
5
|
+
Requires-Python: >=3.10
|
|
6
|
+
Requires-Dist: prompt_toolkit>=3.0
|
|
7
|
+
Requires-Dist: rich>=13.0
|
|
8
|
+
Requires-Dist: httpx[socks]>=0.26
|
|
9
|
+
Requires-Dist: platformdirs>=3.0
|
|
10
|
+
Provides-Extra: dev
|
|
11
|
+
Requires-Dist: pytest>=7.0; extra == "dev"
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
src/v2portal.egg-info/PKG-INFO
|
|
4
|
+
src/v2portal.egg-info/SOURCES.txt
|
|
5
|
+
src/v2portal.egg-info/dependency_links.txt
|
|
6
|
+
src/v2portal.egg-info/entry_points.txt
|
|
7
|
+
src/v2portal.egg-info/requires.txt
|
|
8
|
+
src/v2portal.egg-info/top_level.txt
|
|
9
|
+
src/v2raycli/__init__.py
|
|
10
|
+
src/v2raycli/__main__.py
|
|
11
|
+
src/v2raycli/app.py
|
|
12
|
+
src/v2raycli/backup.py
|
|
13
|
+
src/v2raycli/config.py
|
|
14
|
+
src/v2raycli/connection.py
|
|
15
|
+
src/v2raycli/diagnostics.py
|
|
16
|
+
src/v2raycli/errors.py
|
|
17
|
+
src/v2raycli/exchange.py
|
|
18
|
+
src/v2raycli/firewall.py
|
|
19
|
+
src/v2raycli/geo.py
|
|
20
|
+
src/v2raycli/models.py
|
|
21
|
+
src/v2raycli/runner.py
|
|
22
|
+
src/v2raycli/servers.py
|
|
23
|
+
src/v2raycli/service.py
|
|
24
|
+
src/v2raycli/storage.py
|
|
25
|
+
src/v2raycli/traffic.py
|
|
26
|
+
src/v2raycli/engines/__init__.py
|
|
27
|
+
src/v2raycli/engines/base.py
|
|
28
|
+
src/v2raycli/engines/binary.py
|
|
29
|
+
src/v2raycli/engines/singbox.py
|
|
30
|
+
src/v2raycli/engines/xray.py
|
|
31
|
+
src/v2raycli/outbounds/__init__.py
|
|
32
|
+
src/v2raycli/outbounds/groups.py
|
|
33
|
+
src/v2raycli/outbounds/manual.py
|
|
34
|
+
src/v2raycli/outbounds/vpn.py
|
|
35
|
+
src/v2raycli/routing/__init__.py
|
|
36
|
+
src/v2raycli/routing/rules.py
|
|
37
|
+
src/v2raycli/subs/__init__.py
|
|
38
|
+
src/v2raycli/subs/fetcher.py
|
|
39
|
+
src/v2raycli/subs/health.py
|
|
40
|
+
src/v2raycli/subs/parser.py
|
|
41
|
+
src/v2raycli/subs/share.py
|
|
42
|
+
src/v2raycli/test/__init__.py
|
|
43
|
+
src/v2raycli/test/latency.py
|
|
44
|
+
src/v2raycli/tui/__init__.py
|
|
45
|
+
src/v2raycli/tui/app_screen.py
|
|
46
|
+
src/v2raycli/tui/connection_screen.py
|
|
47
|
+
src/v2raycli/tui/groups_screen.py
|
|
48
|
+
src/v2raycli/tui/manage.py
|
|
49
|
+
src/v2raycli/tui/routing_screen.py
|
|
50
|
+
src/v2raycli/tui/servers_screen.py
|
|
51
|
+
src/v2raycli/tui/settings_screen.py
|
|
52
|
+
src/v2raycli/tui/test_screen.py
|
|
53
|
+
src/v2raycli/tui/widgets.py
|
|
54
|
+
tests/test_acceptance_flow.py
|
|
55
|
+
tests/test_app.py
|
|
56
|
+
tests/test_autoupdate.py
|
|
57
|
+
tests/test_backup.py
|
|
58
|
+
tests/test_binary.py
|
|
59
|
+
tests/test_cli_commands.py
|
|
60
|
+
tests/test_cli_surface.py
|
|
61
|
+
tests/test_code_quality.py
|
|
62
|
+
tests/test_config.py
|
|
63
|
+
tests/test_config_gen.py
|
|
64
|
+
tests/test_connection_errors.py
|
|
65
|
+
tests/test_controller.py
|
|
66
|
+
tests/test_diagnostics.py
|
|
67
|
+
tests/test_engine.py
|
|
68
|
+
tests/test_errors.py
|
|
69
|
+
tests/test_exchange.py
|
|
70
|
+
tests/test_fetcher.py
|
|
71
|
+
tests/test_firewall.py
|
|
72
|
+
tests/test_geo.py
|
|
73
|
+
tests/test_graph_flows.py
|
|
74
|
+
tests/test_groups.py
|
|
75
|
+
tests/test_health.py
|
|
76
|
+
tests/test_latency.py
|
|
77
|
+
tests/test_manual.py
|
|
78
|
+
tests/test_models.py
|
|
79
|
+
tests/test_parser.py
|
|
80
|
+
tests/test_resolve_refs.py
|
|
81
|
+
tests/test_routing.py
|
|
82
|
+
tests/test_runner.py
|
|
83
|
+
tests/test_servers.py
|
|
84
|
+
tests/test_service.py
|
|
85
|
+
tests/test_share.py
|
|
86
|
+
tests/test_storage.py
|
|
87
|
+
tests/test_temp_server.py
|
|
88
|
+
tests/test_traffic.py
|
|
89
|
+
tests/test_tui_connection.py
|
|
90
|
+
tests/test_tui_groups.py
|
|
91
|
+
tests/test_tui_manage.py
|
|
92
|
+
tests/test_tui_pty.py
|
|
93
|
+
tests/test_tui_routing.py
|
|
94
|
+
tests/test_tui_servers.py
|
|
95
|
+
tests/test_tui_settings.py
|
|
96
|
+
tests/test_tui_test_screen.py
|
|
97
|
+
tests/test_tui_widgets.py
|
|
98
|
+
tests/test_verify_acceptance.py
|
|
99
|
+
tests/test_verify_engines.py
|
|
100
|
+
tests/test_vpn.py
|
|
101
|
+
tests/test_vpn_connect.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
v2raycli
|