* Add umedbazarov/ruh-vpn: VPN/proxy manager for sing-box New community plugin: bar widget, panel, service and control-center shortcut for managing SSH, VLESS, VMess, Shadowsocks and SOCKS5 connections through sing-box, with routing presets, custom rules, system-proxy/TUN modes and a kill switch. The bundled Python backend serves a loopback control API protected by a per-launch bearer token. * Address review: sanitize kill-switch ruleset, scope TUN capability, fix mux error path, disclose DNS - kill switch: only pre-resolved, canonicalized literal IPs enter the nft ruleset; domains are resolved first and anything unparseable is dropped, so subscription-supplied addresses can no longer inject nft syntax - TUN: CAP_NET_ADMIN is granted to a plugin-private copy of sing-box in a 0700 directory instead of the shared system binary; the copy is refreshed (clearing the cap) when the system binary changes, and the legacy grant on the shared binary is removed in the same polkit prompt - fix NameError in the mux startup failure path (undefined mux_name) that hid the log tail and skipped teardown - README: disclose plain-UDP DNS endpoints (8.8.8.8 via tunnel, 223.5.5.5 direct in rules mode) alongside the TUN DoH endpoint --------- Co-authored-by: Umedjon Bazarov <170195993+UmedjonBA@users.noreply.github.com>
42 lines
1.3 KiB
Python
42 lines
1.3 KiB
Python
import base64
|
|
|
|
from backend.subscription.parsers import parse_share_link
|
|
|
|
|
|
def test_vless_link():
|
|
link = (
|
|
"vless://11111111-2222-3333-4444-555555555555@example.com:443"
|
|
"?type=ws&security=tls&sni=cdn.example.com&path=%2Fws#My%20VLESS"
|
|
)
|
|
data = parse_share_link(link)
|
|
assert data is not None
|
|
assert data["protocol"] == "vless"
|
|
assert data["address"] == "example.com"
|
|
assert data["port"] == 443
|
|
assert data["uuid"] == "11111111-2222-3333-4444-555555555555"
|
|
assert data["transport"] == "ws"
|
|
assert data["security"] == "tls"
|
|
|
|
|
|
def test_ss_link():
|
|
userinfo = base64.urlsafe_b64encode(b"aes-256-gcm:secretpw").decode().rstrip("=")
|
|
data = parse_share_link(f"ss://{userinfo}@example.com:8388#SS")
|
|
assert data is not None
|
|
assert data["protocol"] == "shadowsocks"
|
|
assert data["method"] == "aes-256-gcm"
|
|
assert data["password"] == "secretpw"
|
|
assert data["port"] == 8388
|
|
|
|
|
|
def test_socks5_link():
|
|
data = parse_share_link("socks5://user:pw@example.com:1080#S5")
|
|
assert data is not None
|
|
assert data["protocol"] == "socks5"
|
|
assert data["port"] == 1080
|
|
|
|
|
|
def test_unsupported_link():
|
|
assert parse_share_link("trojan://whatever@example.com:443") is None
|
|
assert parse_share_link("not a link") is None
|
|
assert parse_share_link("") is None
|