* 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>
34 lines
993 B
Luau
34 lines
993 B
Luau
--!nonstrict
|
|
-- shortcut.luau — control-center tile: toggle the proxy on/off.
|
|
|
|
local nonce = 0
|
|
local function send(method, args)
|
|
nonce = nonce + 1
|
|
noctalia.state.set("cmd", { method = method, args = args or {}, nonce = tostring(nonce) .. ":" .. tostring(os.time()) })
|
|
end
|
|
|
|
local function refresh()
|
|
local s = noctalia.state.get("status") or {}
|
|
local running = s.running == true
|
|
shortcut.setIcon(running and "lock" or "lock-open")
|
|
shortcut.setLabel(running and noctalia.tr("shortcut.on") or noctalia.tr("shortcut.off"))
|
|
shortcut.setActive(running)
|
|
end
|
|
|
|
function update() refresh() end
|
|
|
|
function onClick()
|
|
local s = noctalia.state.get("status") or {}
|
|
if s.running then
|
|
send("StopProxy", {})
|
|
else
|
|
if s.activeServerId and s.activeServerId ~= "" then
|
|
send("StartProxy", { s.activeServerId, s.mode or "rules", s.proxyMode or "system" })
|
|
else
|
|
noctalia.notifyError("VPN", noctalia.tr("error.no-server"))
|
|
end
|
|
end
|
|
end
|
|
|
|
noctalia.setUpdateInterval(2000)
|