mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-11-03 21:03:56 +08:00
🌴 Sync 2026-03-05 23:51:42
This commit is contained in:
1 parent
97c049ed0a
commit
0acff03804
14253 files changed
+3893239
No files matched your search
@@ -0,0 +1,93 @@
|
||||
-- Copyright (C) 2014-2017 Jian Chang <aa65535@live.com>
|
||||
-- Copyright (C) 2020-2023 honwen <https://github.com/honwen>
|
||||
-- Licensed to the public under the GNU General Public License v3.
|
||||
|
||||
module("luci.controller.shadowsocks", package.seeall)
|
||||
|
||||
function index()
|
||||
if not nixio.fs.access("/etc/config/shadowsocks") then
|
||||
return
|
||||
end
|
||||
|
||||
page = entry({"admin", "services", "shadowsocks"},
|
||||
alias("admin", "services", "shadowsocks", "general"),
|
||||
_("ShadowSocks"), 10)
|
||||
page.dependent = true
|
||||
page.acl_depends = { "luci-app-shadowsocks" }
|
||||
|
||||
page = entry({"admin", "services", "shadowsocks", "general"},
|
||||
cbi("shadowsocks/general"),
|
||||
_("General Settings"), 10)
|
||||
page.leaf = true
|
||||
page.acl_depends = { "luci-app-shadowsocks" }
|
||||
|
||||
page = entry({"admin", "services", "shadowsocks", "status"},
|
||||
call("action_status"))
|
||||
page.leaf = true
|
||||
page.acl_depends = { "luci-app-shadowsocks" }
|
||||
|
||||
page = entry({"admin", "services", "shadowsocks", "servers"},
|
||||
arcombine(cbi("shadowsocks/servers"), cbi("shadowsocks/servers-details")),
|
||||
_("Servers Manage"), 20)
|
||||
page.leaf = true
|
||||
page.acl_depends = { "luci-app-shadowsocks" }
|
||||
|
||||
if luci.sys.call("command -v sslocal >/dev/null") ~= 0 then
|
||||
return
|
||||
end
|
||||
|
||||
page = entry({"admin", "services", "shadowsocks", "access-control"},
|
||||
cbi("shadowsocks/access-control"),
|
||||
_("Access Control"), 30)
|
||||
page.leaf = true
|
||||
page.acl_depends = { "luci-app-shadowsocks" }
|
||||
|
||||
entry({"admin", "services", "shadowsocks", "log"},
|
||||
call("action_log"),
|
||||
_("System Log"), 90)
|
||||
page.leaf = true
|
||||
page.acl_depends = { "luci-app-shadowsocks" }
|
||||
|
||||
if luci.sys.call("command -v /etc/init.d/dnsmasq-extra >/dev/null") ~= 0 then
|
||||
return
|
||||
end
|
||||
|
||||
page = entry({"admin", "services", "shadowsocks", "gfwlist"},
|
||||
call("action_gfw"),
|
||||
_("GFW-List"), 60)
|
||||
page.leaf = true
|
||||
page.acl_depends = { "luci-app-shadowsocks" }
|
||||
|
||||
page = entry({"admin", "services", "shadowsocks", "custom"},
|
||||
cbi("shadowsocks/gfwlist-custom"),
|
||||
_("Custom-List"), 50)
|
||||
page.leaf = true
|
||||
page.acl_depends = { "luci-app-shadowsocks" }
|
||||
|
||||
end
|
||||
|
||||
local function is_running(name)
|
||||
return luci.sys.call("pgrep -f '%s' >/dev/null" %{name}) == 0
|
||||
end
|
||||
|
||||
function action_status()
|
||||
luci.http.prepare_content("application/json")
|
||||
luci.http.write_json({
|
||||
ss_redir = is_running("/var/run/ss-redir"),
|
||||
ss_http = is_running("/var/run/ss-local-http"),
|
||||
ss_socks = is_running("/var/run/ss-local-socks"),
|
||||
ss_tunnel = is_running("/var/run/ss-tunnel")
|
||||
})
|
||||
end
|
||||
|
||||
function action_log()
|
||||
local conffile = "/var/log/shadowsocks_healthcheck.log"
|
||||
local healthcheck = nixio.fs.readfile(conffile) or ""
|
||||
luci.template.render("shadowsocks/plain", {content=healthcheck})
|
||||
end
|
||||
|
||||
function action_gfw()
|
||||
local conffile = "/etc/dnsmasq-extra.d/gfwlist"
|
||||
local gfwlist = nixio.fs.readfile(conffile) or luci.sys.exec("cat %s.gz | gunzip -c" %{conffile}) or ""
|
||||
luci.template.render("shadowsocks/plain", {content=gfwlist})
|
||||
end
|
||||
@@ -0,0 +1,136 @@
|
||||
-- Copyright (C) 2016-2017 Jian Chang <aa65535@live.com>
|
||||
-- Licensed to the public under the GNU General Public License v3.
|
||||
|
||||
local m, s, o
|
||||
local shadowsocks = "shadowsocks"
|
||||
local uci = luci.model.uci.cursor()
|
||||
local nwm = require("luci.model.network").init()
|
||||
local gfwroute = luci.sys.call("command -v /etc/init.d/dnsmasq-extra >/dev/null") == 0
|
||||
local chnroute = gfwroute and "/etc/chinadns_chnroute.txt" or uci:get_first("chinadns", "chinadns", "chnroute")
|
||||
local lan_ifaces = {}
|
||||
local io = require "io"
|
||||
|
||||
local function ipv4_hints(callback)
|
||||
local hosts = {}
|
||||
uci:foreach("dhcp", "dnsmasq", function(s)
|
||||
if s.leasefile and nixio.fs.access(s.leasefile) then
|
||||
for e in io.lines(s.leasefile) do
|
||||
mac, ip, name = e:match("^%d+ (%S+) (%S+) (%S+)")
|
||||
if mac and ip then
|
||||
hosts[ip] = name ~= "*" and name or mac:upper()
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
uci:foreach("dhcp", "host", function(s)
|
||||
for mac in luci.util.imatch(s.mac) do
|
||||
if s.ip then
|
||||
hosts[s.ip] = s.name or mac:upper()
|
||||
end
|
||||
end
|
||||
end)
|
||||
for ip, name in pairs(hosts) do
|
||||
callback(ip, name)
|
||||
end
|
||||
end
|
||||
|
||||
for _, net in ipairs(nwm:get_networks()) do
|
||||
if net:name() ~= "loopback" and string.find(net:name(), "wan") ~= 1 then
|
||||
net = nwm:get_network(net:name())
|
||||
local device = net and net:get_interface()
|
||||
if device then
|
||||
lan_ifaces[device:name()] = device:get_i18n()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
m = Map(shadowsocks, "%s - %s" %{translate("ShadowSocks"), translate("Access Control")})
|
||||
|
||||
-- [[ Zone WAN ]]--
|
||||
s = m:section(TypedSection, "access_control", translate("Zone WAN"))
|
||||
s.anonymous = true
|
||||
|
||||
o = s:option(Value, "wan_bp_list", translate("Bypassed IP List"))
|
||||
o:value("/dev/null", translate("NULL - As Global Proxy"))
|
||||
if gfwroute then o:value("/dev/flag_gfwlist", translate("Only Proxy GFW-List")) end
|
||||
if chnroute then o:value(chnroute, translate("ChinaDNS CHNRoute")) end
|
||||
-- o.datatype = "or(file, '/dev/null')"
|
||||
o.default = "/dev/null"
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(DynamicList, "wan_bp_ips", translate("Bypassed IP"))
|
||||
o.datatype = "ip4addr"
|
||||
o.rmempty = true
|
||||
|
||||
o = s:option(Value, "wan_fw_list", translate("Forwarded IP List"))
|
||||
o.datatype = "or(file, '/dev/null')"
|
||||
o.rmempty = true
|
||||
|
||||
o = s:option(DynamicList, "wan_fw_ips", translate("Forwarded IP"))
|
||||
o.datatype = "ip4addr"
|
||||
o.rmempty = true
|
||||
|
||||
-- [[ Zone LAN ]]--
|
||||
s = m:section(TypedSection, "access_control", translate("Zone LAN"))
|
||||
s.anonymous = true
|
||||
|
||||
o = s:option(MultiValue, "lan_ifaces", translate("Interface"))
|
||||
function o.cfgvalue(...)
|
||||
local v = MultiValue.cfgvalue(...)
|
||||
if v then
|
||||
return v
|
||||
else
|
||||
local names = {}
|
||||
for name, _ in pairs(lan_ifaces) do
|
||||
names[#names+1] = name
|
||||
end
|
||||
return table.concat(names, " ")
|
||||
end
|
||||
end
|
||||
for name, i18n in pairs(lan_ifaces) do
|
||||
o:value(name, i18n)
|
||||
end
|
||||
|
||||
o = s:option(ListValue, "lan_target", translate("Proxy Type"))
|
||||
o:value("SS_SPEC_WAN_AC", translate("Normal"))
|
||||
o:value("RETURN", translate("Direct"))
|
||||
o:value("SS_SPEC_WAN_FW", translate("Global"))
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(ListValue, "self_proxy", translate("Self Proxy"))
|
||||
o:value("1", translate("Normal"))
|
||||
o:value("0", translate("Direct"))
|
||||
o:value("2", translate("Global"))
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "ipt_ext", translate("Extra arguments"),
|
||||
translate("Passes additional arguments to iptables. Use with care!"))
|
||||
o:value("", translate("None"))
|
||||
o:value("--dport 22:1023", translatef("Proxy port numbers %s only", "22~1023"))
|
||||
o:value("-m multiport --dport 22:1023,8000:8443", translatef("Proxy port numbers %s only", "22~1023,8000~8443"))
|
||||
o:value("-m multiport --dports 53,80,443,853", translatef("Proxy port numbers %s only", "53,80,443,853"))
|
||||
|
||||
-- [[ LAN Hosts ]]--
|
||||
s = m:section(TypedSection, "lan_hosts", translate("LAN Hosts"))
|
||||
s.template = "cbi/tblsection"
|
||||
s.addremove = true
|
||||
s.anonymous = true
|
||||
|
||||
o = s:option(Value, "host", translate("Host"))
|
||||
ipv4_hints(function(ip, name)
|
||||
o:value(ip, "%s (%s)" %{ip, name})
|
||||
end)
|
||||
o.datatype = "ip4addr"
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(ListValue, "type", translate("Proxy Type"))
|
||||
o:value("b", translate("Direct"))
|
||||
o:value("g", translate("Global"))
|
||||
o:value("n", translate("Normal"))
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Flag, "enable", translate("Enable"))
|
||||
o.default = "1"
|
||||
o.rmempty = false
|
||||
|
||||
return m
|
||||
@@ -0,0 +1,203 @@
|
||||
-- Copyright (C) 2014-2018 Jian Chang <aa65535@live.com>
|
||||
-- Copyright (C) 2020-2023 honwen <https://github.com/honwen>
|
||||
-- Licensed to the public under the GNU General Public License v3.
|
||||
|
||||
local m, s, o
|
||||
local shadowsocks = "shadowsocks"
|
||||
local uci = luci.model.uci.cursor()
|
||||
local servers = {}
|
||||
|
||||
local function has_bin(name)
|
||||
return luci.sys.call("command -v %s >/dev/null" %{name}) == 0
|
||||
end
|
||||
|
||||
local function has_udp_relay()
|
||||
return luci.sys.call("lsmod | grep -q TPROXY && command -v ip >/dev/null") == 0
|
||||
end
|
||||
|
||||
local function support_fast_open()
|
||||
local bit = luci.sys.exec("cat /proc/sys/net/ipv4/tcp_fastopen 2>/dev/null"):trim()
|
||||
return bit == "1" or bit == "3"
|
||||
end
|
||||
|
||||
local has_ss = has_bin("sslocal")
|
||||
|
||||
if not has_ss then
|
||||
return Map(shadowsocks, "%s - %s" %{translate("ShadowSocks"),
|
||||
translate("General Settings")}, '<b style="color:red">shadowsocks-rust binary file not found.</b>')
|
||||
end
|
||||
|
||||
local function is_running(name)
|
||||
return luci.sys.call("pgrep -f '%s' >/dev/null" %{name}) == 0
|
||||
end
|
||||
|
||||
local function get_status(name)
|
||||
return is_running(name) and translate("RUNNING") or translate("NOT RUNNING")
|
||||
end
|
||||
|
||||
uci:foreach(shadowsocks, "servers", function(s)
|
||||
if s.server and s.server_port then
|
||||
servers[#servers+1] = {name = s[".name"], alias = s.alias or "%s:%s" %{s.server, s.server_port}}
|
||||
end
|
||||
end)
|
||||
|
||||
m = Map(shadowsocks, "%s - %s" %{translate("ShadowSocks"), translate("General Settings")})
|
||||
m.template = "shadowsocks/general"
|
||||
|
||||
-- [[ Running Status ]]--
|
||||
s = m:section(TypedSection, "general", translate("Running Status"))
|
||||
s.anonymous = true
|
||||
|
||||
o = s:option(DummyValue, "_redir_status", translate("Transparent Proxy"))
|
||||
o.value = "<span id=\"_redir_status\">%s</span>" %{get_status("/var/run/ss-redir")}
|
||||
o.rawhtml = true
|
||||
|
||||
o = s:option(DummyValue, "http_status", translate("HTTP Proxy"))
|
||||
o.value = "<span id=\"_http_status\">%s</span>" %{get_status("/var/run/ss-local-http")}
|
||||
o.rawhtml = true
|
||||
|
||||
o = s:option(DummyValue, "socks_status", translate("SOCKS5 Proxy"))
|
||||
o.value = "<span id=\"_socks_status\">%s</span>" %{get_status("/var/run/ss-local-socks")}
|
||||
o.rawhtml = true
|
||||
|
||||
o = s:option(DummyValue, "_tunnel_status", translate("Port Forward"))
|
||||
o.value = "<span id=\"_tunnel_status\">%s</span>" %{get_status("/var/run/ss-tunnel")}
|
||||
o.rawhtml = true
|
||||
|
||||
s = m:section(TypedSection, "general", translate("Global Settings"))
|
||||
s.anonymous = true
|
||||
|
||||
o = s:option(Value, "startup_delay", translate("Startup Delay"))
|
||||
o:value(0, translate("Not enabled"))
|
||||
for _, v in ipairs({3, 5, 10, 15, 25, 40}) do
|
||||
o:value(v, translatef("%u seconds", v))
|
||||
end
|
||||
o.datatype = "uinteger"
|
||||
o.default = 0
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "udp_timeout", translate("Timeout for UDP Associations"))
|
||||
for _, v in ipairs({10, 30, 60, 120, 180, 300, 600, 1800}) do
|
||||
o:value(v, translatef("%u seconds", v))
|
||||
end
|
||||
o.default = 300
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "udp_max_associations", translate("Maximum UDP Associations"))
|
||||
o:value(0, translate("Unlimited"))
|
||||
for _, v in ipairs({64, 256, 1024, 5120, 8192, 32768}) do
|
||||
o:value(v)
|
||||
end
|
||||
o.default = 512
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Flag, "no_dns_injection", translate("Disable DNS Auto-Injection"))
|
||||
o.rmempty = false
|
||||
|
||||
-- [[ Transparent Proxy ]]--
|
||||
s = m:section(TypedSection, "transparent_proxy", translate("Transparent Proxy"))
|
||||
s.anonymous = true
|
||||
|
||||
o = s:option(Flag, "no_delay", translate("TCP no-delay"))
|
||||
o.rmempty = false
|
||||
if support_fast_open() then
|
||||
o = s:option(Flag, "fast_open", translate("TCP Fast Open"))
|
||||
o.rmempty = false
|
||||
end
|
||||
|
||||
o = s:option(DynamicList, "main_server", translate("Main Server"))
|
||||
o:value("nil", translate("Disable"))
|
||||
for _, s in ipairs(servers) do o:value(s.name, s.alias) end
|
||||
o.default = "nil"
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(ListValue, "udp_relay_server", translate("UDP-Relay Server"))
|
||||
if has_udp_relay() then
|
||||
o:value("nil", translate("Disable"))
|
||||
o:value("same", translate("Same as Main Server"))
|
||||
for _, s in ipairs(servers) do o:value(s.name, s.alias) end
|
||||
else
|
||||
o:value("nil", translate("Unusable - Missing iptables-mod-tproxy or ip"))
|
||||
end
|
||||
o.default = "nil"
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "local_port", translate("Local Port"))
|
||||
o.datatype = "port"
|
||||
o.default = 1234
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Flag, "no_healthcheck", translate("Disable HealthCheck"))
|
||||
o.rmempty = false
|
||||
|
||||
-- [[ HTTP Proxy ]]--
|
||||
s = m:section(TypedSection, "http_proxy", translate("HTTP Proxy"))
|
||||
s.anonymous = true
|
||||
|
||||
o = s:option(Flag, "no_delay", translate("TCP no-delay"))
|
||||
o.rmempty = false
|
||||
if support_fast_open() then
|
||||
o = s:option(Flag, "fast_open", translate("TCP Fast Open"))
|
||||
o.rmempty = false
|
||||
end
|
||||
|
||||
o = s:option(DynamicList, "server", translate("Server"))
|
||||
o:value("nil", translate("Disable"))
|
||||
for _, s in ipairs(servers) do o:value(s.name, s.alias) end
|
||||
o.default = "nil"
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "local_port", translate("Local Port"))
|
||||
o.datatype = "port"
|
||||
o.default = 1080
|
||||
o.rmempty = false
|
||||
|
||||
-- [[ SOCKS5 Proxy ]]--
|
||||
s = m:section(TypedSection, "socks_proxy", translate("SOCKS5 Proxy"))
|
||||
s.anonymous = true
|
||||
|
||||
o = s:option(Flag, "no_delay", translate("TCP no-delay"))
|
||||
o.rmempty = false
|
||||
if support_fast_open() then
|
||||
o = s:option(Flag, "fast_open", translate("TCP Fast Open"))
|
||||
o.rmempty = false
|
||||
end
|
||||
|
||||
o = s:option(DynamicList, "server", translate("Server"))
|
||||
o:value("nil", translate("Disable"))
|
||||
for _, s in ipairs(servers) do o:value(s.name, s.alias) end
|
||||
o.default = "nil"
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "local_port", translate("Local Port"))
|
||||
o.datatype = "port"
|
||||
o.default = 1080
|
||||
o.rmempty = false
|
||||
|
||||
-- [[ Port Forward ]]--
|
||||
s = m:section(TypedSection, "port_forward", translate("Port Forward"))
|
||||
s.anonymous = true
|
||||
|
||||
o = s:option(Flag, "no_delay", translate("TCP no-delay"))
|
||||
o.rmempty = false
|
||||
if support_fast_open() then
|
||||
o = s:option(Flag, "fast_open", translate("TCP Fast Open"))
|
||||
o.rmempty = false
|
||||
end
|
||||
|
||||
o = s:option(DynamicList, "server", translate("Server"))
|
||||
o:value("nil", translate("Disable"))
|
||||
for _, s in ipairs(servers) do o:value(s.name, s.alias) end
|
||||
o.default = "nil"
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "local_port", translate("Local Port"))
|
||||
o.datatype = "port"
|
||||
o.default = 5300
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "destination", translate("Destination"))
|
||||
o.default = "8.8.4.4:53"
|
||||
o.rmempty = false
|
||||
|
||||
return m
|
||||
@@ -0,0 +1,23 @@
|
||||
local fs = require "nixio.fs"
|
||||
local conffile = "/etc/dnsmasq-extra.d/custom.conf"
|
||||
|
||||
f = SimpleForm("custom", translate("Be Careful!"), translate("Dnsmasq Config for Shadowsocks. This may CRASH DNSMASQ!"))
|
||||
|
||||
t = f:field(TextValue, "conf")
|
||||
t.rmempty = true
|
||||
t.rows = 30
|
||||
function t.cfgvalue()
|
||||
return fs.readfile(conffile) or ""
|
||||
end
|
||||
|
||||
function f.handle(self, state, data)
|
||||
if state == FORM_VALID then
|
||||
if data.conf then
|
||||
fs.writefile(conffile, data.conf:gsub("\r\n", "\n"))
|
||||
luci.sys.call("/etc/init.d/dnsmasq-extra restart")
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
return f
|
||||
@@ -0,0 +1,92 @@
|
||||
-- Copyright (C) 2016-2017 Jian Chang <aa65535@live.com>
|
||||
-- Copyright (C) 2020-2023 honwen <https://github.com/honwen>
|
||||
-- Licensed to the public under the GNU General Public License v3.
|
||||
|
||||
local m, s, o
|
||||
local shadowsocks = "shadowsocks"
|
||||
local sid = arg[1]
|
||||
local encrypt_methods = {
|
||||
"aes-256-gcm",
|
||||
"aes-128-gcm",
|
||||
"chacha20-ietf-poly1305",
|
||||
"2022-blake3-aes-128-gcm",
|
||||
"2022-blake3-aes-256-gcm",
|
||||
"2022-blake3-chacha20-poly1305",
|
||||
"rc4-md5",
|
||||
"aes-128-cfb",
|
||||
"aes-192-cfb",
|
||||
"aes-256-cfb",
|
||||
"aes-128-ctr",
|
||||
"aes-192-ctr",
|
||||
"aes-256-ctr",
|
||||
"camellia-128-cfb",
|
||||
"camellia-192-cfb",
|
||||
"camellia-256-cfb",
|
||||
"chacha20-ietf",
|
||||
"plain",
|
||||
"none",
|
||||
}
|
||||
|
||||
m = Map(shadowsocks, "%s - %s" %{translate("ShadowSocks"), translate("Edit Server")})
|
||||
m.redirect = luci.dispatcher.build_url("admin/services/shadowsocks/servers")
|
||||
m.sid = sid
|
||||
m.template = "shadowsocks/servers-details"
|
||||
|
||||
if m.uci:get(shadowsocks, sid) ~= "servers" then
|
||||
luci.http.redirect(m.redirect)
|
||||
return
|
||||
end
|
||||
|
||||
-- [[ Edit Server ]]--
|
||||
s = m:section(NamedSection, sid, "servers")
|
||||
s.anonymous = true
|
||||
s.addremove = false
|
||||
|
||||
o = s:option(Value, "alias", translate("Alias(optional)"))
|
||||
o.rmempty = true
|
||||
|
||||
o = s:option(Value, "server", translate("Server Address"))
|
||||
o.datatype = "host"
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "server_port", translate("Server Port"))
|
||||
o.datatype = "port"
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "timeout", translate("TCP Connection Timeout"))
|
||||
o.datatype = "uinteger"
|
||||
o.default = 60
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "password", translate("Password"))
|
||||
o.password = true
|
||||
|
||||
o = s:option(ListValue, "encrypt_method", translate("Encrypt Method"))
|
||||
for _, v in ipairs(encrypt_methods) do o:value(v, v:upper()) end
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(Value, "plugin", translate("Plugin Name"))
|
||||
o.placeholder = "eg: v2ray-plugin"
|
||||
|
||||
o = s:option(Value, "plugin_opts", translate("Plugin Arguments"))
|
||||
o.placeholder = "eg: tls;host=www.bing.com;path=/websocket"
|
||||
|
||||
o = s:option(ListValue, "tcp_weight", translate("TCP Weight"))
|
||||
o.datatype = "ufloat"
|
||||
o:value(0, translate("0%(UDP ONLY)"))
|
||||
for _, v in ipairs({0.05, 0.1, 0.2, 0.3, 0.5, 0.7, 0.8, 0.9, 0.95, 1.0}) do
|
||||
o:value(v, translatef("%u%%", v*100.0))
|
||||
end
|
||||
o.default = 1.0
|
||||
o.rmempty = false
|
||||
|
||||
o = s:option(ListValue, "udp_weight", translate("UDP Weight"))
|
||||
o.datatype = "ufloat"
|
||||
o:value(0, translate("0%(TCP ONLY)"))
|
||||
for _, v in ipairs({0.05, 0.1, 0.2, 0.3, 0.5, 0.7, 0.8, 0.9, 0.95, 1.0}) do
|
||||
o:value(v, translatef("%u%%", v * 100.0))
|
||||
end
|
||||
o.default = 1.0
|
||||
o.rmempty = false
|
||||
|
||||
return m
|
||||
@@ -0,0 +1,50 @@
|
||||
-- Copyright (C) 2016-2017 Jian Chang <aa65535@live.com>
|
||||
-- Licensed to the public under the GNU General Public License v3.
|
||||
|
||||
local m, s, o
|
||||
local shadowsocks = "shadowsocks"
|
||||
|
||||
m = Map(shadowsocks, "%s - %s" %{translate("ShadowSocks"), translate("Servers Manage")})
|
||||
|
||||
-- [[ Servers Manage ]]--
|
||||
s = m:section(TypedSection, "servers")
|
||||
s.anonymous = true
|
||||
s.addremove = true
|
||||
s.sortable = true
|
||||
s.template = "cbi/tblsection"
|
||||
s.extedit = luci.dispatcher.build_url("admin/services/shadowsocks/servers/%s")
|
||||
function s.create(...)
|
||||
local sid = TypedSection.create(...)
|
||||
if sid then
|
||||
luci.http.redirect(s.extedit % sid)
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
o = s:option(DummyValue, "alias", translate("Alias"))
|
||||
function o.cfgvalue(...)
|
||||
return Value.cfgvalue(...) or translate("None")
|
||||
end
|
||||
|
||||
o = s:option(DummyValue, "server", translate("Server Address"))
|
||||
function o.cfgvalue(...)
|
||||
return Value.cfgvalue(...) or "?"
|
||||
end
|
||||
|
||||
o = s:option(DummyValue, "server_port", translate("Server Port"))
|
||||
function o.cfgvalue(...)
|
||||
return Value.cfgvalue(...) or "?"
|
||||
end
|
||||
|
||||
o = s:option(DummyValue, "encrypt_method", translate("Encrypt Method"))
|
||||
function o.cfgvalue(...)
|
||||
local v = Value.cfgvalue(...)
|
||||
return v and v:upper() or "?"
|
||||
end
|
||||
|
||||
o = s:option(DummyValue, "plugin", translate("Plugin"))
|
||||
function o.cfgvalue(...)
|
||||
return Value.cfgvalue(...) or translate("None")
|
||||
end
|
||||
|
||||
return m
|
||||
@@ -0,0 +1,92 @@
|
||||
<%#
|
||||
Copyright (C) 2017-2018 Jian Chang <aa65535@live.com>
|
||||
Copyright (C) 2020-2023 honwen <https://github.com/honwen>
|
||||
Licensed to the public under the GNU General Public License v3.
|
||||
-%>
|
||||
|
||||
<% include("cbi/map") %>
|
||||
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
(function() {
|
||||
window.cbi_combobox = function(id, values, def, man, focus) {
|
||||
var selid = "cbi.combobox." + id;
|
||||
if (document.getElementById(selid)) {
|
||||
return;
|
||||
}
|
||||
|
||||
var obj = document.getElementById(id);
|
||||
var sel = document.createElement("select");
|
||||
sel.id = selid;
|
||||
sel.index = obj.index;
|
||||
sel.className = obj.className.replace(/cbi-input-text/, 'cbi-input-select');
|
||||
|
||||
if (obj.nextSibling) {
|
||||
obj.parentNode.insertBefore(sel, obj.nextSibling);
|
||||
} else {
|
||||
obj.parentNode.appendChild(sel);
|
||||
}
|
||||
|
||||
var dt = obj.getAttribute('cbi_datatype');
|
||||
var op = obj.getAttribute('cbi_optional');
|
||||
|
||||
if (!values[obj.value]) {
|
||||
if (obj.value != "") {
|
||||
var opt = document.createElement("option");
|
||||
opt.value = obj.value;
|
||||
opt.selected = "selected";
|
||||
opt.appendChild(document.createTextNode(obj.value));
|
||||
sel.appendChild(opt);
|
||||
}
|
||||
}
|
||||
|
||||
for (var i in values) {
|
||||
var opt = document.createElement("option");
|
||||
opt.value = i;
|
||||
|
||||
if (obj.value == i) {
|
||||
opt.selected = "selected";
|
||||
}
|
||||
|
||||
opt.appendChild(document.createTextNode(values[i]));
|
||||
sel.appendChild(opt);
|
||||
}
|
||||
|
||||
obj.style.display = "none";
|
||||
|
||||
if (dt)
|
||||
cbi_validate_field(sel, op == 'true', dt);
|
||||
|
||||
cbi_bind(sel, "change", function() {
|
||||
obj.value = sel.options[sel.selectedIndex].value;
|
||||
|
||||
try {
|
||||
cbi_d_update();
|
||||
} catch (e) {
|
||||
//Do nothing
|
||||
}
|
||||
})
|
||||
|
||||
// Retrigger validation in select
|
||||
if (focus !== false) {
|
||||
sel.focus();
|
||||
sel.blur();
|
||||
}
|
||||
};
|
||||
|
||||
var elements = {
|
||||
ss_redir: document.getElementById("_redir_status"),
|
||||
ss_http: document.getElementById("_http_status"),
|
||||
ss_socks: document.getElementById("_socks_status"),
|
||||
ss_tunnel: document.getElementById("_tunnel_status"),
|
||||
};
|
||||
XHR.poll(5, "<%=luci.dispatcher.build_url("admin", "services", "shadowsocks", "status")%>", null, function(xhr, status) {
|
||||
if (xhr.status === 200) {
|
||||
for (var k in elements) {
|
||||
if (elements[k]) {
|
||||
elements[k].textContent = status[k] ? "<%:RUNNING%>" : "<%:NOT RUNNING%>";
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}());
|
||||
//]]></script>
|
||||
@@ -0,0 +1,9 @@
|
||||
<%+header%>
|
||||
<textarea
|
||||
style="background: #fafafa; color: #666; width: 100%;"
|
||||
readonly="readonly"
|
||||
wrap="off"
|
||||
rows="<%=content:cmatch("\n")+2%>">
|
||||
<%=content:pcdata()%>
|
||||
</textarea>
|
||||
<%+footer%>
|
||||
@@ -0,0 +1,35 @@
|
||||
<%#
|
||||
Copyright (C) 2017-2018 Jian Chang <aa65535@live.com>
|
||||
Licensed to the public under the GNU General Public License v3.
|
||||
-%>
|
||||
|
||||
<% include("cbi/map") %>
|
||||
|
||||
<script type="text/javascript">//<![CDATA[
|
||||
(function($) {
|
||||
var password = $("password");
|
||||
var key = $("key");
|
||||
var form = key.form;
|
||||
var checkCryptoConfig = function() {
|
||||
password.className = password.className.replace(/ cbi-input-invalid/g, "");
|
||||
key.className = key.className.replace(/ cbi-input-invalid/g, "");
|
||||
if (password.value.length == 0 && key.value.length == 0) {
|
||||
password.className += " cbi-input-invalid";
|
||||
key.className += " cbi-input-invalid";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
password.onkeyup = checkCryptoConfig;
|
||||
key.onkeyup = checkCryptoConfig;
|
||||
if (form) {
|
||||
if (!form.cbi_validators) {
|
||||
form.cbi_validators = [];
|
||||
}
|
||||
form.cbi_validators.push(checkCryptoConfig);
|
||||
}
|
||||
checkCryptoConfig();
|
||||
}(function(id) {
|
||||
return document.getElementById("cbid.<%=self.config%>.<%=self.sid%>." + id);
|
||||
}));
|
||||
//]]></script>
|
||||
Reference in new issue
Block a user