luci-app-passwall2: sync upstream

last commit: 743232172c
This commit is contained in:
gitea-action 2024-12-18 22:00:30 +08:00
parent da558465eb
commit a2c38903f1
34 changed files with 1315 additions and 1181 deletions

View File

@ -158,7 +158,7 @@ end
function get_now_use_node() function get_now_use_node()
local e = {} local e = {}
local node = api.get_cache_var("GLOBAL_node") local node = api.get_cache_var("ACL_GLOBAL_node")
if node then if node then
e["global"] = node e["global"] = node
end end
@ -319,7 +319,7 @@ end
function clear_all_nodes() function clear_all_nodes()
uci:set(appname, '@global[0]', "enabled", "0") uci:set(appname, '@global[0]', "enabled", "0")
uci:set(appname, '@global[0]', "node", "nil") uci:delete(appname, '@global[0]', "node")
uci:foreach(appname, "socks", function(t) uci:foreach(appname, "socks", function(t)
uci:delete(appname, t[".name"]) uci:delete(appname, t[".name"])
uci:set_list(appname, t[".name"], "autoswitch_backup_node", {}) uci:set_list(appname, t[".name"], "autoswitch_backup_node", {})
@ -328,7 +328,7 @@ function clear_all_nodes()
uci:delete(appname, t[".name"]) uci:delete(appname, t[".name"])
end) end)
uci:foreach(appname, "acl_rule", function(t) uci:foreach(appname, "acl_rule", function(t)
uci:set(appname, t[".name"], "node", "nil") uci:delete(appname, t[".name"], "node")
end) end)
uci:foreach(appname, "nodes", function(node) uci:foreach(appname, "nodes", function(node)
uci:delete(appname, node['.name']) uci:delete(appname, node['.name'])
@ -341,8 +341,8 @@ end
function delete_select_nodes() function delete_select_nodes()
local ids = luci.http.formvalue("ids") local ids = luci.http.formvalue("ids")
string.gsub(ids, '[^' .. "," .. ']+', function(w) string.gsub(ids, '[^' .. "," .. ']+', function(w)
if (uci:get(appname, "@global[0]", "node") or "nil") == w then if (uci:get(appname, "@global[0]", "node") or "") == w then
uci:set(appname, '@global[0]', "node", "nil") uci:delete(appname, '@global[0]', "node")
end end
uci:foreach(appname, "socks", function(t) uci:foreach(appname, "socks", function(t)
if t["node"] == w then if t["node"] == w then
@ -363,7 +363,7 @@ function delete_select_nodes()
end) end)
uci:foreach(appname, "acl_rule", function(t) uci:foreach(appname, "acl_rule", function(t)
if t["node"] == w then if t["node"] == w then
uci:set(appname, t[".name"], "node", "nil") uci:delete(appname, t[".name"], "node")
end end
end) end)
uci:foreach(appname, "nodes", function(t) uci:foreach(appname, "nodes", function(t)

View File

@ -68,7 +68,7 @@ o.rmempty = false
---- Remarks ---- Remarks
o = s:option(Value, "remarks", translate("Remarks")) o = s:option(Value, "remarks", translate("Remarks"))
o.default = arg[1] o.default = arg[1]
o.rmempty = true o.rmempty = false
o = s:option(ListValue, "interface", translate("Source Interface")) o = s:option(ListValue, "interface", translate("Source Interface"))
o:value("", translate("All")) o:value("", translate("All"))
@ -165,9 +165,8 @@ sources.write = dynamicList_write
---- TCP No Redir Ports ---- TCP No Redir Ports
local TCP_NO_REDIR_PORTS = uci:get(appname, "@global_forwarding[0]", "tcp_no_redir_ports") local TCP_NO_REDIR_PORTS = uci:get(appname, "@global_forwarding[0]", "tcp_no_redir_ports")
o = s:option(Value, "tcp_no_redir_ports", translate("TCP No Redir Ports")) o = s:option(Value, "tcp_no_redir_ports", translate("TCP No Redir Ports"))
o.default = "default" o:value("", translate("Use global config") .. "(" .. TCP_NO_REDIR_PORTS .. ")")
o:value("disable", translate("No patterns are used")) o:value("disable", translate("No patterns are used"))
o:value("default", translate("Use global config") .. "(" .. TCP_NO_REDIR_PORTS .. ")")
o:value("1:65535", translate("All")) o:value("1:65535", translate("All"))
o.validate = port_validate o.validate = port_validate
@ -177,53 +176,74 @@ o = s:option(Value, "udp_no_redir_ports", translate("UDP No Redir Ports"),
"<font color='red'>" .. "<font color='red'>" ..
translate("If you don't want to let the device in the list to go proxy, please choose all.") .. translate("If you don't want to let the device in the list to go proxy, please choose all.") ..
"</font>") "</font>")
o.default = "default" o:value("", translate("Use global config") .. "(" .. UDP_NO_REDIR_PORTS .. ")")
o:value("disable", translate("No patterns are used")) o:value("disable", translate("No patterns are used"))
o:value("default", translate("Use global config") .. "(" .. UDP_NO_REDIR_PORTS .. ")")
o:value("1:65535", translate("All")) o:value("1:65535", translate("All"))
o.validate = port_validate o.validate = port_validate
node = s:option(ListValue, "node", "<a style='color: red'>" .. translate("Node") .. "</a>") o = s:option(DummyValue, "_hide_node_option", "")
node.default = "default" o.template = "passwall2/cbi/hidevalue"
node:value("default", translate("Use global config")) o.value = "1"
for k, v in pairs(nodes_table) do o:depends({ tcp_no_redir_ports = "1:65535", udp_no_redir_ports = "1:65535" })
node:value(v.id, v["remark"]) if TCP_NO_REDIR_PORTS == "1:65535" and UDP_NO_REDIR_PORTS == "1:65535" then
o:depends({ tcp_no_redir_ports = "", udp_no_redir_ports = "" })
end end
local GLOBAL_ENABLED = uci:get(appname, "@global[0]", "enabled")
local NODE = uci:get(appname, "@global[0]", "node")
o = s:option(ListValue, "node", "<a style='color: red'>" .. translate("Node") .. "</a>")
if GLOBAL_ENABLED == "1" and NODE then
o:value("", translate("Use global config") .. "(" .. api.get_node_name(NODE) .. ")")
end
o:depends({ _hide_node_option = "1", ['!reverse'] = true })
o = s:option(DummyValue, "_hide_dns_option", "")
o.template = "passwall2/cbi/hidevalue"
o.value = "1"
o:depends({ node = "" })
if GLOBAL_ENABLED == "1" and NODE then
o:depends({ node = NODE })
end
o = s:option(DummyValue, "_xray_node", "")
o.template = "passwall2/cbi/hidevalue"
o.value = "1"
o:depends({ __hide = true })
---- TCP Redir Ports ---- TCP Redir Ports
local TCP_REDIR_PORTS = uci:get(appname, "@global_forwarding[0]", "tcp_redir_ports") local TCP_REDIR_PORTS = uci:get(appname, "@global_forwarding[0]", "tcp_redir_ports")
o = s:option(Value, "tcp_redir_ports", translate("TCP Redir Ports")) o = s:option(Value, "tcp_redir_ports", translate("TCP Redir Ports"))
o.default = "default" o:value("", translate("Use global config") .. "(" .. TCP_REDIR_PORTS .. ")")
o:value("default", translate("Use global config") .. "(" .. TCP_REDIR_PORTS .. ")")
o:value("1:65535", translate("All")) o:value("1:65535", translate("All"))
o:value("22,25,53,143,465,587,853,993,995,80,443", translate("Common Use")) o:value("22,25,53,143,465,587,853,993,995,80,443", translate("Common Use"))
o:value("80,443", "80,443") o:value("80,443", "80,443")
o.validate = port_validate o.validate = port_validate
o:depends({ _hide_node_option = "1", ['!reverse'] = true })
---- UDP Redir Ports ---- UDP Redir Ports
local UDP_REDIR_PORTS = uci:get(appname, "@global_forwarding[0]", "udp_redir_ports") local UDP_REDIR_PORTS = uci:get(appname, "@global_forwarding[0]", "udp_redir_ports")
o = s:option(Value, "udp_redir_ports", translate("UDP Redir Ports")) o = s:option(Value, "udp_redir_ports", translate("UDP Redir Ports"))
o.default = "default" o:value("", translate("Use global config") .. "(" .. UDP_REDIR_PORTS .. ")")
o:value("default", translate("Use global config") .. "(" .. UDP_REDIR_PORTS .. ")")
o:value("1:65535", translate("All")) o:value("1:65535", translate("All"))
o.validate = port_validate o.validate = port_validate
o:depends({ _hide_node_option = "1", ['!reverse'] = true })
o = s:option(ListValue, "direct_dns_query_strategy", translate("Direct Query Strategy")) o = s:option(ListValue, "direct_dns_query_strategy", translate("Direct Query Strategy"))
o.default = "UseIP" o.default = "UseIP"
o:value("UseIP") o:value("UseIP")
o:value("UseIPv4") o:value("UseIPv4")
o:value("UseIPv6") o:value("UseIPv6")
o:depends({ node = "default", ['!reverse'] = true }) o:depends({ _hide_dns_option = "1", ['!reverse'] = true })
o = s:option(Flag, "write_ipset_direct", translate("Direct DNS result write to IPSet"), translate("Perform the matching direct domain name rules into IP to IPSet/NFTSet, and then connect directly (not entering the core). Maybe conflict with some special circumstances.")) o = s:option(Flag, "write_ipset_direct", translate("Direct DNS result write to IPSet"), translate("Perform the matching direct domain name rules into IP to IPSet/NFTSet, and then connect directly (not entering the core). Maybe conflict with some special circumstances."))
o.default = "1" o.default = "1"
o:depends({ node = "default", ['!reverse'] = true }) o:depends({ direct_dns_query_strategy = "", ['!reverse'] = true })
o = s:option(ListValue, "remote_dns_protocol", translate("Remote DNS Protocol")) o = s:option(ListValue, "remote_dns_protocol", translate("Remote DNS Protocol"))
o:value("tcp", "TCP") o:value("tcp", "TCP")
o:value("doh", "DoH") o:value("doh", "DoH")
o:value("udp", "UDP") o:value("udp", "UDP")
o:depends({ node = "default", ['!reverse'] = true }) o:depends({ _hide_dns_option = "1", ['!reverse'] = true })
---- DNS Forward ---- DNS Forward
o = s:option(Value, "remote_dns", translate("Remote DNS")) o = s:option(Value, "remote_dns", translate("Remote DNS"))
@ -291,8 +311,8 @@ o.rows = 5
o.wrap = "off" o.wrap = "off"
o:depends({ __hide = true }) o:depends({ __hide = true })
o.remove = function(self, section) o.remove = function(self, section)
local node_value = node:formvalue(arg[1]) local node_value = s.fields["node"]:formvalue(arg[1])
if node_value ~= "nil" then if node_value then
local node_t = m:get(node_value) or {} local node_t = m:get(node_value) or {}
if node_t.type == "Xray" then if node_t.type == "Xray" then
AbstractValue.remove(self, section) AbstractValue.remove(self, section)
@ -301,11 +321,14 @@ o.remove = function(self, section)
end end
for k, v in pairs(nodes_table) do for k, v in pairs(nodes_table) do
s.fields["node"]:value(v.id, v["remark"])
if v.type == "Xray" then if v.type == "Xray" then
s.fields["remote_dns_client_ip"]:depends({ node = v.id, remote_dns_protocol = "tcp" }) s.fields["_xray_node"]:depends({ node = v.id })
s.fields["remote_dns_client_ip"]:depends({ node = v.id, remote_dns_protocol = "doh" })
s.fields["dns_hosts"]:depends({ node = v.id })
end end
end end
s.fields["remote_dns_client_ip"]:depends({ _xray_node = "1", remote_dns_protocol = "tcp" })
s.fields["remote_dns_client_ip"]:depends({ _xray_node = "1", remote_dns_protocol = "doh" })
s.fields["dns_hosts"]:depends({ _xray_node = "1" })
return m return m

View File

@ -79,14 +79,14 @@ o = s:taboption("Main", Flag, "enabled", translate("Main switch"))
o.rmempty = false o.rmempty = false
---- Node ---- Node
node = s:taboption("Main", ListValue, "node", "<a style='color: red'>" .. translate("Node") .. "</a>") o = s:taboption("Main", ListValue, "node", "<a style='color: red'>" .. translate("Node") .. "</a>")
node:value("nil", translate("Close")) o:value("", translate("Close"))
-- 分流 -- 分流
if (has_singbox or has_xray) and #nodes_table > 0 then if (has_singbox or has_xray) and #nodes_table > 0 then
local function get_cfgvalue(shunt_node_id, option) local function get_cfgvalue(shunt_node_id, option)
return function(self, section) return function(self, section)
return m:get(shunt_node_id, option) or "nil" return m:get(shunt_node_id, option)
end end
end end
local function get_write(shunt_node_id, option) local function get_write(shunt_node_id, option)
@ -138,7 +138,7 @@ if (has_singbox or has_xray) and #nodes_table > 0 then
if (has_singbox and has_xray) or (v.type == "sing-box" and not has_singbox) or (v.type == "Xray" and not has_xray) then if (has_singbox and has_xray) or (v.type == "sing-box" and not has_singbox) or (v.type == "Xray" and not has_xray) then
type:depends("node", v.id) type:depends("node", v.id)
else else
type:depends("node", "hide") --不存在的依赖,即始终隐藏 type:depends({ __hide = true }) --不存在的依赖,即始终隐藏
end end
uci:foreach(appname, "shunt_rules", function(e) uci:foreach(appname, "shunt_rules", function(e)
@ -149,8 +149,8 @@ if (has_singbox or has_xray) and #nodes_table > 0 then
o.cfgvalue = get_cfgvalue(v.id, id) o.cfgvalue = get_cfgvalue(v.id, id)
o.write = get_write(v.id, id) o.write = get_write(v.id, id)
o:depends("node", v.id) o:depends("node", v.id)
o.default = "nil" o.default = ""
o:value("nil", translate("Close")) o:value("", translate("Close"))
o:value("_default", translate("Default")) o:value("_default", translate("Default"))
o:value("_direct", translate("Direct Connection")) o:value("_direct", translate("Direct Connection"))
o:value("_blackhole", translate("Blackhole")) o:value("_blackhole", translate("Blackhole"))
@ -158,9 +158,9 @@ if (has_singbox or has_xray) and #nodes_table > 0 then
local pt = s:taboption("Main", ListValue, vid .. "-".. id .. "_proxy_tag", string.format('* <a style="color:red">%s</a>', e.remarks .. " " .. translate("Preproxy"))) local pt = s:taboption("Main", ListValue, vid .. "-".. id .. "_proxy_tag", string.format('* <a style="color:red">%s</a>', e.remarks .. " " .. translate("Preproxy")))
pt.cfgvalue = get_cfgvalue(v.id, id .. "_proxy_tag") pt.cfgvalue = get_cfgvalue(v.id, id .. "_proxy_tag")
pt.write = get_write(v.id, id .. "_proxy_tag") pt.write = get_write(v.id, id .. "_proxy_tag")
pt:value("nil", translate("Close")) pt.default = ""
pt:value("", translate("Close"))
pt:value("main", translate("Preproxy Node")) pt:value("main", translate("Preproxy Node"))
pt.default = "nil"
for k1, v1 in pairs(socks_list) do for k1, v1 in pairs(socks_list) do
o:value(v1.id, v1.remark) o:value(v1.id, v1.remark)
end end
@ -202,7 +202,7 @@ if (has_singbox or has_xray) and #nodes_table > 0 then
o = s:taboption("Main", ListValue, vid .. "-" .. id, string.format('* <a style="color:red">%s</a>', translate("Default Preproxy")), translate("When using, localhost will connect this node first and then use this node to connect the default node.")) o = s:taboption("Main", ListValue, vid .. "-" .. id, string.format('* <a style="color:red">%s</a>', translate("Default Preproxy")), translate("When using, localhost will connect this node first and then use this node to connect the default node."))
o.cfgvalue = get_cfgvalue(v.id, id) o.cfgvalue = get_cfgvalue(v.id, id)
o.write = get_write(v.id, id) o.write = get_write(v.id, id)
o:value("nil", translate("Close")) o:value("", translate("Close"))
o:value("main", translate("Preproxy Node")) o:value("main", translate("Preproxy Node"))
for k1, v1 in pairs(normal_list) do for k1, v1 in pairs(normal_list) do
if v1.protocol ~= "_balancing" then if v1.protocol ~= "_balancing" then
@ -216,7 +216,7 @@ if (has_singbox or has_xray) and #nodes_table > 0 then
tips.cfgvalue = function(t, n) tips.cfgvalue = function(t, n)
return string.format('<a style="color: red">%s</a>', translate("There are no available nodes, please add or subscribe nodes first.")) return string.format('<a style="color: red">%s</a>', translate("There are no available nodes, please add or subscribe nodes first."))
end end
tips:depends({ node = "nil", ["!reverse"] = true }) tips:depends({ node = "", ["!reverse"] = true })
for k, v in pairs(shunt_list) do for k, v in pairs(shunt_list) do
tips:depends("node", v.id) tips:depends("node", v.id)
end end
@ -240,7 +240,7 @@ node_socks_port.datatype = "port"
node_socks_bind_local = s:taboption("Main", Flag, "node_socks_bind_local", translate("Node") .. " Socks " .. translate("Bind Local"), translate("When selected, it can only be accessed localhost.")) node_socks_bind_local = s:taboption("Main", Flag, "node_socks_bind_local", translate("Node") .. " Socks " .. translate("Bind Local"), translate("When selected, it can only be accessed localhost."))
node_socks_bind_local.default = "1" node_socks_bind_local.default = "1"
node_socks_bind_local:depends({ node = "nil", ["!reverse"] = true }) node_socks_bind_local:depends({ node = "", ["!reverse"] = true })
s:tab("DNS", translate("DNS")) s:tab("DNS", translate("DNS"))
@ -316,8 +316,8 @@ o.rows = 5
o.wrap = "off" o.wrap = "off"
o:depends({ __hide = true }) o:depends({ __hide = true })
o.remove = function(self, section) o.remove = function(self, section)
local node_value = node:formvalue(global_cfgid) local node_value = s.fields["node"]:formvalue(global_cfgid)
if node_value ~= "nil" then if node_value then
local node_t = m:get(node_value) or {} local node_t = m:get(node_value) or {}
if node_t.type == "Xray" then if node_t.type == "Xray" then
AbstractValue.remove(self, section) AbstractValue.remove(self, section)
@ -336,13 +336,14 @@ function o.write(e, e)
luci.http.redirect(api.url("log")) luci.http.redirect(api.url("log"))
end end
for k, v in pairs(nodes_table) do o = s:taboption("DNS", DummyValue, "_xray_node", "")
if v.type == "Xray" then o.template = "passwall2/cbi/hidevalue"
s.fields["remote_dns_client_ip"]:depends({ node = v.id, remote_dns_protocol = "tcp" }) o.value = "1"
s.fields["remote_dns_client_ip"]:depends({ node = v.id, remote_dns_protocol = "doh" }) o:depends({ __hide = true })
s.fields["dns_hosts"]:depends({ node = v.id })
end s.fields["remote_dns_client_ip"]:depends({ _xray_node = "1", remote_dns_protocol = "tcp" })
end s.fields["remote_dns_client_ip"]:depends({ _xray_node = "1", remote_dns_protocol = "doh" })
s.fields["dns_hosts"]:depends({ _xray_node = "1" })
s:tab("log", translate("Log")) s:tab("log", translate("Log"))
o = s:taboption("log", Flag, "log_node", translate("Enable Node Log")) o = s:taboption("log", Flag, "log_node", translate("Enable Node Log"))
@ -365,30 +366,30 @@ o.template = appname .. "/global/faq"
o = s:taboption("Main", Flag, "socks_enabled", "Socks " .. translate("Main switch")) o = s:taboption("Main", Flag, "socks_enabled", "Socks " .. translate("Main switch"))
o.rmempty = false o.rmempty = false
s = m:section(TypedSection, "socks", translate("Socks Config")) s2 = m:section(TypedSection, "socks", translate("Socks Config"))
s.template = "cbi/tblsection" s2.template = "cbi/tblsection"
s.anonymous = true s2.anonymous = true
s.addremove = true s2.addremove = true
s.extedit = api.url("socks_config", "%s") s2.extedit = api.url("socks_config", "%s")
function s.create(e, t) function s2.create(e, t)
local uuid = api.gen_short_uuid() local uuid = api.gen_short_uuid()
t = uuid t = uuid
TypedSection.create(e, t) TypedSection.create(e, t)
luci.http.redirect(e.extedit:format(t)) luci.http.redirect(e.extedit:format(t))
end end
o = s:option(DummyValue, "status", translate("Status")) o = s2:option(DummyValue, "status", translate("Status"))
o.rawhtml = true o.rawhtml = true
o.cfgvalue = function(t, n) o.cfgvalue = function(t, n)
return string.format('<div class="_status" socks_id="%s"></div>', n) return string.format('<div class="_status" socks_id="%s"></div>', n)
end end
---- Enable ---- Enable
o = s:option(Flag, "enabled", translate("Enable")) o = s2:option(Flag, "enabled", translate("Enable"))
o.default = 1 o.default = 1
o.rmempty = false o.rmempty = false
socks_node = s:option(ListValue, "node", translate("Socks Node")) o = s2:option(ListValue, "node", translate("Socks Node"))
local n = 1 local n = 1
uci:foreach(appname, "socks", function(s) uci:foreach(appname, "socks", function(s)
@ -398,25 +399,22 @@ uci:foreach(appname, "socks", function(s)
n = n + 1 n = n + 1
end) end)
o = s:option(Value, "port", "Socks " .. translate("Listen Port")) o = s2:option(Value, "port", "Socks " .. translate("Listen Port"))
o.default = n + 1080 o.default = n + 1080
o.datatype = "port" o.datatype = "port"
o.rmempty = false o.rmempty = false
if has_singbox or has_xray then if has_singbox or has_xray then
o = s:option(Value, "http_port", "HTTP " .. translate("Listen Port") .. " " .. translate("0 is not use")) o = s2:option(Value, "http_port", "HTTP " .. translate("Listen Port") .. " " .. translate("0 is not use"))
o.default = 0 o.default = 0
o.datatype = "port" o.datatype = "port"
end end
for k, v in pairs(nodes_table) do for k, v in pairs(nodes_table) do
node:value(v.id, v["remark"]) s.fields["node"]:value(v.id, v["remark"])
if v.type == "Socks" then s2.fields["node"]:value(v.id, v["remark"])
if has_singbox or has_xray then if v.type == "Xray" then
socks_node:value(v.id, v["remark"]) s.fields["_xray_node"]:depends({ node = v.id })
end
else
socks_node:value(v.id, v["remark"])
end end
end end

View File

@ -54,13 +54,17 @@ function s.remove(e, t)
end end
end) end)
TypedSection.remove(e, t) TypedSection.remove(e, t)
local new_node = "nil" local new_node
local node0 = m:get("@nodes[0]") or nil local node0 = m:get("@nodes[0]") or nil
if node0 then if node0 then
new_node = node0[".name"] new_node = node0[".name"]
end end
if (m:get("@global[0]", "node") or "nil") == t then if (m:get("@global[0]", "node") or "") == t then
m:set('@global[0]', "node", new_node) if new_node then
m:set('@global[0]', "node", new_node)
else
m:del('@global[0]', "node")
end
end end
end end

View File

@ -19,43 +19,46 @@ s = m:section(TypedSection, "global_delay", translate("Delay Settings"))
s.anonymous = true s.anonymous = true
s.addremove = false s.addremove = false
---- Delay Start
o = s:option(Value, "start_delay", translate("Delay Start"), translate("Units:seconds"))
o.default = "1"
o.rmempty = true
---- Open and close Daemon ---- Open and close Daemon
o = s:option(Flag, "start_daemon", translate("Open and close Daemon")) o = s:option(Flag, "start_daemon", translate("Open and close Daemon"))
o.default = 1 o.default = 1
o.rmempty = false o.rmempty = false
--[[ ---- Delay Start
---- Open and close automatically o = s:option(Value, "start_delay", translate("Delay Start"), translate("Units:seconds"))
o = s:option(Flag, "auto_on", translate("Open and close automatically")) o.default = "1"
o.default = 0 o.rmempty = true
o.rmempty = false
---- Automatically turn off time for index, value in ipairs({"stop", "start", "restart"}) do
o = s:option(ListValue, "time_off", translate("Automatically turn off time")) o = s:option(ListValue, value .. "_week_mode", translate(value .. " automatically mode"))
o.default = nil o:value("", translate("Disable"))
o:depends("auto_on", true) o:value(8, translate("Loop Mode"))
o:value(nil, translate("Disable")) o:value(7, translate("Every day"))
for e = 0, 23 do o:value(e, e .. translate("oclock")) end o:value(1, translate("Every Monday"))
o:value(2, translate("Every Tuesday"))
o:value(3, translate("Every Wednesday"))
o:value(4, translate("Every Thursday"))
o:value(5, translate("Every Friday"))
o:value(6, translate("Every Saturday"))
o:value(0, translate("Every Sunday"))
---- Automatically turn on time o = s:option(ListValue, value .. "_time_mode", translate(value .. " Time(Every day)"))
o = s:option(ListValue, "time_on", translate("Automatically turn on time")) for t = 0, 23 do o:value(t, t .. ":00") end
o.default = nil o.default = 0
o:depends("auto_on", true) o:depends(value .. "_week_mode", "0")
o:value(nil, translate("Disable")) o:depends(value .. "_week_mode", "1")
for e = 0, 23 do o:value(e, e .. translate("oclock")) end o:depends(value .. "_week_mode", "2")
o:depends(value .. "_week_mode", "3")
o:depends(value .. "_week_mode", "4")
o:depends(value .. "_week_mode", "5")
o:depends(value .. "_week_mode", "6")
o:depends(value .. "_week_mode", "7")
---- Automatically restart time o = s:option(ListValue, value .. "_interval_mode", translate(value .. " Interval(Hour)"))
o = s:option(ListValue, "time_restart", translate("Automatically restart time")) for t = 1, 24 do o:value(t, t .. " " .. translate("Hour")) end
o.default = nil o.default = 2
o:depends("auto_on", true) o:depends(value .. "_week_mode", "8")
o:value(nil, translate("Disable")) end
for e = 0, 23 do o:value(e, e .. translate("oclock")) end
--]]
-- [[ Forwarding Settings ]]-- -- [[ Forwarding Settings ]]--
s = m:section(TypedSection, "global_forwarding", translate("Forwarding Settings")) s = m:section(TypedSection, "global_forwarding", translate("Forwarding Settings"))

View File

@ -10,7 +10,7 @@ local type_name = "Hysteria2"
local option_prefix = "hysteria2_" local option_prefix = "hysteria2_"
local function option_name(name) local function _n(name)
return option_prefix .. name return option_prefix .. name
end end
@ -18,58 +18,58 @@ end
s.fields["type"]:value(type_name, "Hysteria2") s.fields["type"]:value(type_name, "Hysteria2")
o = s:option(ListValue, option_name("protocol"), translate("Protocol")) o = s:option(ListValue, _n("protocol"), translate("Protocol"))
o:value("udp", "UDP") o:value("udp", "UDP")
o = s:option(Value, option_name("address"), translate("Address (Support Domain Name)")) o = s:option(Value, _n("address"), translate("Address (Support Domain Name)"))
o = s:option(Value, option_name("port"), translate("Port")) o = s:option(Value, _n("port"), translate("Port"))
o.datatype = "port" o.datatype = "port"
o = s:option(Value, option_name("hop"), translate("Additional ports for hysteria hop")) o = s:option(Value, _n("hop"), translate("Additional ports for hysteria hop"))
o.rewrite_option = o.option o.rewrite_option = o.option
o = s:option(Value, option_name("obfs"), translate("Obfs Password")) o = s:option(Value, _n("obfs"), translate("Obfs Password"))
o.rewrite_option = o.option o.rewrite_option = o.option
o = s:option(Value, option_name("auth_password"), translate("Auth Password")) o = s:option(Value, _n("auth_password"), translate("Auth Password"))
o.password = true o.password = true
o.rewrite_option = o.option o.rewrite_option = o.option
o = s:option(Flag, option_name("fast_open"), translate("Fast Open")) o = s:option(Flag, _n("fast_open"), translate("Fast Open"))
o.default = "0" o.default = "0"
o = s:option(Value, option_name("tls_serverName"), translate("Domain")) o = s:option(Value, _n("tls_serverName"), translate("Domain"))
o = s:option(Flag, option_name("tls_allowInsecure"), translate("allowInsecure"), translate("Whether unsafe connections are allowed. When checked, Certificate validation will be skipped.")) o = s:option(Flag, _n("tls_allowInsecure"), translate("allowInsecure"), translate("Whether unsafe connections are allowed. When checked, Certificate validation will be skipped."))
o.default = "0" o.default = "0"
o = s:option(Value, option_name("tls_pinSHA256"), translate("PinSHA256"),translate("Certificate fingerprint")) o = s:option(Value, _n("tls_pinSHA256"), translate("PinSHA256"),translate("Certificate fingerprint"))
o.rewrite_option = o.option o.rewrite_option = o.option
o = s:option(Value, option_name("up_mbps"), translate("Max upload Mbps")) o = s:option(Value, _n("up_mbps"), translate("Max upload Mbps"))
o.rewrite_option = o.option o.rewrite_option = o.option
o = s:option(Value, option_name("down_mbps"), translate("Max download Mbps")) o = s:option(Value, _n("down_mbps"), translate("Max download Mbps"))
o.rewrite_option = o.option o.rewrite_option = o.option
o = s:option(Value, option_name("hop_interval"), translate("Hop Interval"), translate("Example:") .. "30s (≥5s)") o = s:option(Value, _n("hop_interval"), translate("Hop Interval"), translate("Example:") .. "30s (≥5s)")
o.rewrite_option = o.option o.rewrite_option = o.option
o = s:option(Value, option_name("recv_window"), translate("QUIC stream receive window")) o = s:option(Value, _n("recv_window"), translate("QUIC stream receive window"))
o.rewrite_option = o.option o.rewrite_option = o.option
o = s:option(Value, option_name("recv_window_conn"), translate("QUIC connection receive window")) o = s:option(Value, _n("recv_window_conn"), translate("QUIC connection receive window"))
o.rewrite_option = o.option o.rewrite_option = o.option
o = s:option(Value, option_name("idle_timeout"), translate("Idle Timeout"), translate("Example:") .. "30s (4s-120s)") o = s:option(Value, _n("idle_timeout"), translate("Idle Timeout"), translate("Example:") .. "30s (4s-120s)")
o.rewrite_option = o.option o.rewrite_option = o.option
o = s:option(Flag, option_name("disable_mtu_discovery"), translate("Disable MTU detection")) o = s:option(Flag, _n("disable_mtu_discovery"), translate("Disable MTU detection"))
o.default = "0" o.default = "0"
o.rewrite_option = o.option o.rewrite_option = o.option
o = s:option(Flag, option_name("lazy_start"), translate("Lazy Start")) o = s:option(Flag, _n("lazy_start"), translate("Lazy Start"))
o.default = "0" o.default = "0"
o.rewrite_option = o.option o.rewrite_option = o.option

View File

@ -10,7 +10,7 @@ local type_name = "Naiveproxy"
local option_prefix = "naive_" local option_prefix = "naive_"
local function option_name(name) local function _n(name)
return option_prefix .. name return option_prefix .. name
end end
@ -18,18 +18,18 @@ end
s.fields["type"]:value(type_name, translate("NaiveProxy")) s.fields["type"]:value(type_name, translate("NaiveProxy"))
o = s:option(ListValue, option_name("protocol"), translate("Protocol")) o = s:option(ListValue, _n("protocol"), translate("Protocol"))
o:value("https", translate("HTTPS")) o:value("https", translate("HTTPS"))
o:value("quic", translate("QUIC")) o:value("quic", translate("QUIC"))
o = s:option(Value, option_name("address"), translate("Address (Support Domain Name)")) o = s:option(Value, _n("address"), translate("Address (Support Domain Name)"))
o = s:option(Value, option_name("port"), translate("Port")) o = s:option(Value, _n("port"), translate("Port"))
o.datatype = "port" o.datatype = "port"
o = s:option(Value, option_name("username"), translate("Username")) o = s:option(Value, _n("username"), translate("Username"))
o = s:option(Value, option_name("password"), translate("Password")) o = s:option(Value, _n("password"), translate("Password"))
o.password = true o.password = true
api.luci_types(arg[1], m, s, type_name, option_prefix) api.luci_types(arg[1], m, s, type_name, option_prefix)

View File

@ -14,7 +14,7 @@ local type_name = "Xray"
local option_prefix = "xray_" local option_prefix = "xray_"
local function option_name(name) local function _n(name)
return option_prefix .. name return option_prefix .. name
end end
@ -33,7 +33,7 @@ local xray_version = api.get_app_version("xray")
s.fields["type"]:value(type_name, "Xray") s.fields["type"]:value(type_name, "Xray")
o = s:option(ListValue, option_name("protocol"), translate("Protocol")) o = s:option(ListValue, _n("protocol"), translate("Protocol"))
o:value("vmess", translate("Vmess")) o:value("vmess", translate("Vmess"))
o:value("vless", translate("VLESS")) o:value("vless", translate("VLESS"))
o:value("http", translate("HTTP")) o:value("http", translate("HTTP"))
@ -45,9 +45,9 @@ o:value("_balancing", translate("Balancing"))
o:value("_shunt", translate("Shunt")) o:value("_shunt", translate("Shunt"))
o:value("_iface", translate("Custom Interface")) o:value("_iface", translate("Custom Interface"))
o = s:option(Value, option_name("iface"), translate("Interface")) o = s:option(Value, _n("iface"), translate("Interface"))
o.default = "eth1" o.default = "eth1"
o:depends({ [option_name("protocol")] = "_iface" }) o:depends({ [_n("protocol")] = "_iface" })
local nodes_table = {} local nodes_table = {}
local balancers_table = {} local balancers_table = {}
@ -96,12 +96,12 @@ uci:foreach(appname, "socks", function(s)
end) end)
-- 负载均衡列表 -- 负载均衡列表
local o = s:option(DynamicList, option_name("balancing_node"), translate("Load balancing node list"), translate("Load balancing node list, <a target='_blank' href='https://toutyrater.github.io/routing/balance2.html'>document</a>")) local o = s:option(DynamicList, _n("balancing_node"), translate("Load balancing node list"), translate("Load balancing node list, <a target='_blank' href='https://toutyrater.github.io/routing/balance2.html'>document</a>"))
o:depends({ [option_name("protocol")] = "_balancing" }) o:depends({ [_n("protocol")] = "_balancing" })
for k, v in pairs(nodes_table) do o:value(v.id, v.remark) end for k, v in pairs(nodes_table) do o:value(v.id, v.remark) end
local o = s:option(ListValue, option_name("balancingStrategy"), translate("Balancing Strategy")) local o = s:option(ListValue, _n("balancingStrategy"), translate("Balancing Strategy"))
o:depends({ [option_name("protocol")] = "_balancing" }) o:depends({ [_n("protocol")] = "_balancing" })
o:value("random") o:value("random")
o:value("roundRobin") o:value("roundRobin")
o:value("leastPing") o:value("leastPing")
@ -109,11 +109,11 @@ o.default = "leastPing"
-- Fallback Node -- Fallback Node
if api.compare_versions(xray_version, ">=", "1.8.10") then if api.compare_versions(xray_version, ">=", "1.8.10") then
local o = s:option(ListValue, option_name("fallback_node"), translate("Fallback Node")) local o = s:option(ListValue, _n("fallback_node"), translate("Fallback Node"))
if api.compare_versions(xray_version, ">=", "1.8.12") then if api.compare_versions(xray_version, ">=", "1.8.12") then
o:depends({ [option_name("protocol")] = "_balancing" }) o:depends({ [_n("protocol")] = "_balancing" })
else else
o:depends({ [option_name("balancingStrategy")] = "leastPing" }) o:depends({ [_n("balancingStrategy")] = "leastPing" })
end end
local function check_fallback_chain(fb) local function check_fallback_chain(fb)
for k, v in pairs(fallback_table) do for k, v in pairs(fallback_table) do
@ -132,11 +132,11 @@ if api.compare_versions(xray_version, ">=", "1.8.10") then
end end
-- 探测地址 -- 探测地址
local ucpu = s:option(Flag, option_name("useCustomProbeUrl"), translate("Use Custome Probe URL"), translate("By default the built-in probe URL will be used, enable this option to use a custom probe URL.")) local ucpu = s:option(Flag, _n("useCustomProbeUrl"), translate("Use Custome Probe URL"), translate("By default the built-in probe URL will be used, enable this option to use a custom probe URL."))
ucpu:depends({ [option_name("balancingStrategy")] = "leastPing" }) ucpu:depends({ [_n("balancingStrategy")] = "leastPing" })
local pu = s:option(Value, option_name("probeUrl"), translate("Probe URL")) local pu = s:option(Value, _n("probeUrl"), translate("Probe URL"))
pu:depends({ [option_name("useCustomProbeUrl")] = true }) pu:depends({ [_n("useCustomProbeUrl")] = true })
pu:value("https://cp.cloudflare.com/", "Cloudflare") pu:value("https://cp.cloudflare.com/", "Cloudflare")
pu:value("https://www.gstatic.com/generate_204", "Gstatic") pu:value("https://www.gstatic.com/generate_204", "Gstatic")
pu:value("https://www.google.com/generate_204", "Google") pu:value("https://www.google.com/generate_204", "Google")
@ -147,27 +147,27 @@ pu.default = "https://www.google.com/generate_204"
pu.description = translate("The URL used to detect the connection status.") pu.description = translate("The URL used to detect the connection status.")
-- 探测间隔 -- 探测间隔
local pi = s:option(Value, option_name("probeInterval"), translate("Probe Interval")) local pi = s:option(Value, _n("probeInterval"), translate("Probe Interval"))
pi:depends({ [option_name("balancingStrategy")] = "leastPing" }) pi:depends({ [_n("balancingStrategy")] = "leastPing" })
pi.default = "1m" pi.default = "1m"
pi.description = translate("The interval between initiating probes. Every time this time elapses, a server status check is performed on a server. The time format is numbers + units, such as '10s', '2h45m', and the supported time units are <code>ns</code>, <code>us</code>, <code>ms</code>, <code>s</code>, <code>m</code>, <code>h</code>, which correspond to nanoseconds, microseconds, milliseconds, seconds, minutes, and hours, respectively.") pi.description = translate("The interval between initiating probes. Every time this time elapses, a server status check is performed on a server. The time format is numbers + units, such as '10s', '2h45m', and the supported time units are <code>ns</code>, <code>us</code>, <code>ms</code>, <code>s</code>, <code>m</code>, <code>h</code>, which correspond to nanoseconds, microseconds, milliseconds, seconds, minutes, and hours, respectively.")
if api.compare_versions(xray_version, ">=", "1.8.12") then if api.compare_versions(xray_version, ">=", "1.8.12") then
ucpu:depends({ [option_name("protocol")] = "_balancing" }) ucpu:depends({ [_n("protocol")] = "_balancing" })
pi:depends({ [option_name("protocol")] = "_balancing" }) pi:depends({ [_n("protocol")] = "_balancing" })
else else
ucpu:depends({ [option_name("balancingStrategy")] = "leastPing" }) ucpu:depends({ [_n("balancingStrategy")] = "leastPing" })
pi:depends({ [option_name("balancingStrategy")] = "leastPing" }) pi:depends({ [_n("balancingStrategy")] = "leastPing" })
end end
-- [[ 分流模块 ]] -- [[ 分流模块 ]]
if #nodes_table > 0 then if #nodes_table > 0 then
o = s:option(Flag, option_name("preproxy_enabled"), translate("Preproxy")) o = s:option(Flag, _n("preproxy_enabled"), translate("Preproxy"))
o:depends({ [option_name("protocol")] = "_shunt" }) o:depends({ [_n("protocol")] = "_shunt" })
o = s:option(ListValue, option_name("main_node"), string.format('<a style="color:red">%s</a>', translate("Preproxy Node")), translate("Set the node to be used as a pre-proxy. Each rule (including <code>Default</code>) has a separate switch that controls whether this rule uses the pre-proxy or not.")) o = s:option(ListValue, _n("main_node"), string.format('<a style="color:red">%s</a>', translate("Preproxy Node")), translate("Set the node to be used as a pre-proxy. Each rule (including <code>Default</code>) has a separate switch that controls whether this rule uses the pre-proxy or not."))
o:depends({ [option_name("protocol")] = "_shunt", [option_name("preproxy_enabled")] = true }) o:depends({ [_n("protocol")] = "_shunt", [_n("preproxy_enabled")] = true })
for k, v in pairs(socks_list) do for k, v in pairs(socks_list) do
o:value(v.id, v.remark) o:value(v.id, v.remark)
end end
@ -180,16 +180,18 @@ if #nodes_table > 0 then
for k, v in pairs(nodes_table) do for k, v in pairs(nodes_table) do
o:value(v.id, v.remark) o:value(v.id, v.remark)
end end
o.default = "nil" if #o.keylist > 0 then
o.default = o.keylist[1]
end
end end
uci:foreach(appname, "shunt_rules", function(e) uci:foreach(appname, "shunt_rules", function(e)
if e[".name"] and e.remarks then if e[".name"] and e.remarks then
o = s:option(ListValue, option_name(e[".name"]), string.format('* <a href="%s" target="_blank">%s</a>', api.url("shunt_rules", e[".name"]), e.remarks)) o = s:option(ListValue, _n(e[".name"]), string.format('* <a href="%s" target="_blank">%s</a>', api.url("shunt_rules", e[".name"]), e.remarks))
o:value("nil", translate("Close")) o:value("", translate("Close"))
o:value("_default", translate("Default")) o:value("_default", translate("Default"))
o:value("_direct", translate("Direct Connection")) o:value("_direct", translate("Direct Connection"))
o:value("_blackhole", translate("Blackhole")) o:value("_blackhole", translate("Blackhole"))
o:depends({ [option_name("protocol")] = "_shunt" }) o:depends({ [_n("protocol")] = "_shunt" })
if #nodes_table > 0 then if #nodes_table > 0 then
for k, v in pairs(socks_list) do for k, v in pairs(socks_list) do
@ -201,28 +203,27 @@ uci:foreach(appname, "shunt_rules", function(e)
for k, v in pairs(iface_table) do for k, v in pairs(iface_table) do
o:value(v.id, v.remark) o:value(v.id, v.remark)
end end
local pt = s:option(ListValue, option_name(e[".name"] .. "_proxy_tag"), string.format('* <a style="color:red">%s</a>', e.remarks .. " " .. translate("Preproxy"))) local pt = s:option(ListValue, _n(e[".name"] .. "_proxy_tag"), string.format('* <a style="color:red">%s</a>', e.remarks .. " " .. translate("Preproxy")))
pt:value("nil", translate("Close")) pt:value("", translate("Close"))
pt:value("main", translate("Preproxy Node")) pt:value("main", translate("Preproxy Node"))
pt.default = "nil"
for k, v in pairs(nodes_table) do for k, v in pairs(nodes_table) do
o:value(v.id, v.remark) o:value(v.id, v.remark)
pt:depends({ [option_name("protocol")] = "_shunt", [option_name("preproxy_enabled")] = true, [option_name(e[".name"])] = v.id }) pt:depends({ [_n("protocol")] = "_shunt", [_n("preproxy_enabled")] = true, [_n(e[".name"])] = v.id })
end end
end end
end end
end) end)
o = s:option(DummyValue, option_name("shunt_tips"), " ") o = s:option(DummyValue, _n("shunt_tips"), " ")
o.not_rewrite = true o.not_rewrite = true
o.rawhtml = true o.rawhtml = true
o.cfgvalue = function(t, n) o.cfgvalue = function(t, n)
return string.format('<a style="color: red" href="../rule">%s</a>', translate("No shunt rules? Click me to go to add.")) return string.format('<a style="color: red" href="../rule">%s</a>', translate("No shunt rules? Click me to go to add."))
end end
o:depends({ [option_name("protocol")] = "_shunt" }) o:depends({ [_n("protocol")] = "_shunt" })
local o = s:option(ListValue, option_name("default_node"), string.format('* <a style="color:red">%s</a>', translate("Default"))) local o = s:option(ListValue, _n("default_node"), string.format('* <a style="color:red">%s</a>', translate("Default")))
o:depends({ [option_name("protocol")] = "_shunt" }) o:depends({ [_n("protocol")] = "_shunt" })
o:value("_direct", translate("Direct Connection")) o:value("_direct", translate("Direct Connection"))
o:value("_blackhole", translate("Blackhole")) o:value("_blackhole", translate("Blackhole"))
@ -236,17 +237,16 @@ if #nodes_table > 0 then
for k, v in pairs(iface_table) do for k, v in pairs(iface_table) do
o:value(v.id, v.remark) o:value(v.id, v.remark)
end end
local dpt = s:option(ListValue, option_name("default_proxy_tag"), string.format('* <a style="color:red">%s</a>', translate("Default Preproxy")), translate("When using, localhost will connect this node first and then use this node to connect the default node.")) local dpt = s:option(ListValue, _n("default_proxy_tag"), string.format('* <a style="color:red">%s</a>', translate("Default Preproxy")), translate("When using, localhost will connect this node first and then use this node to connect the default node."))
dpt:value("nil", translate("Close")) dpt:value("", translate("Close"))
dpt:value("main", translate("Preproxy Node")) dpt:value("main", translate("Preproxy Node"))
dpt.default = "nil"
for k, v in pairs(nodes_table) do for k, v in pairs(nodes_table) do
o:value(v.id, v.remark) o:value(v.id, v.remark)
dpt:depends({ [option_name("protocol")] = "_shunt", [option_name("preproxy_enabled")] = true, [option_name("default_node")] = v.id }) dpt:depends({ [_n("protocol")] = "_shunt", [_n("preproxy_enabled")] = true, [_n("default_node")] = v.id })
end end
end end
o = s:option(ListValue, option_name("domainStrategy"), translate("Domain Strategy")) o = s:option(ListValue, _n("domainStrategy"), translate("Domain Strategy"))
o:value("AsIs") o:value("AsIs")
o:value("IPIfNonMatch") o:value("IPIfNonMatch")
o:value("IPOnDemand") o:value("IPOnDemand")
@ -255,92 +255,92 @@ o.description = "<br /><ul><li>" .. translate("'AsIs': Only use domain for routi
.. "</li><li>" .. translate("'IPIfNonMatch': When no rule matches current domain, resolves it into IP addresses (A or AAAA records) and try all rules again.") .. "</li><li>" .. translate("'IPIfNonMatch': When no rule matches current domain, resolves it into IP addresses (A or AAAA records) and try all rules again.")
.. "</li><li>" .. translate("'IPOnDemand': As long as there is a IP-based rule, resolves the domain into IP immediately.") .. "</li><li>" .. translate("'IPOnDemand': As long as there is a IP-based rule, resolves the domain into IP immediately.")
.. "</li></ul>" .. "</li></ul>"
o:depends({ [option_name("protocol")] = "_shunt" }) o:depends({ [_n("protocol")] = "_shunt" })
o = s:option(ListValue, option_name("domainMatcher"), translate("Domain matcher")) o = s:option(ListValue, _n("domainMatcher"), translate("Domain matcher"))
o:value("hybrid") o:value("hybrid")
o:value("linear") o:value("linear")
o:depends({ [option_name("protocol")] = "_shunt" }) o:depends({ [_n("protocol")] = "_shunt" })
-- [[ 分流模块 End ]] -- [[ 分流模块 End ]]
o = s:option(Value, option_name("address"), translate("Address (Support Domain Name)")) o = s:option(Value, _n("address"), translate("Address (Support Domain Name)"))
o = s:option(Value, option_name("port"), translate("Port")) o = s:option(Value, _n("port"), translate("Port"))
o.datatype = "port" o.datatype = "port"
local protocols = s.fields[option_name("protocol")].keylist local protocols = s.fields[_n("protocol")].keylist
if #protocols > 0 then if #protocols > 0 then
for index, value in ipairs(protocols) do for index, value in ipairs(protocols) do
if not value:find("_") then if not value:find("_") then
s.fields[option_name("address")]:depends({ [option_name("protocol")] = value }) s.fields[_n("address")]:depends({ [_n("protocol")] = value })
s.fields[option_name("port")]:depends({ [option_name("protocol")] = value }) s.fields[_n("port")]:depends({ [_n("protocol")] = value })
end end
end end
end end
o = s:option(Value, option_name("username"), translate("Username")) o = s:option(Value, _n("username"), translate("Username"))
o:depends({ [option_name("protocol")] = "http" }) o:depends({ [_n("protocol")] = "http" })
o:depends({ [option_name("protocol")] = "socks" }) o:depends({ [_n("protocol")] = "socks" })
o = s:option(Value, option_name("password"), translate("Password")) o = s:option(Value, _n("password"), translate("Password"))
o.password = true o.password = true
o:depends({ [option_name("protocol")] = "http" }) o:depends({ [_n("protocol")] = "http" })
o:depends({ [option_name("protocol")] = "socks" }) o:depends({ [_n("protocol")] = "socks" })
o:depends({ [option_name("protocol")] = "shadowsocks" }) o:depends({ [_n("protocol")] = "shadowsocks" })
o:depends({ [option_name("protocol")] = "trojan" }) o:depends({ [_n("protocol")] = "trojan" })
o = s:option(ListValue, option_name("security"), translate("Encrypt Method")) o = s:option(ListValue, _n("security"), translate("Encrypt Method"))
for a, t in ipairs(security_list) do o:value(t) end for a, t in ipairs(security_list) do o:value(t) end
o:depends({ [option_name("protocol")] = "vmess" }) o:depends({ [_n("protocol")] = "vmess" })
o = s:option(Value, option_name("encryption"), translate("Encrypt Method")) o = s:option(Value, _n("encryption"), translate("Encrypt Method"))
o.default = "none" o.default = "none"
o:value("none") o:value("none")
o:depends({ [option_name("protocol")] = "vless" }) o:depends({ [_n("protocol")] = "vless" })
o = s:option(ListValue, option_name("ss_method"), translate("Encrypt Method")) o = s:option(ListValue, _n("ss_method"), translate("Encrypt Method"))
o.rewrite_option = "method" o.rewrite_option = "method"
for a, t in ipairs(ss_method_list) do o:value(t) end for a, t in ipairs(ss_method_list) do o:value(t) end
o:depends({ [option_name("protocol")] = "shadowsocks" }) o:depends({ [_n("protocol")] = "shadowsocks" })
o = s:option(Flag, option_name("iv_check"), translate("IV Check")) o = s:option(Flag, _n("iv_check"), translate("IV Check"))
o:depends({ [option_name("protocol")] = "shadowsocks", [option_name("ss_method")] = "aes-128-gcm" }) o:depends({ [_n("protocol")] = "shadowsocks", [_n("ss_method")] = "aes-128-gcm" })
o:depends({ [option_name("protocol")] = "shadowsocks", [option_name("ss_method")] = "aes-256-gcm" }) o:depends({ [_n("protocol")] = "shadowsocks", [_n("ss_method")] = "aes-256-gcm" })
o:depends({ [option_name("protocol")] = "shadowsocks", [option_name("ss_method")] = "chacha20-poly1305" }) o:depends({ [_n("protocol")] = "shadowsocks", [_n("ss_method")] = "chacha20-poly1305" })
o:depends({ [option_name("protocol")] = "shadowsocks", [option_name("ss_method")] = "xchacha20-poly1305" }) o:depends({ [_n("protocol")] = "shadowsocks", [_n("ss_method")] = "xchacha20-poly1305" })
o = s:option(Flag, option_name("uot"), translate("UDP over TCP")) o = s:option(Flag, _n("uot"), translate("UDP over TCP"))
o:depends({ [option_name("protocol")] = "shadowsocks" }) o:depends({ [_n("protocol")] = "shadowsocks" })
o = s:option(Value, option_name("uuid"), translate("ID")) o = s:option(Value, _n("uuid"), translate("ID"))
o.password = true o.password = true
o:depends({ [option_name("protocol")] = "vmess" }) o:depends({ [_n("protocol")] = "vmess" })
o:depends({ [option_name("protocol")] = "vless" }) o:depends({ [_n("protocol")] = "vless" })
o = s:option(ListValue, option_name("flow"), translate("flow")) o = s:option(ListValue, _n("flow"), translate("flow"))
o.default = "" o.default = ""
o:value("", translate("Disable")) o:value("", translate("Disable"))
o:value("xtls-rprx-vision") o:value("xtls-rprx-vision")
o:depends({ [option_name("protocol")] = "vless", [option_name("tls")] = true, [option_name("transport")] = "raw" }) o:depends({ [_n("protocol")] = "vless", [_n("tls")] = true, [_n("transport")] = "raw" })
o = s:option(Flag, option_name("tls"), translate("TLS")) o = s:option(Flag, _n("tls"), translate("TLS"))
o.default = 0 o.default = 0
o:depends({ [option_name("protocol")] = "vmess" }) o:depends({ [_n("protocol")] = "vmess" })
o:depends({ [option_name("protocol")] = "vless" }) o:depends({ [_n("protocol")] = "vless" })
o:depends({ [option_name("protocol")] = "http" }) o:depends({ [_n("protocol")] = "http" })
o:depends({ [option_name("protocol")] = "socks" }) o:depends({ [_n("protocol")] = "socks" })
o:depends({ [option_name("protocol")] = "trojan" }) o:depends({ [_n("protocol")] = "trojan" })
o:depends({ [option_name("protocol")] = "shadowsocks" }) o:depends({ [_n("protocol")] = "shadowsocks" })
o = s:option(Flag, option_name("reality"), translate("REALITY")) o = s:option(Flag, _n("reality"), translate("REALITY"))
o.default = 0 o.default = 0
o:depends({ [option_name("tls")] = true, [option_name("transport")] = "raw" }) o:depends({ [_n("tls")] = true, [_n("transport")] = "raw" })
o:depends({ [option_name("tls")] = true, [option_name("transport")] = "h2" }) o:depends({ [_n("tls")] = true, [_n("transport")] = "h2" })
o:depends({ [option_name("tls")] = true, [option_name("transport")] = "grpc" }) o:depends({ [_n("tls")] = true, [_n("transport")] = "grpc" })
o:depends({ [option_name("tls")] = true, [option_name("transport")] = "xhttp" }) o:depends({ [_n("tls")] = true, [_n("transport")] = "xhttp" })
o = s:option(ListValue, option_name("alpn"), translate("alpn")) o = s:option(ListValue, _n("alpn"), translate("alpn"))
o.default = "default" o.default = "default"
o:value("default", translate("Default")) o:value("default", translate("Default"))
o:value("h3") o:value("h3")
@ -349,36 +349,36 @@ o:value("h3,h2")
o:value("http/1.1") o:value("http/1.1")
o:value("h2,http/1.1") o:value("h2,http/1.1")
o:value("h3,h2,http/1.1") o:value("h3,h2,http/1.1")
o:depends({ [option_name("tls")] = true, [option_name("reality")] = false }) o:depends({ [_n("tls")] = true, [_n("reality")] = false })
-- o = s:option(Value, option_name("minversion"), translate("minversion")) -- o = s:option(Value, _n("minversion"), translate("minversion"))
-- o.default = "1.3" -- o.default = "1.3"
-- o:value("1.3") -- o:value("1.3")
-- o:depends({ [option_name("tls")] = true }) -- o:depends({ [_n("tls")] = true })
o = s:option(Value, option_name("tls_serverName"), translate("Domain")) o = s:option(Value, _n("tls_serverName"), translate("Domain"))
o:depends({ [option_name("tls")] = true }) o:depends({ [_n("tls")] = true })
o = s:option(Flag, option_name("tls_allowInsecure"), translate("allowInsecure"), translate("Whether unsafe connections are allowed. When checked, Certificate validation will be skipped.")) o = s:option(Flag, _n("tls_allowInsecure"), translate("allowInsecure"), translate("Whether unsafe connections are allowed. When checked, Certificate validation will be skipped."))
o.default = "0" o.default = "0"
o:depends({ [option_name("tls")] = true, [option_name("reality")] = false }) o:depends({ [_n("tls")] = true, [_n("reality")] = false })
-- [[ REALITY部分 ]] -- -- [[ REALITY部分 ]] --
o = s:option(Value, option_name("reality_publicKey"), translate("Public Key")) o = s:option(Value, _n("reality_publicKey"), translate("Public Key"))
o:depends({ [option_name("tls")] = true, [option_name("reality")] = true }) o:depends({ [_n("tls")] = true, [_n("reality")] = true })
o = s:option(Value, option_name("reality_shortId"), translate("Short Id")) o = s:option(Value, _n("reality_shortId"), translate("Short Id"))
o:depends({ [option_name("tls")] = true, [option_name("reality")] = true }) o:depends({ [_n("tls")] = true, [_n("reality")] = true })
o = s:option(Value, option_name("reality_spiderX"), translate("Spider X")) o = s:option(Value, _n("reality_spiderX"), translate("Spider X"))
o.placeholder = "/" o.placeholder = "/"
o:depends({ [option_name("tls")] = true, [option_name("reality")] = true }) o:depends({ [_n("tls")] = true, [_n("reality")] = true })
o = s:option(Flag, option_name("utls"), translate("uTLS")) o = s:option(Flag, _n("utls"), translate("uTLS"))
o.default = "0" o.default = "0"
o:depends({ [option_name("tls")] = true, [option_name("reality")] = false }) o:depends({ [_n("tls")] = true, [_n("reality")] = false })
o = s:option(ListValue, option_name("fingerprint"), translate("Finger Print")) o = s:option(ListValue, _n("fingerprint"), translate("Finger Print"))
o:value("chrome") o:value("chrome")
o:value("firefox") o:value("firefox")
o:value("edge") o:value("edge")
@ -390,10 +390,10 @@ o:value("android")
o:value("random") o:value("random")
o:value("randomized") o:value("randomized")
o.default = "chrome" o.default = "chrome"
o:depends({ [option_name("tls")] = true, [option_name("utls")] = true }) o:depends({ [_n("tls")] = true, [_n("utls")] = true })
o:depends({ [option_name("tls")] = true, [option_name("reality")] = true }) o:depends({ [_n("tls")] = true, [_n("reality")] = true })
o = s:option(ListValue, option_name("transport"), translate("Transport")) o = s:option(ListValue, _n("transport"), translate("Transport"))
o:value("raw", "RAW (TCP)") o:value("raw", "RAW (TCP)")
o:value("mkcp", "mKCP") o:value("mkcp", "mKCP")
o:value("ws", "WebSocket") o:value("ws", "WebSocket")
@ -403,193 +403,193 @@ o:value("quic", "QUIC")
o:value("grpc", "gRPC") o:value("grpc", "gRPC")
o:value("httpupgrade", "HttpUpgrade") o:value("httpupgrade", "HttpUpgrade")
o:value("xhttp", "XHTTP (SplitHTTP)") o:value("xhttp", "XHTTP (SplitHTTP)")
o:depends({ [option_name("protocol")] = "vmess" }) o:depends({ [_n("protocol")] = "vmess" })
o:depends({ [option_name("protocol")] = "vless" }) o:depends({ [_n("protocol")] = "vless" })
o:depends({ [option_name("protocol")] = "socks" }) o:depends({ [_n("protocol")] = "socks" })
o:depends({ [option_name("protocol")] = "shadowsocks" }) o:depends({ [_n("protocol")] = "shadowsocks" })
o:depends({ [option_name("protocol")] = "trojan" }) o:depends({ [_n("protocol")] = "trojan" })
o = s:option(Value, option_name("wireguard_public_key"), translate("Public Key")) o = s:option(Value, _n("wireguard_public_key"), translate("Public Key"))
o:depends({ [option_name("protocol")] = "wireguard" }) o:depends({ [_n("protocol")] = "wireguard" })
o = s:option(Value, option_name("wireguard_secret_key"), translate("Private Key")) o = s:option(Value, _n("wireguard_secret_key"), translate("Private Key"))
o:depends({ [option_name("protocol")] = "wireguard" }) o:depends({ [_n("protocol")] = "wireguard" })
o = s:option(Value, option_name("wireguard_preSharedKey"), translate("Pre shared key")) o = s:option(Value, _n("wireguard_preSharedKey"), translate("Pre shared key"))
o:depends({ [option_name("protocol")] = "wireguard" }) o:depends({ [_n("protocol")] = "wireguard" })
o = s:option(DynamicList, option_name("wireguard_local_address"), translate("Local Address")) o = s:option(DynamicList, _n("wireguard_local_address"), translate("Local Address"))
o:depends({ [option_name("protocol")] = "wireguard" }) o:depends({ [_n("protocol")] = "wireguard" })
o = s:option(Value, option_name("wireguard_mtu"), translate("MTU")) o = s:option(Value, _n("wireguard_mtu"), translate("MTU"))
o.default = "1420" o.default = "1420"
o:depends({ [option_name("protocol")] = "wireguard" }) o:depends({ [_n("protocol")] = "wireguard" })
if api.compare_versions(xray_version, ">=", "1.8.0") then if api.compare_versions(xray_version, ">=", "1.8.0") then
o = s:option(Value, option_name("wireguard_reserved"), translate("Reserved"), translate("Decimal numbers separated by \",\" or Base64-encoded strings.")) o = s:option(Value, _n("wireguard_reserved"), translate("Reserved"), translate("Decimal numbers separated by \",\" or Base64-encoded strings."))
o:depends({ [option_name("protocol")] = "wireguard" }) o:depends({ [_n("protocol")] = "wireguard" })
end end
o = s:option(Value, option_name("wireguard_keepAlive"), translate("Keep Alive")) o = s:option(Value, _n("wireguard_keepAlive"), translate("Keep Alive"))
o.default = "0" o.default = "0"
o:depends({ [option_name("protocol")] = "wireguard" }) o:depends({ [_n("protocol")] = "wireguard" })
-- [[ RAW部分 ]]-- -- [[ RAW部分 ]]--
-- TCP伪装 -- TCP伪装
o = s:option(ListValue, option_name("tcp_guise"), translate("Camouflage Type")) o = s:option(ListValue, _n("tcp_guise"), translate("Camouflage Type"))
o:value("none", "none") o:value("none", "none")
o:value("http", "http") o:value("http", "http")
o:depends({ [option_name("transport")] = "raw" }) o:depends({ [_n("transport")] = "raw" })
-- HTTP域名 -- HTTP域名
o = s:option(DynamicList, option_name("tcp_guise_http_host"), translate("HTTP Host")) o = s:option(DynamicList, _n("tcp_guise_http_host"), translate("HTTP Host"))
o:depends({ [option_name("tcp_guise")] = "http" }) o:depends({ [_n("tcp_guise")] = "http" })
-- HTTP路径 -- HTTP路径
o = s:option(DynamicList, option_name("tcp_guise_http_path"), translate("HTTP Path")) o = s:option(DynamicList, _n("tcp_guise_http_path"), translate("HTTP Path"))
o.placeholder = "/" o.placeholder = "/"
o:depends({ [option_name("tcp_guise")] = "http" }) o:depends({ [_n("tcp_guise")] = "http" })
-- [[ mKCP部分 ]]-- -- [[ mKCP部分 ]]--
o = s:option(ListValue, option_name("mkcp_guise"), translate("Camouflage Type"), translate('<br />none: default, no masquerade, data sent is packets with no characteristics.<br />srtp: disguised as an SRTP packet, it will be recognized as video call data (such as FaceTime).<br />utp: packets disguised as uTP will be recognized as bittorrent downloaded data.<br />wechat-video: packets disguised as WeChat video calls.<br />dtls: disguised as DTLS 1.2 packet.<br />wireguard: disguised as a WireGuard packet. (not really WireGuard protocol)')) o = s:option(ListValue, _n("mkcp_guise"), translate("Camouflage Type"), translate('<br />none: default, no masquerade, data sent is packets with no characteristics.<br />srtp: disguised as an SRTP packet, it will be recognized as video call data (such as FaceTime).<br />utp: packets disguised as uTP will be recognized as bittorrent downloaded data.<br />wechat-video: packets disguised as WeChat video calls.<br />dtls: disguised as DTLS 1.2 packet.<br />wireguard: disguised as a WireGuard packet. (not really WireGuard protocol)'))
for a, t in ipairs(header_type_list) do o:value(t) end for a, t in ipairs(header_type_list) do o:value(t) end
o:depends({ [option_name("transport")] = "mkcp" }) o:depends({ [_n("transport")] = "mkcp" })
o = s:option(Value, option_name("mkcp_mtu"), translate("KCP MTU")) o = s:option(Value, _n("mkcp_mtu"), translate("KCP MTU"))
o.default = "1350" o.default = "1350"
o:depends({ [option_name("transport")] = "mkcp" }) o:depends({ [_n("transport")] = "mkcp" })
o = s:option(Value, option_name("mkcp_tti"), translate("KCP TTI")) o = s:option(Value, _n("mkcp_tti"), translate("KCP TTI"))
o.default = "20" o.default = "20"
o:depends({ [option_name("transport")] = "mkcp" }) o:depends({ [_n("transport")] = "mkcp" })
o = s:option(Value, option_name("mkcp_uplinkCapacity"), translate("KCP uplinkCapacity")) o = s:option(Value, _n("mkcp_uplinkCapacity"), translate("KCP uplinkCapacity"))
o.default = "5" o.default = "5"
o:depends({ [option_name("transport")] = "mkcp" }) o:depends({ [_n("transport")] = "mkcp" })
o = s:option(Value, option_name("mkcp_downlinkCapacity"), translate("KCP downlinkCapacity")) o = s:option(Value, _n("mkcp_downlinkCapacity"), translate("KCP downlinkCapacity"))
o.default = "20" o.default = "20"
o:depends({ [option_name("transport")] = "mkcp" }) o:depends({ [_n("transport")] = "mkcp" })
o = s:option(Flag, option_name("mkcp_congestion"), translate("KCP Congestion")) o = s:option(Flag, _n("mkcp_congestion"), translate("KCP Congestion"))
o:depends({ [option_name("transport")] = "mkcp" }) o:depends({ [_n("transport")] = "mkcp" })
o = s:option(Value, option_name("mkcp_readBufferSize"), translate("KCP readBufferSize")) o = s:option(Value, _n("mkcp_readBufferSize"), translate("KCP readBufferSize"))
o.default = "1" o.default = "1"
o:depends({ [option_name("transport")] = "mkcp" }) o:depends({ [_n("transport")] = "mkcp" })
o = s:option(Value, option_name("mkcp_writeBufferSize"), translate("KCP writeBufferSize")) o = s:option(Value, _n("mkcp_writeBufferSize"), translate("KCP writeBufferSize"))
o.default = "1" o.default = "1"
o:depends({ [option_name("transport")] = "mkcp" }) o:depends({ [_n("transport")] = "mkcp" })
o = s:option(Value, option_name("mkcp_seed"), translate("KCP Seed")) o = s:option(Value, _n("mkcp_seed"), translate("KCP Seed"))
o:depends({ [option_name("transport")] = "mkcp" }) o:depends({ [_n("transport")] = "mkcp" })
-- [[ WebSocket部分 ]]-- -- [[ WebSocket部分 ]]--
o = s:option(Value, option_name("ws_host"), translate("WebSocket Host")) o = s:option(Value, _n("ws_host"), translate("WebSocket Host"))
o:depends({ [option_name("transport")] = "ws" }) o:depends({ [_n("transport")] = "ws" })
o = s:option(Value, option_name("ws_path"), translate("WebSocket Path")) o = s:option(Value, _n("ws_path"), translate("WebSocket Path"))
o.placeholder = "/" o.placeholder = "/"
o:depends({ [option_name("transport")] = "ws" }) o:depends({ [_n("transport")] = "ws" })
o = s:option(Value, option_name("ws_heartbeatPeriod"), translate("HeartbeatPeriod(second)")) o = s:option(Value, _n("ws_heartbeatPeriod"), translate("HeartbeatPeriod(second)"))
o.datatype = "integer" o.datatype = "integer"
o:depends({ [option_name("transport")] = "ws" }) o:depends({ [_n("transport")] = "ws" })
-- [[ HTTP/2部分 ]]-- -- [[ HTTP/2部分 ]]--
o = s:option(Value, option_name("h2_host"), translate("HTTP/2 Host")) o = s:option(Value, _n("h2_host"), translate("HTTP/2 Host"))
o:depends({ [option_name("transport")] = "h2" }) o:depends({ [_n("transport")] = "h2" })
o = s:option(Value, option_name("h2_path"), translate("HTTP/2 Path")) o = s:option(Value, _n("h2_path"), translate("HTTP/2 Path"))
o.placeholder = "/" o.placeholder = "/"
o:depends({ [option_name("transport")] = "h2" }) o:depends({ [_n("transport")] = "h2" })
o = s:option(Flag, option_name("h2_health_check"), translate("Health check")) o = s:option(Flag, _n("h2_health_check"), translate("Health check"))
o:depends({ [option_name("transport")] = "h2" }) o:depends({ [_n("transport")] = "h2" })
o = s:option(Value, option_name("h2_read_idle_timeout"), translate("Idle timeout")) o = s:option(Value, _n("h2_read_idle_timeout"), translate("Idle timeout"))
o.default = "10" o.default = "10"
o:depends({ [option_name("h2_health_check")] = true }) o:depends({ [_n("h2_health_check")] = true })
o = s:option(Value, option_name("h2_health_check_timeout"), translate("Health check timeout")) o = s:option(Value, _n("h2_health_check_timeout"), translate("Health check timeout"))
o.default = "15" o.default = "15"
o:depends({ [option_name("h2_health_check")] = true }) o:depends({ [_n("h2_health_check")] = true })
-- [[ DomainSocket部分 ]]-- -- [[ DomainSocket部分 ]]--
o = s:option(Value, option_name("ds_path"), "Path", translate("A legal file path. This file must not exist before running.")) o = s:option(Value, _n("ds_path"), "Path", translate("A legal file path. This file must not exist before running."))
o:depends({ [option_name("transport")] = "ds" }) o:depends({ [_n("transport")] = "ds" })
-- [[ QUIC部分 ]]-- -- [[ QUIC部分 ]]--
o = s:option(ListValue, option_name("quic_security"), translate("Encrypt Method")) o = s:option(ListValue, _n("quic_security"), translate("Encrypt Method"))
o:value("none") o:value("none")
o:value("aes-128-gcm") o:value("aes-128-gcm")
o:value("chacha20-poly1305") o:value("chacha20-poly1305")
o:depends({ [option_name("transport")] = "quic" }) o:depends({ [_n("transport")] = "quic" })
o = s:option(Value, option_name("quic_key"), translate("Encrypt Method") .. translate("Key")) o = s:option(Value, _n("quic_key"), translate("Encrypt Method") .. translate("Key"))
o:depends({ [option_name("transport")] = "quic" }) o:depends({ [_n("transport")] = "quic" })
o = s:option(ListValue, option_name("quic_guise"), translate("Camouflage Type")) o = s:option(ListValue, _n("quic_guise"), translate("Camouflage Type"))
for a, t in ipairs(header_type_list) do o:value(t) end for a, t in ipairs(header_type_list) do o:value(t) end
o:depends({ [option_name("transport")] = "quic" }) o:depends({ [_n("transport")] = "quic" })
-- [[ gRPC部分 ]]-- -- [[ gRPC部分 ]]--
o = s:option(Value, option_name("grpc_serviceName"), "ServiceName") o = s:option(Value, _n("grpc_serviceName"), "ServiceName")
o:depends({ [option_name("transport")] = "grpc" }) o:depends({ [_n("transport")] = "grpc" })
o = s:option(ListValue, option_name("grpc_mode"), "gRPC " .. translate("Transfer mode")) o = s:option(ListValue, _n("grpc_mode"), "gRPC " .. translate("Transfer mode"))
o:value("gun") o:value("gun")
o:value("multi") o:value("multi")
o:depends({ [option_name("transport")] = "grpc" }) o:depends({ [_n("transport")] = "grpc" })
o = s:option(Flag, option_name("grpc_health_check"), translate("Health check")) o = s:option(Flag, _n("grpc_health_check"), translate("Health check"))
o:depends({ [option_name("transport")] = "grpc" }) o:depends({ [_n("transport")] = "grpc" })
o = s:option(Value, option_name("grpc_idle_timeout"), translate("Idle timeout")) o = s:option(Value, _n("grpc_idle_timeout"), translate("Idle timeout"))
o.default = "10" o.default = "10"
o:depends({ [option_name("grpc_health_check")] = true }) o:depends({ [_n("grpc_health_check")] = true })
o = s:option(Value, option_name("grpc_health_check_timeout"), translate("Health check timeout")) o = s:option(Value, _n("grpc_health_check_timeout"), translate("Health check timeout"))
o.default = "20" o.default = "20"
o:depends({ [option_name("grpc_health_check")] = true }) o:depends({ [_n("grpc_health_check")] = true })
o = s:option(Flag, option_name("grpc_permit_without_stream"), translate("Permit without stream")) o = s:option(Flag, _n("grpc_permit_without_stream"), translate("Permit without stream"))
o.default = "0" o.default = "0"
o:depends({ [option_name("grpc_health_check")] = true }) o:depends({ [_n("grpc_health_check")] = true })
o = s:option(Value, option_name("grpc_initial_windows_size"), translate("Initial Windows Size")) o = s:option(Value, _n("grpc_initial_windows_size"), translate("Initial Windows Size"))
o.default = "0" o.default = "0"
o:depends({ [option_name("transport")] = "grpc" }) o:depends({ [_n("transport")] = "grpc" })
-- [[ HttpUpgrade部分 ]]-- -- [[ HttpUpgrade部分 ]]--
o = s:option(Value, option_name("httpupgrade_host"), translate("HttpUpgrade Host")) o = s:option(Value, _n("httpupgrade_host"), translate("HttpUpgrade Host"))
o:depends({ [option_name("transport")] = "httpupgrade" }) o:depends({ [_n("transport")] = "httpupgrade" })
o = s:option(Value, option_name("httpupgrade_path"), translate("HttpUpgrade Path")) o = s:option(Value, _n("httpupgrade_path"), translate("HttpUpgrade Path"))
o.placeholder = "/" o.placeholder = "/"
o:depends({ [option_name("transport")] = "httpupgrade" }) o:depends({ [_n("transport")] = "httpupgrade" })
-- [[ XHTTP部分 ]]-- -- [[ XHTTP部分 ]]--
o = s:option(ListValue, option_name("xhttp_mode"), "XHTTP " .. translate("Mode")) o = s:option(ListValue, _n("xhttp_mode"), "XHTTP " .. translate("Mode"))
o:depends({ [option_name("transport")] = "xhttp" }) o:depends({ [_n("transport")] = "xhttp" })
o.default = "auto" o.default = "auto"
o:value("auto") o:value("auto")
o:value("packet-up") o:value("packet-up")
o:value("stream-up") o:value("stream-up")
o:value("stream-one") o:value("stream-one")
o = s:option(Value, option_name("xhttp_host"), translate("XHTTP Host")) o = s:option(Value, _n("xhttp_host"), translate("XHTTP Host"))
o:depends({ [option_name("transport")] = "xhttp" }) o:depends({ [_n("transport")] = "xhttp" })
o = s:option(Value, option_name("xhttp_path"), translate("XHTTP Path")) o = s:option(Value, _n("xhttp_path"), translate("XHTTP Path"))
o.placeholder = "/" o.placeholder = "/"
o:depends({ [option_name("transport")] = "xhttp" }) o:depends({ [_n("transport")] = "xhttp" })
o = s:option(TextValue, option_name("xhttp_extra"), translate("XHTTP Extra"), translate("An <a target='_blank' href='https://xtls.github.io/config/transports/splithttp.html#extra'>XHTTP extra object</a> in raw json")) o = s:option(TextValue, _n("xhttp_extra"), translate("XHTTP Extra"), translate("An <a target='_blank' href='https://xtls.github.io/config/transports/splithttp.html#extra'>XHTTP extra object</a> in raw json"))
o:depends({ [option_name("transport")] = "xhttp" }) o:depends({ [_n("transport")] = "xhttp" })
o.rows = 15 o.rows = 15
o.wrap = "off" o.wrap = "off"
o.custom_write = function(self, section, value) o.custom_write = function(self, section, value)
@ -618,63 +618,63 @@ o.validate = function(self, value)
end end
-- [[ Mux.Cool ]]-- -- [[ Mux.Cool ]]--
o = s:option(Flag, option_name("mux"), "Mux", translate("Enable Mux.Cool")) o = s:option(Flag, _n("mux"), "Mux", translate("Enable Mux.Cool"))
o:depends({ [option_name("protocol")] = "vmess" }) o:depends({ [_n("protocol")] = "vmess" })
o:depends({ [option_name("protocol")] = "vless", [option_name("flow")] = "" }) o:depends({ [_n("protocol")] = "vless", [_n("flow")] = "" })
o:depends({ [option_name("protocol")] = "http" }) o:depends({ [_n("protocol")] = "http" })
o:depends({ [option_name("protocol")] = "socks" }) o:depends({ [_n("protocol")] = "socks" })
o:depends({ [option_name("protocol")] = "shadowsocks" }) o:depends({ [_n("protocol")] = "shadowsocks" })
o:depends({ [option_name("protocol")] = "trojan" }) o:depends({ [_n("protocol")] = "trojan" })
o = s:option(Value, option_name("mux_concurrency"), translate("Mux concurrency")) o = s:option(Value, _n("mux_concurrency"), translate("Mux concurrency"))
o.default = 8 o.default = 8
o:depends({ [option_name("mux")] = true }) o:depends({ [_n("mux")] = true })
-- [[ XUDP Mux ]]-- -- [[ XUDP Mux ]]--
o = s:option(Flag, option_name("xmux"), "XUDP Mux") o = s:option(Flag, _n("xmux"), "XUDP Mux")
o.default = 1 o.default = 1
o:depends({ [option_name("protocol")] = "vless", [option_name("flow")] = "xtls-rprx-vision" }) o:depends({ [_n("protocol")] = "vless", [_n("flow")] = "xtls-rprx-vision" })
o:depends({ [option_name("protocol")] = "vless", [option_name("flow")] = "xtls-rprx-vision-udp443" }) o:depends({ [_n("protocol")] = "vless", [_n("flow")] = "xtls-rprx-vision-udp443" })
o = s:option(Value, option_name("xudp_concurrency"), translate("XUDP Mux concurrency")) o = s:option(Value, _n("xudp_concurrency"), translate("XUDP Mux concurrency"))
o.default = 8 o.default = 8
o:depends({ [option_name("xmux")] = true }) o:depends({ [_n("xmux")] = true })
--[[tcpMptcp]] --[[tcpMptcp]]
o = s:option(Flag, option_name("tcpMptcp"), "tcpMptcp", translate("Enable Multipath TCP, need to be enabled in both server and client configuration.")) o = s:option(Flag, _n("tcpMptcp"), "tcpMptcp", translate("Enable Multipath TCP, need to be enabled in both server and client configuration."))
o.default = 0 o.default = 0
o = s:option(Flag, option_name("tcpNoDelay"), "tcpNoDelay") o = s:option(Flag, _n("tcpNoDelay"), "tcpNoDelay")
o.default = 0 o.default = 0
o = s:option(ListValue, option_name("chain_proxy"), translate("Chain Proxy")) o = s:option(ListValue, _n("chain_proxy"), translate("Chain Proxy"))
o:value("", translate("Close(Not use)")) o:value("", translate("Close(Not use)"))
o:value("1", translate("Preproxy Node")) o:value("1", translate("Preproxy Node"))
o:value("2", translate("Landing Node")) o:value("2", translate("Landing Node"))
for i, v in ipairs(s.fields[option_name("protocol")].keylist) do for i, v in ipairs(s.fields[_n("protocol")].keylist) do
if not v:find("_") then if not v:find("_") then
o:depends({ [option_name("protocol")] = v }) o:depends({ [_n("protocol")] = v })
end end
end end
o = s:option(ListValue, option_name("preproxy_node"), translate("Preproxy Node"), translate("Only support a layer of proxy.")) o = s:option(ListValue, _n("preproxy_node"), translate("Preproxy Node"), translate("Only support a layer of proxy."))
o:depends({ [option_name("chain_proxy")] = "1" }) o:depends({ [_n("chain_proxy")] = "1" })
o = s:option(ListValue, option_name("to_node"), translate("Landing Node"), translate("Only support a layer of proxy.")) o = s:option(ListValue, _n("to_node"), translate("Landing Node"), translate("Only support a layer of proxy."))
o:depends({ [option_name("chain_proxy")] = "2" }) o:depends({ [_n("chain_proxy")] = "2" })
for k, v in pairs(nodes_table) do for k, v in pairs(nodes_table) do
if v.type == "Xray" and v.id ~= arg[1] then if v.type == "Xray" and v.id ~= arg[1] then
s.fields[option_name("preproxy_node")]:value(v.id, v.remark) s.fields[_n("preproxy_node")]:value(v.id, v.remark)
s.fields[option_name("to_node")]:value(v.id, v.remark) s.fields[_n("to_node")]:value(v.id, v.remark)
end end
end end
for i, v in ipairs(s.fields[option_name("protocol")].keylist) do for i, v in ipairs(s.fields[_n("protocol")].keylist) do
if not v:find("_") then if not v:find("_") then
s.fields[option_name("tcpMptcp")]:depends({ [option_name("protocol")] = v }) s.fields[_n("tcpMptcp")]:depends({ [_n("protocol")] = v })
s.fields[option_name("tcpNoDelay")]:depends({ [option_name("protocol")] = v }) s.fields[_n("tcpNoDelay")]:depends({ [_n("protocol")] = v })
s.fields[option_name("chain_proxy")]:depends({ [option_name("protocol")] = v }) s.fields[_n("chain_proxy")]:depends({ [_n("protocol")] = v })
end end
end end

View File

@ -17,7 +17,7 @@ local type_name = "sing-box"
local option_prefix = "singbox_" local option_prefix = "singbox_"
local function option_name(name) local function _n(name)
return option_prefix .. name return option_prefix .. name
end end
@ -35,7 +35,7 @@ local security_list = { "none", "auto", "aes-128-gcm", "chacha20-poly1305", "zer
s.fields["type"]:value(type_name, translate("Sing-Box")) s.fields["type"]:value(type_name, translate("Sing-Box"))
o = s:option(ListValue, option_name("protocol"), translate("Protocol")) o = s:option(ListValue, _n("protocol"), translate("Protocol"))
o:value("socks", "Socks") o:value("socks", "Socks")
o:value("http", "HTTP") o:value("http", "HTTP")
o:value("shadowsocks", "Shadowsocks") o:value("shadowsocks", "Shadowsocks")
@ -60,9 +60,9 @@ end
o:value("_shunt", translate("Shunt")) o:value("_shunt", translate("Shunt"))
o:value("_iface", translate("Custom Interface")) o:value("_iface", translate("Custom Interface"))
o = s:option(Value, option_name("iface"), translate("Interface")) o = s:option(Value, _n("iface"), translate("Interface"))
o.default = "eth1" o.default = "eth1"
o:depends({ [option_name("protocol")] = "_iface" }) o:depends({ [_n("protocol")] = "_iface" })
local nodes_table = {} local nodes_table = {}
local iface_table = {} local iface_table = {}
@ -94,11 +94,11 @@ end)
-- [[ 分流模块 ]] -- [[ 分流模块 ]]
if #nodes_table > 0 then if #nodes_table > 0 then
o = s:option(Flag, option_name("preproxy_enabled"), translate("Preproxy")) o = s:option(Flag, _n("preproxy_enabled"), translate("Preproxy"))
o:depends({ [option_name("protocol")] = "_shunt" }) o:depends({ [_n("protocol")] = "_shunt" })
o = s:option(ListValue, option_name("main_node"), string.format('<a style="color:red">%s</a>', translate("Preproxy Node")), translate("Set the node to be used as a pre-proxy. Each rule (including <code>Default</code>) has a separate switch that controls whether this rule uses the pre-proxy or not.")) o = s:option(ListValue, _n("main_node"), string.format('<a style="color:red">%s</a>', translate("Preproxy Node")), translate("Set the node to be used as a pre-proxy. Each rule (including <code>Default</code>) has a separate switch that controls whether this rule uses the pre-proxy or not."))
o:depends({ [option_name("protocol")] = "_shunt", [option_name("preproxy_enabled")] = true }) o:depends({ [_n("protocol")] = "_shunt", [_n("preproxy_enabled")] = true })
for k, v in pairs(socks_list) do for k, v in pairs(socks_list) do
o:value(v.id, v.remark) o:value(v.id, v.remark)
end end
@ -108,16 +108,18 @@ if #nodes_table > 0 then
for k, v in pairs(nodes_table) do for k, v in pairs(nodes_table) do
o:value(v.id, v.remark) o:value(v.id, v.remark)
end end
o.default = "nil" if #o.keylist > 0 then
o.default = o.keylist[1]
end
end end
uci:foreach(appname, "shunt_rules", function(e) uci:foreach(appname, "shunt_rules", function(e)
if e[".name"] and e.remarks then if e[".name"] and e.remarks then
o = s:option(ListValue, option_name(e[".name"]), string.format('* <a href="%s" target="_blank">%s</a>', api.url("shunt_rules", e[".name"]), e.remarks)) o = s:option(ListValue, _n(e[".name"]), string.format('* <a href="%s" target="_blank">%s</a>', api.url("shunt_rules", e[".name"]), e.remarks))
o:value("nil", translate("Close")) o:value("", translate("Close"))
o:value("_default", translate("Default")) o:value("_default", translate("Default"))
o:value("_direct", translate("Direct Connection")) o:value("_direct", translate("Direct Connection"))
o:value("_blackhole", translate("Blackhole")) o:value("_blackhole", translate("Blackhole"))
o:depends({ [option_name("protocol")] = "_shunt" }) o:depends({ [_n("protocol")] = "_shunt" })
if #nodes_table > 0 then if #nodes_table > 0 then
for k, v in pairs(socks_list) do for k, v in pairs(socks_list) do
@ -126,28 +128,27 @@ uci:foreach(appname, "shunt_rules", function(e)
for k, v in pairs(iface_table) do for k, v in pairs(iface_table) do
o:value(v.id, v.remark) o:value(v.id, v.remark)
end end
local pt = s:option(ListValue, option_name(e[".name"] .. "_proxy_tag"), string.format('* <a style="color:red">%s</a>', e.remarks .. " " .. translate("Preproxy"))) local pt = s:option(ListValue, _n(e[".name"] .. "_proxy_tag"), string.format('* <a style="color:red">%s</a>', e.remarks .. " " .. translate("Preproxy")))
pt:value("nil", translate("Close")) pt:value("", translate("Close"))
pt:value("main", translate("Preproxy Node")) pt:value("main", translate("Preproxy Node"))
pt.default = "nil"
for k, v in pairs(nodes_table) do for k, v in pairs(nodes_table) do
o:value(v.id, v.remark) o:value(v.id, v.remark)
pt:depends({ [option_name("protocol")] = "_shunt", [option_name("preproxy_enabled")] = true, [option_name(e[".name"])] = v.id }) pt:depends({ [_n("protocol")] = "_shunt", [_n("preproxy_enabled")] = true, [_n(e[".name"])] = v.id })
end end
end end
end end
end) end)
o = s:option(DummyValue, option_name("shunt_tips"), " ") o = s:option(DummyValue, _n("shunt_tips"), " ")
o.not_rewrite = true o.not_rewrite = true
o.rawhtml = true o.rawhtml = true
o.cfgvalue = function(t, n) o.cfgvalue = function(t, n)
return string.format('<a style="color: red" href="../rule">%s</a>', translate("No shunt rules? Click me to go to add.")) return string.format('<a style="color: red" href="../rule">%s</a>', translate("No shunt rules? Click me to go to add."))
end end
o:depends({ [option_name("protocol")] = "_shunt" }) o:depends({ [_n("protocol")] = "_shunt" })
local o = s:option(ListValue, option_name("default_node"), string.format('* <a style="color:red">%s</a>', translate("Default"))) local o = s:option(ListValue, _n("default_node"), string.format('* <a style="color:red">%s</a>', translate("Default")))
o:depends({ [option_name("protocol")] = "_shunt" }) o:depends({ [_n("protocol")] = "_shunt" })
o:value("_direct", translate("Direct Connection")) o:value("_direct", translate("Direct Connection"))
o:value("_blackhole", translate("Blackhole")) o:value("_blackhole", translate("Blackhole"))
@ -158,61 +159,60 @@ if #nodes_table > 0 then
for k, v in pairs(iface_table) do for k, v in pairs(iface_table) do
o:value(v.id, v.remark) o:value(v.id, v.remark)
end end
local dpt = s:option(ListValue, option_name("default_proxy_tag"), string.format('* <a style="color:red">%s</a>', translate("Default Preproxy")), translate("When using, localhost will connect this node first and then use this node to connect the default node.")) local dpt = s:option(ListValue, _n("default_proxy_tag"), string.format('* <a style="color:red">%s</a>', translate("Default Preproxy")), translate("When using, localhost will connect this node first and then use this node to connect the default node."))
dpt:value("nil", translate("Close")) dpt:value("", translate("Close"))
dpt:value("main", translate("Preproxy Node")) dpt:value("main", translate("Preproxy Node"))
dpt.default = "nil"
for k, v in pairs(nodes_table) do for k, v in pairs(nodes_table) do
o:value(v.id, v.remark) o:value(v.id, v.remark)
dpt:depends({ [option_name("protocol")] = "_shunt", [option_name("preproxy_enabled")] = true, [option_name("default_node")] = v.id }) dpt:depends({ [_n("protocol")] = "_shunt", [_n("preproxy_enabled")] = true, [_n("default_node")] = v.id })
end end
end end
-- [[ 分流模块 End ]] -- [[ 分流模块 End ]]
o = s:option(Value, option_name("address"), translate("Address (Support Domain Name)")) o = s:option(Value, _n("address"), translate("Address (Support Domain Name)"))
o = s:option(Value, option_name("port"), translate("Port")) o = s:option(Value, _n("port"), translate("Port"))
o.datatype = "port" o.datatype = "port"
local protocols = s.fields[option_name("protocol")].keylist local protocols = s.fields[_n("protocol")].keylist
if #protocols > 0 then if #protocols > 0 then
for index, value in ipairs(protocols) do for index, value in ipairs(protocols) do
if not value:find("_") then if not value:find("_") then
s.fields[option_name("address")]:depends({ [option_name("protocol")] = value }) s.fields[_n("address")]:depends({ [_n("protocol")] = value })
s.fields[option_name("port")]:depends({ [option_name("protocol")] = value }) s.fields[_n("port")]:depends({ [_n("protocol")] = value })
end end
end end
end end
o = s:option(Value, option_name("username"), translate("Username")) o = s:option(Value, _n("username"), translate("Username"))
o:depends({ [option_name("protocol")] = "http" }) o:depends({ [_n("protocol")] = "http" })
o:depends({ [option_name("protocol")] = "socks" }) o:depends({ [_n("protocol")] = "socks" })
o = s:option(Value, option_name("password"), translate("Password")) o = s:option(Value, _n("password"), translate("Password"))
o.password = true o.password = true
o:depends({ [option_name("protocol")] = "http" }) o:depends({ [_n("protocol")] = "http" })
o:depends({ [option_name("protocol")] = "socks" }) o:depends({ [_n("protocol")] = "socks" })
o:depends({ [option_name("protocol")] = "shadowsocks" }) o:depends({ [_n("protocol")] = "shadowsocks" })
o:depends({ [option_name("protocol")] = "shadowsocksr" }) o:depends({ [_n("protocol")] = "shadowsocksr" })
o:depends({ [option_name("protocol")] = "trojan" }) o:depends({ [_n("protocol")] = "trojan" })
o:depends({ [option_name("protocol")] = "tuic" }) o:depends({ [_n("protocol")] = "tuic" })
o = s:option(ListValue, option_name("security"), translate("Encrypt Method")) o = s:option(ListValue, _n("security"), translate("Encrypt Method"))
for a, t in ipairs(security_list) do o:value(t) end for a, t in ipairs(security_list) do o:value(t) end
o:depends({ [option_name("protocol")] = "vmess" }) o:depends({ [_n("protocol")] = "vmess" })
o = s:option(ListValue, option_name("ss_method"), translate("Encrypt Method")) o = s:option(ListValue, _n("ss_method"), translate("Encrypt Method"))
o.rewrite_option = "method" o.rewrite_option = "method"
for a, t in ipairs(ss_method_new_list) do o:value(t) end for a, t in ipairs(ss_method_new_list) do o:value(t) end
for a, t in ipairs(ss_method_old_list) do o:value(t) end for a, t in ipairs(ss_method_old_list) do o:value(t) end
o:depends({ [option_name("protocol")] = "shadowsocks" }) o:depends({ [_n("protocol")] = "shadowsocks" })
if singbox_tags:find("with_shadowsocksr") then if singbox_tags:find("with_shadowsocksr") then
o = s:option(ListValue, option_name("ssr_method"), translate("Encrypt Method")) o = s:option(ListValue, _n("ssr_method"), translate("Encrypt Method"))
o.rewrite_option = "method" o.rewrite_option = "method"
for a, t in ipairs(ss_method_old_list) do o:value(t) end for a, t in ipairs(ss_method_old_list) do o:value(t) end
o:depends({ [option_name("protocol")] = "shadowsocksr" }) o:depends({ [_n("protocol")] = "shadowsocksr" })
local ssr_protocol_list = { local ssr_protocol_list = {
"origin", "verify_simple", "verify_deflate", "verify_sha1", "auth_simple", "origin", "verify_simple", "verify_deflate", "verify_sha1", "auth_simple",
@ -221,120 +221,120 @@ if singbox_tags:find("with_shadowsocksr") then
"auth_chain_d", "auth_chain_e", "auth_chain_f" "auth_chain_d", "auth_chain_e", "auth_chain_f"
} }
o = s:option(ListValue, option_name("ssr_protocol"), translate("Protocol")) o = s:option(ListValue, _n("ssr_protocol"), translate("Protocol"))
for a, t in ipairs(ssr_protocol_list) do o:value(t) end for a, t in ipairs(ssr_protocol_list) do o:value(t) end
o:depends({ [option_name("protocol")] = "shadowsocksr" }) o:depends({ [_n("protocol")] = "shadowsocksr" })
o = s:option(Value, option_name("ssr_protocol_param"), translate("Protocol_param")) o = s:option(Value, _n("ssr_protocol_param"), translate("Protocol_param"))
o:depends({ [option_name("protocol")] = "shadowsocksr" }) o:depends({ [_n("protocol")] = "shadowsocksr" })
local ssr_obfs_list = { local ssr_obfs_list = {
"plain", "http_simple", "http_post", "random_head", "tls_simple", "plain", "http_simple", "http_post", "random_head", "tls_simple",
"tls1.0_session_auth", "tls1.2_ticket_auth" "tls1.0_session_auth", "tls1.2_ticket_auth"
} }
o = s:option(ListValue, option_name("ssr_obfs"), translate("Obfs")) o = s:option(ListValue, _n("ssr_obfs"), translate("Obfs"))
for a, t in ipairs(ssr_obfs_list) do o:value(t) end for a, t in ipairs(ssr_obfs_list) do o:value(t) end
o:depends({ [option_name("protocol")] = "shadowsocksr" }) o:depends({ [_n("protocol")] = "shadowsocksr" })
o = s:option(Value, option_name("ssr_obfs_param"), translate("Obfs_param")) o = s:option(Value, _n("ssr_obfs_param"), translate("Obfs_param"))
o:depends({ [option_name("protocol")] = "shadowsocksr" }) o:depends({ [_n("protocol")] = "shadowsocksr" })
end end
o = s:option(Flag, option_name("uot"), translate("UDP over TCP")) o = s:option(Flag, _n("uot"), translate("UDP over TCP"))
o:depends({ [option_name("protocol")] = "socks" }) o:depends({ [_n("protocol")] = "socks" })
o:depends({ [option_name("protocol")] = "shadowsocks" }) o:depends({ [_n("protocol")] = "shadowsocks" })
o = s:option(Value, option_name("uuid"), translate("ID")) o = s:option(Value, _n("uuid"), translate("ID"))
o.password = true o.password = true
o:depends({ [option_name("protocol")] = "vmess" }) o:depends({ [_n("protocol")] = "vmess" })
o:depends({ [option_name("protocol")] = "vless" }) o:depends({ [_n("protocol")] = "vless" })
o:depends({ [option_name("protocol")] = "tuic" }) o:depends({ [_n("protocol")] = "tuic" })
o = s:option(Value, option_name("alter_id"), "Alter ID") o = s:option(Value, _n("alter_id"), "Alter ID")
o.datatype = "uinteger" o.datatype = "uinteger"
o.default = "0" o.default = "0"
o:depends({ [option_name("protocol")] = "vmess" }) o:depends({ [_n("protocol")] = "vmess" })
o = s:option(Flag, option_name("global_padding"), "global_padding", translate("Protocol parameter. Will waste traffic randomly if enabled.")) o = s:option(Flag, _n("global_padding"), "global_padding", translate("Protocol parameter. Will waste traffic randomly if enabled."))
o.default = "0" o.default = "0"
o:depends({ [option_name("protocol")] = "vmess" }) o:depends({ [_n("protocol")] = "vmess" })
o = s:option(Flag, option_name("authenticated_length"), "authenticated_length", translate("Protocol parameter. Enable length block encryption.")) o = s:option(Flag, _n("authenticated_length"), "authenticated_length", translate("Protocol parameter. Enable length block encryption."))
o.default = "0" o.default = "0"
o:depends({ [option_name("protocol")] = "vmess" }) o:depends({ [_n("protocol")] = "vmess" })
o = s:option(ListValue, option_name("flow"), translate("flow")) o = s:option(ListValue, _n("flow"), translate("flow"))
o.default = "" o.default = ""
o:value("", translate("Disable")) o:value("", translate("Disable"))
o:value("xtls-rprx-vision") o:value("xtls-rprx-vision")
o:depends({ [option_name("protocol")] = "vless", [option_name("tls")] = true }) o:depends({ [_n("protocol")] = "vless", [_n("tls")] = true })
if singbox_tags:find("with_quic") then if singbox_tags:find("with_quic") then
o = s:option(Value, option_name("hysteria_obfs"), translate("Obfs Password")) o = s:option(Value, _n("hysteria_obfs"), translate("Obfs Password"))
o:depends({ [option_name("protocol")] = "hysteria" }) o:depends({ [_n("protocol")] = "hysteria" })
o = s:option(ListValue, option_name("hysteria_auth_type"), translate("Auth Type")) o = s:option(ListValue, _n("hysteria_auth_type"), translate("Auth Type"))
o:value("disable", translate("Disable")) o:value("disable", translate("Disable"))
o:value("string", translate("STRING")) o:value("string", translate("STRING"))
o:value("base64", translate("BASE64")) o:value("base64", translate("BASE64"))
o:depends({ [option_name("protocol")] = "hysteria" }) o:depends({ [_n("protocol")] = "hysteria" })
o = s:option(Value, option_name("hysteria_auth_password"), translate("Auth Password")) o = s:option(Value, _n("hysteria_auth_password"), translate("Auth Password"))
o.password = true o.password = true
o:depends({ [option_name("protocol")] = "hysteria", [option_name("hysteria_auth_type")] = "string"}) o:depends({ [_n("protocol")] = "hysteria", [_n("hysteria_auth_type")] = "string"})
o:depends({ [option_name("protocol")] = "hysteria", [option_name("hysteria_auth_type")] = "base64"}) o:depends({ [_n("protocol")] = "hysteria", [_n("hysteria_auth_type")] = "base64"})
o = s:option(Value, option_name("hysteria_up_mbps"), translate("Max upload Mbps")) o = s:option(Value, _n("hysteria_up_mbps"), translate("Max upload Mbps"))
o.default = "10" o.default = "10"
o:depends({ [option_name("protocol")] = "hysteria" }) o:depends({ [_n("protocol")] = "hysteria" })
o = s:option(Value, option_name("hysteria_down_mbps"), translate("Max download Mbps")) o = s:option(Value, _n("hysteria_down_mbps"), translate("Max download Mbps"))
o.default = "50" o.default = "50"
o:depends({ [option_name("protocol")] = "hysteria" }) o:depends({ [_n("protocol")] = "hysteria" })
o = s:option(Value, option_name("hysteria_recv_window_conn"), translate("QUIC stream receive window")) o = s:option(Value, _n("hysteria_recv_window_conn"), translate("QUIC stream receive window"))
o:depends({ [option_name("protocol")] = "hysteria" }) o:depends({ [_n("protocol")] = "hysteria" })
o = s:option(Value, option_name("hysteria_recv_window"), translate("QUIC connection receive window")) o = s:option(Value, _n("hysteria_recv_window"), translate("QUIC connection receive window"))
o:depends({ [option_name("protocol")] = "hysteria" }) o:depends({ [_n("protocol")] = "hysteria" })
o = s:option(Flag, option_name("hysteria_disable_mtu_discovery"), translate("Disable MTU detection")) o = s:option(Flag, _n("hysteria_disable_mtu_discovery"), translate("Disable MTU detection"))
o:depends({ [option_name("protocol")] = "hysteria" }) o:depends({ [_n("protocol")] = "hysteria" })
o = s:option(Value, option_name("hysteria_alpn"), translate("QUIC TLS ALPN")) o = s:option(Value, _n("hysteria_alpn"), translate("QUIC TLS ALPN"))
o:depends({ [option_name("protocol")] = "hysteria" }) o:depends({ [_n("protocol")] = "hysteria" })
end end
if singbox_tags:find("with_quic") then if singbox_tags:find("with_quic") then
o = s:option(ListValue, option_name("tuic_congestion_control"), translate("Congestion control algorithm")) o = s:option(ListValue, _n("tuic_congestion_control"), translate("Congestion control algorithm"))
o.default = "cubic" o.default = "cubic"
o:value("bbr", translate("BBR")) o:value("bbr", translate("BBR"))
o:value("cubic", translate("CUBIC")) o:value("cubic", translate("CUBIC"))
o:value("new_reno", translate("New Reno")) o:value("new_reno", translate("New Reno"))
o:depends({ [option_name("protocol")] = "tuic" }) o:depends({ [_n("protocol")] = "tuic" })
o = s:option(ListValue, option_name("tuic_udp_relay_mode"), translate("UDP relay mode")) o = s:option(ListValue, _n("tuic_udp_relay_mode"), translate("UDP relay mode"))
o.default = "native" o.default = "native"
o:value("native", translate("native")) o:value("native", translate("native"))
o:value("quic", translate("QUIC")) o:value("quic", translate("QUIC"))
o:depends({ [option_name("protocol")] = "tuic" }) o:depends({ [_n("protocol")] = "tuic" })
--[[ --[[
o = s:option(Flag, option_name("tuic_udp_over_stream"), translate("UDP over stream")) o = s:option(Flag, _n("tuic_udp_over_stream"), translate("UDP over stream"))
o:depends({ [option_name("protocol")] = "tuic" }) o:depends({ [_n("protocol")] = "tuic" })
]]-- ]]--
o = s:option(Flag, option_name("tuic_zero_rtt_handshake"), translate("Enable 0-RTT QUIC handshake")) o = s:option(Flag, _n("tuic_zero_rtt_handshake"), translate("Enable 0-RTT QUIC handshake"))
o.default = 0 o.default = 0
o:depends({ [option_name("protocol")] = "tuic" }) o:depends({ [_n("protocol")] = "tuic" })
o = s:option(Value, option_name("tuic_heartbeat"), translate("Heartbeat interval(second)")) o = s:option(Value, _n("tuic_heartbeat"), translate("Heartbeat interval(second)"))
o.datatype = "uinteger" o.datatype = "uinteger"
o.default = "3" o.default = "3"
o:depends({ [option_name("protocol")] = "tuic" }) o:depends({ [_n("protocol")] = "tuic" })
o = s:option(ListValue, option_name("tuic_alpn"), translate("QUIC TLS ALPN")) o = s:option(ListValue, _n("tuic_alpn"), translate("QUIC TLS ALPN"))
o.default = "default" o.default = "default"
o:value("default", translate("Default")) o:value("default", translate("Default"))
o:value("h3") o:value("h3")
@ -343,38 +343,38 @@ if singbox_tags:find("with_quic") then
o:value("http/1.1") o:value("http/1.1")
o:value("h2,http/1.1") o:value("h2,http/1.1")
o:value("h3,h2,http/1.1") o:value("h3,h2,http/1.1")
o:depends({ [option_name("protocol")] = "tuic" }) o:depends({ [_n("protocol")] = "tuic" })
end end
if singbox_tags:find("with_quic") then if singbox_tags:find("with_quic") then
o = s:option(Value, option_name("hysteria2_up_mbps"), translate("Max upload Mbps")) o = s:option(Value, _n("hysteria2_up_mbps"), translate("Max upload Mbps"))
o:depends({ [option_name("protocol")] = "hysteria2" }) o:depends({ [_n("protocol")] = "hysteria2" })
o = s:option(Value, option_name("hysteria2_down_mbps"), translate("Max download Mbps")) o = s:option(Value, _n("hysteria2_down_mbps"), translate("Max download Mbps"))
o:depends({ [option_name("protocol")] = "hysteria2" }) o:depends({ [_n("protocol")] = "hysteria2" })
o = s:option(ListValue, option_name("hysteria2_obfs_type"), translate("Obfs Type")) o = s:option(ListValue, _n("hysteria2_obfs_type"), translate("Obfs Type"))
o:value("", translate("Disable")) o:value("", translate("Disable"))
o:value("salamander") o:value("salamander")
o:depends({ [option_name("protocol")] = "hysteria2" }) o:depends({ [_n("protocol")] = "hysteria2" })
o = s:option(Value, option_name("hysteria2_obfs_password"), translate("Obfs Password")) o = s:option(Value, _n("hysteria2_obfs_password"), translate("Obfs Password"))
o:depends({ [option_name("protocol")] = "hysteria2" }) o:depends({ [_n("protocol")] = "hysteria2" })
o = s:option(Value, option_name("hysteria2_auth_password"), translate("Auth Password")) o = s:option(Value, _n("hysteria2_auth_password"), translate("Auth Password"))
o.password = true o.password = true
o:depends({ [option_name("protocol")] = "hysteria2"}) o:depends({ [_n("protocol")] = "hysteria2"})
end end
o = s:option(Flag, option_name("tls"), translate("TLS")) o = s:option(Flag, _n("tls"), translate("TLS"))
o.default = 0 o.default = 0
o:depends({ [option_name("protocol")] = "vmess" }) o:depends({ [_n("protocol")] = "vmess" })
o:depends({ [option_name("protocol")] = "vless" }) o:depends({ [_n("protocol")] = "vless" })
o:depends({ [option_name("protocol")] = "http" }) o:depends({ [_n("protocol")] = "http" })
o:depends({ [option_name("protocol")] = "trojan" }) o:depends({ [_n("protocol")] = "trojan" })
o:depends({ [option_name("protocol")] = "shadowsocks" }) o:depends({ [_n("protocol")] = "shadowsocks" })
o = s:option(ListValue, option_name("alpn"), translate("alpn")) o = s:option(ListValue, _n("alpn"), translate("alpn"))
o.default = "default" o.default = "default"
o:value("default", translate("Default")) o:value("default", translate("Default"))
o:value("h3") o:value("h3")
@ -383,36 +383,36 @@ o:value("h3,h2")
o:value("http/1.1") o:value("http/1.1")
o:value("h2,http/1.1") o:value("h2,http/1.1")
o:value("h3,h2,http/1.1") o:value("h3,h2,http/1.1")
o:depends({ [option_name("tls")] = true }) o:depends({ [_n("tls")] = true })
o = s:option(Value, option_name("tls_serverName"), translate("Domain")) o = s:option(Value, _n("tls_serverName"), translate("Domain"))
o:depends({ [option_name("tls")] = true }) o:depends({ [_n("tls")] = true })
o:depends({ [option_name("protocol")] = "hysteria"}) o:depends({ [_n("protocol")] = "hysteria"})
o:depends({ [option_name("protocol")] = "tuic" }) o:depends({ [_n("protocol")] = "tuic" })
o:depends({ [option_name("protocol")] = "hysteria2" }) o:depends({ [_n("protocol")] = "hysteria2" })
o:depends({ [option_name("protocol")] = "shadowsocks" }) o:depends({ [_n("protocol")] = "shadowsocks" })
o = s:option(Flag, option_name("tls_allowInsecure"), translate("allowInsecure"), translate("Whether unsafe connections are allowed. When checked, Certificate validation will be skipped.")) o = s:option(Flag, _n("tls_allowInsecure"), translate("allowInsecure"), translate("Whether unsafe connections are allowed. When checked, Certificate validation will be skipped."))
o.default = "0" o.default = "0"
o:depends({ [option_name("tls")] = true }) o:depends({ [_n("tls")] = true })
o:depends({ [option_name("protocol")] = "hysteria"}) o:depends({ [_n("protocol")] = "hysteria"})
o:depends({ [option_name("protocol")] = "tuic" }) o:depends({ [_n("protocol")] = "tuic" })
o:depends({ [option_name("protocol")] = "hysteria2" }) o:depends({ [_n("protocol")] = "hysteria2" })
o:depends({ [option_name("protocol")] = "shadowsocks" }) o:depends({ [_n("protocol")] = "shadowsocks" })
if singbox_tags:find("with_ech") then if singbox_tags:find("with_ech") then
o = s:option(Flag, option_name("ech"), translate("ECH")) o = s:option(Flag, _n("ech"), translate("ECH"))
o.default = "0" o.default = "0"
o:depends({ [option_name("tls")] = true, [option_name("flow")] = "", [option_name("reality")] = false }) o:depends({ [_n("tls")] = true, [_n("flow")] = "", [_n("reality")] = false })
o:depends({ [option_name("protocol")] = "tuic" }) o:depends({ [_n("protocol")] = "tuic" })
o:depends({ [option_name("protocol")] = "hysteria" }) o:depends({ [_n("protocol")] = "hysteria" })
o:depends({ [option_name("protocol")] = "hysteria2" }) o:depends({ [_n("protocol")] = "hysteria2" })
o = s:option(TextValue, option_name("ech_config"), translate("ECH Config")) o = s:option(TextValue, _n("ech_config"), translate("ECH Config"))
o.default = "" o.default = ""
o.rows = 5 o.rows = 5
o.wrap = "off" o.wrap = "off"
o:depends({ [option_name("ech")] = true }) o:depends({ [_n("ech")] = true })
o.validate = function(self, value) o.validate = function(self, value)
value = value:gsub("^%s+", ""):gsub("%s+$","\n"):gsub("\r\n","\n"):gsub("[ \t]*\n[ \t]*", "\n") value = value:gsub("^%s+", ""):gsub("%s+$","\n"):gsub("\r\n","\n"):gsub("[ \t]*\n[ \t]*", "\n")
value = value:gsub("^%s*\n", "") value = value:gsub("^%s*\n", "")
@ -422,21 +422,21 @@ if singbox_tags:find("with_ech") then
return value return value
end end
o = s:option(Flag, option_name("pq_signature_schemes_enabled"), translate("PQ signature schemes")) o = s:option(Flag, _n("pq_signature_schemes_enabled"), translate("PQ signature schemes"))
o.default = "0" o.default = "0"
o:depends({ [option_name("ech")] = true }) o:depends({ [_n("ech")] = true })
o = s:option(Flag, option_name("dynamic_record_sizing_disabled"), translate("Disable adaptive sizing of TLS records")) o = s:option(Flag, _n("dynamic_record_sizing_disabled"), translate("Disable adaptive sizing of TLS records"))
o.default = "0" o.default = "0"
o:depends({ [option_name("ech")] = true }) o:depends({ [_n("ech")] = true })
end end
if singbox_tags:find("with_utls") then if singbox_tags:find("with_utls") then
o = s:option(Flag, option_name("utls"), translate("uTLS")) o = s:option(Flag, _n("utls"), translate("uTLS"))
o.default = "0" o.default = "0"
o:depends({ [option_name("tls")] = true }) o:depends({ [_n("tls")] = true })
o = s:option(ListValue, option_name("fingerprint"), translate("Finger Print")) o = s:option(ListValue, _n("fingerprint"), translate("Finger Print"))
o:value("chrome") o:value("chrome")
o:value("firefox") o:value("firefox")
o:value("edge") o:value("edge")
@ -448,25 +448,25 @@ if singbox_tags:find("with_utls") then
o:value("random") o:value("random")
-- o:value("randomized") -- o:value("randomized")
o.default = "chrome" o.default = "chrome"
o:depends({ [option_name("tls")] = true, [option_name("utls")] = true }) o:depends({ [_n("tls")] = true, [_n("utls")] = true })
-- [[ REALITY部分 ]] -- -- [[ REALITY部分 ]] --
o = s:option(Flag, option_name("reality"), translate("REALITY")) o = s:option(Flag, _n("reality"), translate("REALITY"))
o.default = 0 o.default = 0
o:depends({ [option_name("protocol")] = "vless", [option_name("utls")] = true }) o:depends({ [_n("protocol")] = "vless", [_n("utls")] = true })
o:depends({ [option_name("protocol")] = "vmess", [option_name("utls")] = true }) o:depends({ [_n("protocol")] = "vmess", [_n("utls")] = true })
o:depends({ [option_name("protocol")] = "shadowsocks", [option_name("utls")] = true }) o:depends({ [_n("protocol")] = "shadowsocks", [_n("utls")] = true })
o:depends({ [option_name("protocol")] = "socks", [option_name("utls")] = true }) o:depends({ [_n("protocol")] = "socks", [_n("utls")] = true })
o:depends({ [option_name("protocol")] = "trojan", [option_name("utls")] = true }) o:depends({ [_n("protocol")] = "trojan", [_n("utls")] = true })
o = s:option(Value, option_name("reality_publicKey"), translate("Public Key")) o = s:option(Value, _n("reality_publicKey"), translate("Public Key"))
o:depends({ [option_name("utls")] = true, [option_name("reality")] = true }) o:depends({ [_n("utls")] = true, [_n("reality")] = true })
o = s:option(Value, option_name("reality_shortId"), translate("Short Id")) o = s:option(Value, _n("reality_shortId"), translate("Short Id"))
o:depends({ [option_name("utls")] = true, [option_name("reality")] = true }) o:depends({ [_n("utls")] = true, [_n("reality")] = true })
end end
o = s:option(ListValue, option_name("transport"), translate("Transport")) o = s:option(ListValue, _n("transport"), translate("Transport"))
o:value("tcp", "TCP") o:value("tcp", "TCP")
o:value("http", "HTTP") o:value("http", "HTTP")
o:value("ws", "WebSocket") o:value("ws", "WebSocket")
@ -478,165 +478,165 @@ if singbox_tags:find("with_grpc") then
o:value("grpc", "gRPC") o:value("grpc", "gRPC")
else o:value("grpc", "gRPC-lite") else o:value("grpc", "gRPC-lite")
end end
o:depends({ [option_name("protocol")] = "vmess" }) o:depends({ [_n("protocol")] = "vmess" })
o:depends({ [option_name("protocol")] = "vless" }) o:depends({ [_n("protocol")] = "vless" })
o:depends({ [option_name("protocol")] = "socks" }) o:depends({ [_n("protocol")] = "socks" })
o:depends({ [option_name("protocol")] = "shadowsocks" }) o:depends({ [_n("protocol")] = "shadowsocks" })
o:depends({ [option_name("protocol")] = "trojan" }) o:depends({ [_n("protocol")] = "trojan" })
if singbox_tags:find("with_wireguard") then if singbox_tags:find("with_wireguard") then
o = s:option(Value, option_name("wireguard_public_key"), translate("Public Key")) o = s:option(Value, _n("wireguard_public_key"), translate("Public Key"))
o:depends({ [option_name("protocol")] = "wireguard" }) o:depends({ [_n("protocol")] = "wireguard" })
o = s:option(Value, option_name("wireguard_secret_key"), translate("Private Key")) o = s:option(Value, _n("wireguard_secret_key"), translate("Private Key"))
o:depends({ [option_name("protocol")] = "wireguard" }) o:depends({ [_n("protocol")] = "wireguard" })
o = s:option(Value, option_name("wireguard_preSharedKey"), translate("Pre shared key")) o = s:option(Value, _n("wireguard_preSharedKey"), translate("Pre shared key"))
o:depends({ [option_name("protocol")] = "wireguard" }) o:depends({ [_n("protocol")] = "wireguard" })
o = s:option(DynamicList, option_name("wireguard_local_address"), translate("Local Address")) o = s:option(DynamicList, _n("wireguard_local_address"), translate("Local Address"))
o:depends({ [option_name("protocol")] = "wireguard" }) o:depends({ [_n("protocol")] = "wireguard" })
o = s:option(Value, option_name("wireguard_mtu"), translate("MTU")) o = s:option(Value, _n("wireguard_mtu"), translate("MTU"))
o.default = "1420" o.default = "1420"
o:depends({ [option_name("protocol")] = "wireguard" }) o:depends({ [_n("protocol")] = "wireguard" })
o = s:option(Flag, option_name("wireguard_system_interface"), translate("System interface")) o = s:option(Flag, _n("wireguard_system_interface"), translate("System interface"))
o.default = 0 o.default = 0
o:depends({ [option_name("protocol")] = "wireguard" }) o:depends({ [_n("protocol")] = "wireguard" })
o = s:option(Value, option_name("wireguard_interface_name"), translate("System interface name")) o = s:option(Value, _n("wireguard_interface_name"), translate("System interface name"))
o:depends({ [option_name("protocol")] = "wireguard" }) o:depends({ [_n("protocol")] = "wireguard" })
o = s:option(Value, option_name("wireguard_reserved"), translate("Reserved"), translate("Decimal numbers separated by \",\" or Base64-encoded strings.")) o = s:option(Value, _n("wireguard_reserved"), translate("Reserved"), translate("Decimal numbers separated by \",\" or Base64-encoded strings."))
o:depends({ [option_name("protocol")] = "wireguard" }) o:depends({ [_n("protocol")] = "wireguard" })
end end
-- [[ HTTP部分 ]]-- -- [[ HTTP部分 ]]--
o = s:option(Value, option_name("http_host"), translate("HTTP Host")) o = s:option(Value, _n("http_host"), translate("HTTP Host"))
o:depends({ [option_name("transport")] = "http" }) o:depends({ [_n("transport")] = "http" })
o = s:option(Value, option_name("http_path"), translate("HTTP Path")) o = s:option(Value, _n("http_path"), translate("HTTP Path"))
o.placeholder = "/" o.placeholder = "/"
o:depends({ [option_name("transport")] = "http" }) o:depends({ [_n("transport")] = "http" })
o = s:option(Flag, option_name("http_h2_health_check"), translate("Health check")) o = s:option(Flag, _n("http_h2_health_check"), translate("Health check"))
o:depends({ [option_name("tls")] = true, [option_name("transport")] = "http" }) o:depends({ [_n("tls")] = true, [_n("transport")] = "http" })
o = s:option(Value, option_name("http_h2_read_idle_timeout"), translate("Idle timeout")) o = s:option(Value, _n("http_h2_read_idle_timeout"), translate("Idle timeout"))
o.default = "10" o.default = "10"
o:depends({ [option_name("tls")] = true, [option_name("transport")] = "http", [option_name("http_h2_health_check")] = true }) o:depends({ [_n("tls")] = true, [_n("transport")] = "http", [_n("http_h2_health_check")] = true })
o = s:option(Value, option_name("http_h2_health_check_timeout"), translate("Health check timeout")) o = s:option(Value, _n("http_h2_health_check_timeout"), translate("Health check timeout"))
o.default = "15" o.default = "15"
o:depends({ [option_name("tls")] = true, [option_name("transport")] = "http", [option_name("http_h2_health_check")] = true }) o:depends({ [_n("tls")] = true, [_n("transport")] = "http", [_n("http_h2_health_check")] = true })
-- [[ WebSocket部分 ]]-- -- [[ WebSocket部分 ]]--
o = s:option(Value, option_name("ws_host"), translate("WebSocket Host")) o = s:option(Value, _n("ws_host"), translate("WebSocket Host"))
o:depends({ [option_name("transport")] = "ws" }) o:depends({ [_n("transport")] = "ws" })
o = s:option(Value, option_name("ws_path"), translate("WebSocket Path")) o = s:option(Value, _n("ws_path"), translate("WebSocket Path"))
o.placeholder = "/" o.placeholder = "/"
o:depends({ [option_name("transport")] = "ws" }) o:depends({ [_n("transport")] = "ws" })
o = s:option(Flag, option_name("ws_enableEarlyData"), translate("Enable early data")) o = s:option(Flag, _n("ws_enableEarlyData"), translate("Enable early data"))
o:depends({ [option_name("transport")] = "ws" }) o:depends({ [_n("transport")] = "ws" })
o = s:option(Value, option_name("ws_maxEarlyData"), translate("Early data length")) o = s:option(Value, _n("ws_maxEarlyData"), translate("Early data length"))
o.default = "1024" o.default = "1024"
o:depends({ [option_name("ws_enableEarlyData")] = true }) o:depends({ [_n("ws_enableEarlyData")] = true })
o = s:option(Value, option_name("ws_earlyDataHeaderName"), translate("Early data header name"), translate("Recommended value: Sec-WebSocket-Protocol")) o = s:option(Value, _n("ws_earlyDataHeaderName"), translate("Early data header name"), translate("Recommended value: Sec-WebSocket-Protocol"))
o:depends({ [option_name("ws_enableEarlyData")] = true }) o:depends({ [_n("ws_enableEarlyData")] = true })
-- [[ HTTPUpgrade部分 ]]-- -- [[ HTTPUpgrade部分 ]]--
o = s:option(Value, option_name("httpupgrade_host"), translate("HTTPUpgrade Host")) o = s:option(Value, _n("httpupgrade_host"), translate("HTTPUpgrade Host"))
o:depends({ [option_name("transport")] = "httpupgrade" }) o:depends({ [_n("transport")] = "httpupgrade" })
o = s:option(Value, option_name("httpupgrade_path"), translate("HTTPUpgrade Path")) o = s:option(Value, _n("httpupgrade_path"), translate("HTTPUpgrade Path"))
o.placeholder = "/" o.placeholder = "/"
o:depends({ [option_name("transport")] = "httpupgrade" }) o:depends({ [_n("transport")] = "httpupgrade" })
-- [[ gRPC部分 ]]-- -- [[ gRPC部分 ]]--
o = s:option(Value, option_name("grpc_serviceName"), "ServiceName") o = s:option(Value, _n("grpc_serviceName"), "ServiceName")
o:depends({ [option_name("transport")] = "grpc" }) o:depends({ [_n("transport")] = "grpc" })
o = s:option(Flag, option_name("grpc_health_check"), translate("Health check")) o = s:option(Flag, _n("grpc_health_check"), translate("Health check"))
o:depends({ [option_name("transport")] = "grpc" }) o:depends({ [_n("transport")] = "grpc" })
o = s:option(Value, option_name("grpc_idle_timeout"), translate("Idle timeout")) o = s:option(Value, _n("grpc_idle_timeout"), translate("Idle timeout"))
o.default = "10" o.default = "10"
o:depends({ [option_name("grpc_health_check")] = true }) o:depends({ [_n("grpc_health_check")] = true })
o = s:option(Value, option_name("grpc_health_check_timeout"), translate("Health check timeout")) o = s:option(Value, _n("grpc_health_check_timeout"), translate("Health check timeout"))
o.default = "20" o.default = "20"
o:depends({ [option_name("grpc_health_check")] = true }) o:depends({ [_n("grpc_health_check")] = true })
o = s:option(Flag, option_name("grpc_permit_without_stream"), translate("Permit without stream")) o = s:option(Flag, _n("grpc_permit_without_stream"), translate("Permit without stream"))
o.default = "0" o.default = "0"
o:depends({ [option_name("grpc_health_check")] = true }) o:depends({ [_n("grpc_health_check")] = true })
-- [[ Mux ]]-- -- [[ Mux ]]--
o = s:option(Flag, option_name("mux"), translate("Mux")) o = s:option(Flag, _n("mux"), translate("Mux"))
o.rmempty = false o.rmempty = false
o:depends({ [option_name("protocol")] = "vmess" }) o:depends({ [_n("protocol")] = "vmess" })
o:depends({ [option_name("protocol")] = "vless", [option_name("flow")] = "" }) o:depends({ [_n("protocol")] = "vless", [_n("flow")] = "" })
o:depends({ [option_name("protocol")] = "shadowsocks", [option_name("uot")] = "" }) o:depends({ [_n("protocol")] = "shadowsocks", [_n("uot")] = "" })
o:depends({ [option_name("protocol")] = "trojan" }) o:depends({ [_n("protocol")] = "trojan" })
o = s:option(ListValue, option_name("mux_type"), translate("Mux")) o = s:option(ListValue, _n("mux_type"), translate("Mux"))
o:value("smux") o:value("smux")
o:value("yamux") o:value("yamux")
o:value("h2mux") o:value("h2mux")
o:depends({ [option_name("mux")] = true }) o:depends({ [_n("mux")] = true })
o = s:option(Value, option_name("mux_concurrency"), translate("Mux concurrency")) o = s:option(Value, _n("mux_concurrency"), translate("Mux concurrency"))
o.default = 4 o.default = 4
o:depends({ [option_name("mux")] = true, [option_name("tcpbrutal")] = false }) o:depends({ [_n("mux")] = true, [_n("tcpbrutal")] = false })
o = s:option(Flag, option_name("mux_padding"), translate("Padding")) o = s:option(Flag, _n("mux_padding"), translate("Padding"))
o.default = 0 o.default = 0
o:depends({ [option_name("mux")] = true }) o:depends({ [_n("mux")] = true })
-- [[ TCP Brutal ]]-- -- [[ TCP Brutal ]]--
o = s:option(Flag, option_name("tcpbrutal"), translate("TCP Brutal")) o = s:option(Flag, _n("tcpbrutal"), translate("TCP Brutal"))
o.default = 0 o.default = 0
o:depends({ [option_name("mux")] = true }) o:depends({ [_n("mux")] = true })
o = s:option(Value, option_name("tcpbrutal_up_mbps"), translate("Max upload Mbps")) o = s:option(Value, _n("tcpbrutal_up_mbps"), translate("Max upload Mbps"))
o.default = "10" o.default = "10"
o:depends({ [option_name("tcpbrutal")] = true }) o:depends({ [_n("tcpbrutal")] = true })
o = s:option(Value, option_name("tcpbrutal_down_mbps"), translate("Max download Mbps")) o = s:option(Value, _n("tcpbrutal_down_mbps"), translate("Max download Mbps"))
o.default = "50" o.default = "50"
o:depends({ [option_name("tcpbrutal")] = true }) o:depends({ [_n("tcpbrutal")] = true })
o = s:option(Flag, option_name("shadowtls"), "ShadowTLS") o = s:option(Flag, _n("shadowtls"), "ShadowTLS")
o.default = 0 o.default = 0
o:depends({ [option_name("protocol")] = "vmess", [option_name("tls")] = false }) o:depends({ [_n("protocol")] = "vmess", [_n("tls")] = false })
o:depends({ [option_name("protocol")] = "shadowsocks", [option_name("tls")] = false }) o:depends({ [_n("protocol")] = "shadowsocks", [_n("tls")] = false })
o = s:option(ListValue, option_name("shadowtls_version"), "ShadowTLS " .. translate("Version")) o = s:option(ListValue, _n("shadowtls_version"), "ShadowTLS " .. translate("Version"))
o.default = "1" o.default = "1"
o:value("1", "ShadowTLS v1") o:value("1", "ShadowTLS v1")
o:value("2", "ShadowTLS v2") o:value("2", "ShadowTLS v2")
o:value("3", "ShadowTLS v3") o:value("3", "ShadowTLS v3")
o:depends({ [option_name("shadowtls")] = true }) o:depends({ [_n("shadowtls")] = true })
o = s:option(Value, option_name("shadowtls_password"), "ShadowTLS " .. translate("Password")) o = s:option(Value, _n("shadowtls_password"), "ShadowTLS " .. translate("Password"))
o.password = true o.password = true
o:depends({ [option_name("shadowtls")] = true, [option_name("shadowtls_version")] = "2" }) o:depends({ [_n("shadowtls")] = true, [_n("shadowtls_version")] = "2" })
o:depends({ [option_name("shadowtls")] = true, [option_name("shadowtls_version")] = "3" }) o:depends({ [_n("shadowtls")] = true, [_n("shadowtls_version")] = "3" })
o = s:option(Value, option_name("shadowtls_serverName"), "ShadowTLS " .. translate("Domain")) o = s:option(Value, _n("shadowtls_serverName"), "ShadowTLS " .. translate("Domain"))
o:depends({ [option_name("shadowtls")] = true }) o:depends({ [_n("shadowtls")] = true })
if singbox_tags:find("with_utls") then if singbox_tags:find("with_utls") then
o = s:option(Flag, option_name("shadowtls_utls"), "ShadowTLS " .. translate("uTLS")) o = s:option(Flag, _n("shadowtls_utls"), "ShadowTLS " .. translate("uTLS"))
o.default = "0" o.default = "0"
o:depends({ [option_name("shadowtls")] = true }) o:depends({ [_n("shadowtls")] = true })
o = s:option(ListValue, option_name("shadowtls_fingerprint"), "ShadowTLS " .. translate("Finger Print")) o = s:option(ListValue, _n("shadowtls_fingerprint"), "ShadowTLS " .. translate("Finger Print"))
o:value("chrome") o:value("chrome")
o:value("firefox") o:value("firefox")
o:value("edge") o:value("edge")
@ -648,62 +648,62 @@ if singbox_tags:find("with_utls") then
o:value("random") o:value("random")
-- o:value("randomized") -- o:value("randomized")
o.default = "chrome" o.default = "chrome"
o:depends({ [option_name("shadowtls")] = true, [option_name("shadowtls_utls")] = true }) o:depends({ [_n("shadowtls")] = true, [_n("shadowtls_utls")] = true })
end end
-- [[ SIP003 plugin ]]-- -- [[ SIP003 plugin ]]--
o = s:option(Flag, option_name("plugin_enabled"), translate("plugin")) o = s:option(Flag, _n("plugin_enabled"), translate("plugin"))
o.default = 0 o.default = 0
o:depends({ [option_name("protocol")] = "shadowsocks" }) o:depends({ [_n("protocol")] = "shadowsocks" })
o = s:option(ListValue, option_name("plugin"), "SIP003 " .. translate("plugin")) o = s:option(ListValue, _n("plugin"), "SIP003 " .. translate("plugin"))
o.default = "obfs-local" o.default = "obfs-local"
o:depends({ [option_name("plugin_enabled")] = true }) o:depends({ [_n("plugin_enabled")] = true })
o:value("obfs-local") o:value("obfs-local")
o:value("v2ray-plugin") o:value("v2ray-plugin")
o = s:option(Value, option_name("plugin_opts"), translate("opts")) o = s:option(Value, _n("plugin_opts"), translate("opts"))
o:depends({ [option_name("plugin_enabled")] = true }) o:depends({ [_n("plugin_enabled")] = true })
o = s:option(ListValue, option_name("domain_strategy"), translate("Domain Strategy"), translate("If is domain name, The requested domain name will be resolved to IP before connect.")) o = s:option(ListValue, _n("domain_strategy"), translate("Domain Strategy"), translate("If is domain name, The requested domain name will be resolved to IP before connect."))
o.default = "" o.default = ""
o:value("", translate("Auto")) o:value("", translate("Auto"))
o:value("prefer_ipv4", translate("Prefer IPv4")) o:value("prefer_ipv4", translate("Prefer IPv4"))
o:value("prefer_ipv6", translate("Prefer IPv6")) o:value("prefer_ipv6", translate("Prefer IPv6"))
o:value("ipv4_only", translate("IPv4 Only")) o:value("ipv4_only", translate("IPv4 Only"))
o:value("ipv6_only", translate("IPv6 Only")) o:value("ipv6_only", translate("IPv6 Only"))
o:depends({ [option_name("protocol")] = "socks" }) o:depends({ [_n("protocol")] = "socks" })
o:depends({ [option_name("protocol")] = "http" }) o:depends({ [_n("protocol")] = "http" })
o:depends({ [option_name("protocol")] = "shadowsocks" }) o:depends({ [_n("protocol")] = "shadowsocks" })
o:depends({ [option_name("protocol")] = "shadowsocksr" }) o:depends({ [_n("protocol")] = "shadowsocksr" })
o:depends({ [option_name("protocol")] = "vmess" }) o:depends({ [_n("protocol")] = "vmess" })
o:depends({ [option_name("protocol")] = "trojan" }) o:depends({ [_n("protocol")] = "trojan" })
o:depends({ [option_name("protocol")] = "wireguard" }) o:depends({ [_n("protocol")] = "wireguard" })
o:depends({ [option_name("protocol")] = "hysteria" }) o:depends({ [_n("protocol")] = "hysteria" })
o:depends({ [option_name("protocol")] = "vless" }) o:depends({ [_n("protocol")] = "vless" })
o:depends({ [option_name("protocol")] = "tuic" }) o:depends({ [_n("protocol")] = "tuic" })
o:depends({ [option_name("protocol")] = "hysteria2" }) o:depends({ [_n("protocol")] = "hysteria2" })
o = s:option(ListValue, option_name("chain_proxy"), translate("Chain Proxy")) o = s:option(ListValue, _n("chain_proxy"), translate("Chain Proxy"))
o:value("", translate("Close(Not use)")) o:value("", translate("Close(Not use)"))
o:value("1", translate("Preproxy Node")) o:value("1", translate("Preproxy Node"))
o:value("2", translate("Landing Node")) o:value("2", translate("Landing Node"))
for i, v in ipairs(s.fields[option_name("protocol")].keylist) do for i, v in ipairs(s.fields[_n("protocol")].keylist) do
if not v:find("_") then if not v:find("_") then
o:depends({ [option_name("protocol")] = v }) o:depends({ [_n("protocol")] = v })
end end
end end
o = s:option(ListValue, option_name("preproxy_node"), translate("Preproxy Node"), translate("Only support a layer of proxy.")) o = s:option(ListValue, _n("preproxy_node"), translate("Preproxy Node"), translate("Only support a layer of proxy."))
o:depends({ [option_name("chain_proxy")] = "1" }) o:depends({ [_n("chain_proxy")] = "1" })
o = s:option(ListValue, option_name("to_node"), translate("Landing Node"), translate("Only support a layer of proxy.")) o = s:option(ListValue, _n("to_node"), translate("Landing Node"), translate("Only support a layer of proxy."))
o:depends({ [option_name("chain_proxy")] = "2" }) o:depends({ [_n("chain_proxy")] = "2" })
for k, v in pairs(nodes_table) do for k, v in pairs(nodes_table) do
if v.type == "sing-box" and v.id ~= arg[1] then if v.type == "sing-box" and v.id ~= arg[1] then
s.fields[option_name("preproxy_node")]:value(v.id, v.remark) s.fields[_n("preproxy_node")]:value(v.id, v.remark)
s.fields[option_name("to_node")]:value(v.id, v.remark) s.fields[_n("to_node")]:value(v.id, v.remark)
end end
end end

View File

@ -10,7 +10,7 @@ local type_name = "SS-Rust"
local option_prefix = "ssrust_" local option_prefix = "ssrust_"
local function option_name(name) local function _n(name)
return option_prefix .. name return option_prefix .. name
end end
@ -24,34 +24,34 @@ local ssrust_encrypt_method_list = {
s.fields["type"]:value(type_name, translate("Shadowsocks Rust")) s.fields["type"]:value(type_name, translate("Shadowsocks Rust"))
o = s:option(Value, option_name("address"), translate("Address (Support Domain Name)")) o = s:option(Value, _n("address"), translate("Address (Support Domain Name)"))
o = s:option(Value, option_name("port"), translate("Port")) o = s:option(Value, _n("port"), translate("Port"))
o.datatype = "port" o.datatype = "port"
o = s:option(Value, option_name("password"), translate("Password")) o = s:option(Value, _n("password"), translate("Password"))
o.password = true o.password = true
o = s:option(Value, option_name("method"), translate("Encrypt Method")) o = s:option(Value, _n("method"), translate("Encrypt Method"))
for a, t in ipairs(ssrust_encrypt_method_list) do o:value(t) end for a, t in ipairs(ssrust_encrypt_method_list) do o:value(t) end
o = s:option(Value, option_name("timeout"), translate("Connection Timeout")) o = s:option(Value, _n("timeout"), translate("Connection Timeout"))
o.datatype = "uinteger" o.datatype = "uinteger"
o.default = 300 o.default = 300
o = s:option(ListValue, option_name("tcp_fast_open"), "TCP " .. translate("Fast Open"), translate("Need node support required")) o = s:option(ListValue, _n("tcp_fast_open"), "TCP " .. translate("Fast Open"), translate("Need node support required"))
o:value("false") o:value("false")
o:value("true") o:value("true")
o = s:option(ListValue, option_name("plugin"), translate("plugin")) o = s:option(ListValue, _n("plugin"), translate("plugin"))
o:value("none", translate("none")) o:value("none", translate("none"))
if api.is_finded("xray-plugin") then o:value("xray-plugin") end if api.is_finded("xray-plugin") then o:value("xray-plugin") end
if api.is_finded("v2ray-plugin") then o:value("v2ray-plugin") end if api.is_finded("v2ray-plugin") then o:value("v2ray-plugin") end
if api.is_finded("obfs-local") then o:value("obfs-local") end if api.is_finded("obfs-local") then o:value("obfs-local") end
o = s:option(Value, option_name("plugin_opts"), translate("opts")) o = s:option(Value, _n("plugin_opts"), translate("opts"))
o:depends({ [option_name("plugin")] = "xray-plugin"}) o:depends({ [_n("plugin")] = "xray-plugin"})
o:depends({ [option_name("plugin")] = "v2ray-plugin"}) o:depends({ [_n("plugin")] = "v2ray-plugin"})
o:depends({ [option_name("plugin")] = "obfs-local"}) o:depends({ [_n("plugin")] = "obfs-local"})
api.luci_types(arg[1], m, s, type_name, option_prefix) api.luci_types(arg[1], m, s, type_name, option_prefix)

View File

@ -10,7 +10,7 @@ local type_name = "SS"
local option_prefix = "ss_" local option_prefix = "ss_"
local function option_name(name) local function _n(name)
return option_prefix .. name return option_prefix .. name
end end
@ -25,34 +25,34 @@ local ss_encrypt_method_list = {
s.fields["type"]:value(type_name, translate("Shadowsocks Libev")) s.fields["type"]:value(type_name, translate("Shadowsocks Libev"))
o = s:option(Value, option_name("address"), translate("Address (Support Domain Name)")) o = s:option(Value, _n("address"), translate("Address (Support Domain Name)"))
o = s:option(Value, option_name("port"), translate("Port")) o = s:option(Value, _n("port"), translate("Port"))
o.datatype = "port" o.datatype = "port"
o = s:option(Value, option_name("password"), translate("Password")) o = s:option(Value, _n("password"), translate("Password"))
o.password = true o.password = true
o = s:option(Value, option_name("method"), translate("Encrypt Method")) o = s:option(Value, _n("method"), translate("Encrypt Method"))
for a, t in ipairs(ss_encrypt_method_list) do o:value(t) end for a, t in ipairs(ss_encrypt_method_list) do o:value(t) end
o = s:option(Value, option_name("timeout"), translate("Connection Timeout")) o = s:option(Value, _n("timeout"), translate("Connection Timeout"))
o.datatype = "uinteger" o.datatype = "uinteger"
o.default = 300 o.default = 300
o = s:option(ListValue, option_name("tcp_fast_open"), "TCP " .. translate("Fast Open"), translate("Need node support required")) o = s:option(ListValue, _n("tcp_fast_open"), "TCP " .. translate("Fast Open"), translate("Need node support required"))
o:value("false") o:value("false")
o:value("true") o:value("true")
o = s:option(ListValue, option_name("plugin"), translate("plugin")) o = s:option(ListValue, _n("plugin"), translate("plugin"))
o:value("none", translate("none")) o:value("none", translate("none"))
if api.is_finded("xray-plugin") then o:value("xray-plugin") end if api.is_finded("xray-plugin") then o:value("xray-plugin") end
if api.is_finded("v2ray-plugin") then o:value("v2ray-plugin") end if api.is_finded("v2ray-plugin") then o:value("v2ray-plugin") end
if api.is_finded("obfs-local") then o:value("obfs-local") end if api.is_finded("obfs-local") then o:value("obfs-local") end
o = s:option(Value, option_name("plugin_opts"), translate("opts")) o = s:option(Value, _n("plugin_opts"), translate("opts"))
o:depends({ [option_name("plugin")] = "xray-plugin"}) o:depends({ [_n("plugin")] = "xray-plugin"})
o:depends({ [option_name("plugin")] = "v2ray-plugin"}) o:depends({ [_n("plugin")] = "v2ray-plugin"})
o:depends({ [option_name("plugin")] = "obfs-local"}) o:depends({ [_n("plugin")] = "obfs-local"})
api.luci_types(arg[1], m, s, type_name, option_prefix) api.luci_types(arg[1], m, s, type_name, option_prefix)

View File

@ -10,7 +10,7 @@ local type_name = "SSR"
local option_prefix = "ssr_" local option_prefix = "ssr_"
local function option_name(name) local function _n(name)
return option_prefix .. name return option_prefix .. name
end end
@ -37,32 +37,32 @@ local ssr_obfs_list = {
s.fields["type"]:value(type_name, translate("ShadowsocksR Libev")) s.fields["type"]:value(type_name, translate("ShadowsocksR Libev"))
o = s:option(Value, option_name("address"), translate("Address (Support Domain Name)")) o = s:option(Value, _n("address"), translate("Address (Support Domain Name)"))
o = s:option(Value, option_name("port"), translate("Port")) o = s:option(Value, _n("port"), translate("Port"))
o.datatype = "port" o.datatype = "port"
o = s:option(Value, option_name("password"), translate("Password")) o = s:option(Value, _n("password"), translate("Password"))
o.password = true o.password = true
o = s:option(ListValue, option_name("method"), translate("Encrypt Method")) o = s:option(ListValue, _n("method"), translate("Encrypt Method"))
for a, t in ipairs(ssr_encrypt_method_list) do o:value(t) end for a, t in ipairs(ssr_encrypt_method_list) do o:value(t) end
o = s:option(ListValue, option_name("protocol"), translate("Protocol")) o = s:option(ListValue, _n("protocol"), translate("Protocol"))
for a, t in ipairs(ssr_protocol_list) do o:value(t) end for a, t in ipairs(ssr_protocol_list) do o:value(t) end
o = s:option(Value, option_name("protocol_param"), translate("Protocol_param")) o = s:option(Value, _n("protocol_param"), translate("Protocol_param"))
o = s:option(ListValue, option_name("obfs"), translate("Obfs")) o = s:option(ListValue, _n("obfs"), translate("Obfs"))
for a, t in ipairs(ssr_obfs_list) do o:value(t) end for a, t in ipairs(ssr_obfs_list) do o:value(t) end
o = s:option(Value, option_name("obfs_param"), translate("Obfs_param")) o = s:option(Value, _n("obfs_param"), translate("Obfs_param"))
o = s:option(Value, option_name("timeout"), translate("Connection Timeout")) o = s:option(Value, _n("timeout"), translate("Connection Timeout"))
o.datatype = "uinteger" o.datatype = "uinteger"
o.default = 300 o.default = 300
o = s:option(ListValue, option_name("tcp_fast_open"), "TCP " .. translate("Fast Open"), translate("Need node support required")) o = s:option(ListValue, _n("tcp_fast_open"), "TCP " .. translate("Fast Open"), translate("Need node support required"))
o:value("false") o:value("false")
o:value("true") o:value("true")

View File

@ -10,7 +10,7 @@ local type_name = "TUIC"
local option_prefix = "tuic_" local option_prefix = "tuic_"
local function option_name(name) local function _n(name)
return option_prefix .. name return option_prefix .. name
end end
@ -18,16 +18,16 @@ end
s.fields["type"]:value(type_name, translate("TUIC")) s.fields["type"]:value(type_name, translate("TUIC"))
o = s:option(Value, option_name("address"), translate("Address (Support Domain Name)")) o = s:option(Value, _n("address"), translate("Address (Support Domain Name)"))
o = s:option(Value, option_name("port"), translate("Port")) o = s:option(Value, _n("port"), translate("Port"))
o.datatype = "port" o.datatype = "port"
o = s:option(Value, option_name("uuid"), translate("ID")) o = s:option(Value, _n("uuid"), translate("ID"))
o.password = true o.password = true
-- Tuic Password for remote server connect -- Tuic Password for remote server connect
o = s:option(Value, option_name("password"), translate("TUIC User Password For Connect Remote Server")) o = s:option(Value, _n("password"), translate("TUIC User Password For Connect Remote Server"))
o.password = true o.password = true
o.rmempty = true o.rmempty = true
o.default = "" o.default = ""
@ -35,32 +35,32 @@ o.rewrite_option = o.option
--[[ --[[
-- Tuic username for local socks connect -- Tuic username for local socks connect
o = s:option(Value, option_name("socks_username"), translate("TUIC UserName For Local Socks")) o = s:option(Value, _n("socks_username"), translate("TUIC UserName For Local Socks"))
o.rmempty = true o.rmempty = true
o.default = "" o.default = ""
o.rewrite_option = o.option o.rewrite_option = o.option
-- Tuic Password for local socks connect -- Tuic Password for local socks connect
o = s:option(Value, option_name("socks_password"), translate("TUIC Password For Local Socks")) o = s:option(Value, _n("socks_password"), translate("TUIC Password For Local Socks"))
o.password = true o.password = true
o.rmempty = true o.rmempty = true
o.default = "" o.default = ""
o.rewrite_option = o.option o.rewrite_option = o.option
--]] --]]
o = s:option(Value, option_name("ip"), translate("Set the TUIC proxy server ip address")) o = s:option(Value, _n("ip"), translate("Set the TUIC proxy server ip address"))
o.datatype = "ipaddr" o.datatype = "ipaddr"
o.rmempty = true o.rmempty = true
o.rewrite_option = o.option o.rewrite_option = o.option
o = s:option(ListValue, option_name("udp_relay_mode"), translate("UDP relay mode")) o = s:option(ListValue, _n("udp_relay_mode"), translate("UDP relay mode"))
o:value("native", translate("native")) o:value("native", translate("native"))
o:value("quic", translate("QUIC")) o:value("quic", translate("QUIC"))
o.default = "native" o.default = "native"
o.rmempty = true o.rmempty = true
o.rewrite_option = o.option o.rewrite_option = o.option
o = s:option(ListValue, option_name("congestion_control"), translate("Congestion control algorithm")) o = s:option(ListValue, _n("congestion_control"), translate("Congestion control algorithm"))
o:value("bbr", translate("BBR")) o:value("bbr", translate("BBR"))
o:value("cubic", translate("CUBIC")) o:value("cubic", translate("CUBIC"))
o:value("new_reno", translate("New Reno")) o:value("new_reno", translate("New Reno"))
@ -68,65 +68,65 @@ o.default = "cubic"
o.rmempty = true o.rmempty = true
o.rewrite_option = o.option o.rewrite_option = o.option
o = s:option(Value, option_name("heartbeat"), translate("Heartbeat interval(second)")) o = s:option(Value, _n("heartbeat"), translate("Heartbeat interval(second)"))
o.datatype = "uinteger" o.datatype = "uinteger"
o.default = "3" o.default = "3"
o.rmempty = true o.rmempty = true
o.rewrite_option = o.option o.rewrite_option = o.option
o = s:option(Value, option_name("timeout"), translate("Timeout for establishing a connection to server(second)")) o = s:option(Value, _n("timeout"), translate("Timeout for establishing a connection to server(second)"))
o.datatype = "uinteger" o.datatype = "uinteger"
o.default = "8" o.default = "8"
o.rmempty = true o.rmempty = true
o.rewrite_option = o.option o.rewrite_option = o.option
o = s:option(Value, option_name("gc_interval"), translate("Garbage collection interval(second)")) o = s:option(Value, _n("gc_interval"), translate("Garbage collection interval(second)"))
o.datatype = "uinteger" o.datatype = "uinteger"
o.default = "3" o.default = "3"
o.rmempty = true o.rmempty = true
o.rewrite_option = o.option o.rewrite_option = o.option
o = s:option(Value, option_name("gc_lifetime"), translate("Garbage collection lifetime(second)")) o = s:option(Value, _n("gc_lifetime"), translate("Garbage collection lifetime(second)"))
o.datatype = "uinteger" o.datatype = "uinteger"
o.default = "15" o.default = "15"
o.rmempty = true o.rmempty = true
o.rewrite_option = o.option o.rewrite_option = o.option
o = s:option(Value, option_name("send_window"), translate("TUIC send window")) o = s:option(Value, _n("send_window"), translate("TUIC send window"))
o.datatype = "uinteger" o.datatype = "uinteger"
o.default = 20971520 o.default = 20971520
o.rmempty = true o.rmempty = true
o.rewrite_option = o.option o.rewrite_option = o.option
o = s:option(Value, option_name("receive_window"), translate("TUIC receive window")) o = s:option(Value, _n("receive_window"), translate("TUIC receive window"))
o.datatype = "uinteger" o.datatype = "uinteger"
o.default = 10485760 o.default = 10485760
o.rmempty = true o.rmempty = true
o.rewrite_option = o.option o.rewrite_option = o.option
o = s:option(Value, option_name("max_package_size"), translate("TUIC Maximum packet size the socks5 server can receive from external, in bytes")) o = s:option(Value, _n("max_package_size"), translate("TUIC Maximum packet size the socks5 server can receive from external, in bytes"))
o.datatype = "uinteger" o.datatype = "uinteger"
o.default = 1500 o.default = 1500
o.rmempty = true o.rmempty = true
o.rewrite_option = o.option o.rewrite_option = o.option
--Tuic settings for the local inbound socks5 server --Tuic settings for the local inbound socks5 server
o = s:option(Flag, option_name("dual_stack"), translate("Set if the listening socket should be dual-stack")) o = s:option(Flag, _n("dual_stack"), translate("Set if the listening socket should be dual-stack"))
o.default = 0 o.default = 0
o.rmempty = true o.rmempty = true
o.rewrite_option = o.option o.rewrite_option = o.option
o = s:option(Flag, option_name("disable_sni"), translate("Disable SNI")) o = s:option(Flag, _n("disable_sni"), translate("Disable SNI"))
o.default = 0 o.default = 0
o.rmempty = true o.rmempty = true
o.rewrite_option = o.option o.rewrite_option = o.option
o = s:option(Flag, option_name("zero_rtt_handshake"), translate("Enable 0-RTT QUIC handshake")) o = s:option(Flag, _n("zero_rtt_handshake"), translate("Enable 0-RTT QUIC handshake"))
o.default = 0 o.default = 0
o.rmempty = true o.rmempty = true
o.rewrite_option = o.option o.rewrite_option = o.option
o = s:option(DynamicList, option_name("tls_alpn"), translate("TLS ALPN")) o = s:option(DynamicList, _n("tls_alpn"), translate("TLS ALPN"))
o.rmempty = true o.rmempty = true
o.rewrite_option = o.option o.rewrite_option = o.option

View File

@ -10,7 +10,7 @@ local type_name = "Hysteria2"
local option_prefix = "hysteria2_" local option_prefix = "hysteria2_"
local function option_name(name) local function _n(name)
return option_prefix .. name return option_prefix .. name
end end
@ -18,31 +18,31 @@ end
s.fields["type"]:value(type_name, "Hysteria2") s.fields["type"]:value(type_name, "Hysteria2")
o = s:option(Value, option_name("port"), translate("Listen Port")) o = s:option(Value, _n("port"), translate("Listen Port"))
o.datatype = "port" o.datatype = "port"
o = s:option(Value, option_name("obfs"), translate("Obfs Password")) o = s:option(Value, _n("obfs"), translate("Obfs Password"))
o.rewrite_option = o.option o.rewrite_option = o.option
o = s:option(Value, option_name("auth_password"), translate("Auth Password")) o = s:option(Value, _n("auth_password"), translate("Auth Password"))
o.password = true o.password = true
o.rewrite_option = o.option o.rewrite_option = o.option
o = s:option(Flag, option_name("udp"), translate("UDP")) o = s:option(Flag, _n("udp"), translate("UDP"))
o.default = "1" o.default = "1"
o.rewrite_option = o.option o.rewrite_option = o.option
o = s:option(Value, option_name("up_mbps"), translate("Max upload Mbps")) o = s:option(Value, _n("up_mbps"), translate("Max upload Mbps"))
o.rewrite_option = o.option o.rewrite_option = o.option
o = s:option(Value, option_name("down_mbps"), translate("Max download Mbps")) o = s:option(Value, _n("down_mbps"), translate("Max download Mbps"))
o.rewrite_option = o.option o.rewrite_option = o.option
o = s:option(Flag, option_name("ignoreClientBandwidth"), translate("ignoreClientBandwidth")) o = s:option(Flag, _n("ignoreClientBandwidth"), translate("ignoreClientBandwidth"))
o.default = "0" o.default = "0"
o.rewrite_option = o.option o.rewrite_option = o.option
o = s:option(FileUpload, option_name("tls_certificateFile"), translate("Public key absolute path"), translate("as:") .. "/etc/ssl/fullchain.pem") o = s:option(FileUpload, _n("tls_certificateFile"), translate("Public key absolute path"), translate("as:") .. "/etc/ssl/fullchain.pem")
o.default = m:get(s.section, "tls_certificateFile") or "/etc/config/ssl/" .. arg[1] .. ".pem" o.default = m:get(s.section, "tls_certificateFile") or "/etc/config/ssl/" .. arg[1] .. ".pem"
o.validate = function(self, value, t) o.validate = function(self, value, t)
if value and value ~= "" then if value and value ~= "" then
@ -55,7 +55,7 @@ o.validate = function(self, value, t)
return nil return nil
end end
o = s:option(FileUpload, option_name("tls_keyFile"), translate("Private key absolute path"), translate("as:") .. "/etc/ssl/private.key") o = s:option(FileUpload, _n("tls_keyFile"), translate("Private key absolute path"), translate("as:") .. "/etc/ssl/private.key")
o.default = m:get(s.section, "tls_keyFile") or "/etc/config/ssl/" .. arg[1] .. ".key" o.default = m:get(s.section, "tls_keyFile") or "/etc/config/ssl/" .. arg[1] .. ".key"
o.validate = function(self, value, t) o.validate = function(self, value, t)
if value and value ~= "" then if value and value ~= "" then
@ -68,7 +68,7 @@ o.validate = function(self, value, t)
return nil return nil
end end
o = s:option(Flag, option_name("log"), translate("Log")) o = s:option(Flag, _n("log"), translate("Log"))
o.default = "1" o.default = "1"
o.rmempty = false o.rmempty = false

View File

@ -10,7 +10,7 @@ local type_name = "Xray"
local option_prefix = "xray_" local option_prefix = "xray_"
local function option_name(name) local function _n(name)
return option_prefix .. name return option_prefix .. name
end end
@ -26,7 +26,7 @@ local header_type_list = {
s.fields["type"]:value(type_name, "Xray") s.fields["type"]:value(type_name, "Xray")
o = s:option(ListValue, option_name("protocol"), translate("Protocol")) o = s:option(ListValue, _n("protocol"), translate("Protocol"))
o:value("vmess", "Vmess") o:value("vmess", "Vmess")
o:value("vless", "VLESS") o:value("vless", "VLESS")
o:value("http", "HTTP") o:value("http", "HTTP")
@ -35,91 +35,91 @@ o:value("shadowsocks", "Shadowsocks")
o:value("trojan", "Trojan") o:value("trojan", "Trojan")
o:value("dokodemo-door", "dokodemo-door") o:value("dokodemo-door", "dokodemo-door")
o = s:option(Value, option_name("port"), translate("Listen Port")) o = s:option(Value, _n("port"), translate("Listen Port"))
o.datatype = "port" o.datatype = "port"
o = s:option(Flag, option_name("auth"), translate("Auth")) o = s:option(Flag, _n("auth"), translate("Auth"))
o.validate = function(self, value, t) o.validate = function(self, value, t)
if value and value == "1" then if value and value == "1" then
local user_v = s.fields[option_name("username")] and s.fields[option_name("username")]:formvalue(t) or "" local user_v = s.fields[_n("username")] and s.fields[_n("username")]:formvalue(t) or ""
local pass_v = s.fields[option_name("password")] and s.fields[option_name("password")]:formvalue(t) or "" local pass_v = s.fields[_n("password")] and s.fields[_n("password")]:formvalue(t) or ""
if user_v == "" or pass_v == "" then if user_v == "" or pass_v == "" then
return nil, translate("Username and Password must be used together!") return nil, translate("Username and Password must be used together!")
end end
end end
return value return value
end end
o:depends({ [option_name("protocol")] = "socks" }) o:depends({ [_n("protocol")] = "socks" })
o:depends({ [option_name("protocol")] = "http" }) o:depends({ [_n("protocol")] = "http" })
o = s:option(Value, option_name("username"), translate("Username")) o = s:option(Value, _n("username"), translate("Username"))
o:depends({ [option_name("auth")] = true }) o:depends({ [_n("auth")] = true })
o = s:option(Value, option_name("password"), translate("Password")) o = s:option(Value, _n("password"), translate("Password"))
o.password = true o.password = true
o:depends({ [option_name("auth")] = true }) o:depends({ [_n("auth")] = true })
o:depends({ [option_name("protocol")] = "shadowsocks" }) o:depends({ [_n("protocol")] = "shadowsocks" })
o = s:option(ListValue, option_name("d_protocol"), translate("Destination protocol")) o = s:option(ListValue, _n("d_protocol"), translate("Destination protocol"))
o:value("tcp", "TCP") o:value("tcp", "TCP")
o:value("udp", "UDP") o:value("udp", "UDP")
o:value("tcp,udp", "TCP,UDP") o:value("tcp,udp", "TCP,UDP")
o:depends({ [option_name("protocol")] = "dokodemo-door" }) o:depends({ [_n("protocol")] = "dokodemo-door" })
o = s:option(Value, option_name("d_address"), translate("Destination address")) o = s:option(Value, _n("d_address"), translate("Destination address"))
o:depends({ [option_name("protocol")] = "dokodemo-door" }) o:depends({ [_n("protocol")] = "dokodemo-door" })
o = s:option(Value, option_name("d_port"), translate("Destination port")) o = s:option(Value, _n("d_port"), translate("Destination port"))
o.datatype = "port" o.datatype = "port"
o:depends({ [option_name("protocol")] = "dokodemo-door" }) o:depends({ [_n("protocol")] = "dokodemo-door" })
o = s:option(Value, option_name("decryption"), translate("Encrypt Method")) o = s:option(Value, _n("decryption"), translate("Encrypt Method"))
o.default = "none" o.default = "none"
o:depends({ [option_name("protocol")] = "vless" }) o:depends({ [_n("protocol")] = "vless" })
o = s:option(ListValue, option_name("x_ss_method"), translate("Encrypt Method")) o = s:option(ListValue, _n("x_ss_method"), translate("Encrypt Method"))
o.rewrite_option = "method" o.rewrite_option = "method"
for a, t in ipairs(x_ss_method_list) do o:value(t) end for a, t in ipairs(x_ss_method_list) do o:value(t) end
o:depends({ [option_name("protocol")] = "shadowsocks" }) o:depends({ [_n("protocol")] = "shadowsocks" })
o = s:option(Flag, option_name("iv_check"), translate("IV Check")) o = s:option(Flag, _n("iv_check"), translate("IV Check"))
o:depends({ [option_name("protocol")] = "shadowsocks" }) o:depends({ [_n("protocol")] = "shadowsocks" })
o = s:option(ListValue, option_name("ss_network"), translate("Transport")) o = s:option(ListValue, _n("ss_network"), translate("Transport"))
o.default = "tcp,udp" o.default = "tcp,udp"
o:value("tcp", "TCP") o:value("tcp", "TCP")
o:value("udp", "UDP") o:value("udp", "UDP")
o:value("tcp,udp", "TCP,UDP") o:value("tcp,udp", "TCP,UDP")
o:depends({ [option_name("protocol")] = "shadowsocks" }) o:depends({ [_n("protocol")] = "shadowsocks" })
o = s:option(Flag, option_name("udp_forward"), translate("UDP Forward")) o = s:option(Flag, _n("udp_forward"), translate("UDP Forward"))
o.default = "1" o.default = "1"
o.rmempty = false o.rmempty = false
o:depends({ [option_name("protocol")] = "socks" }) o:depends({ [_n("protocol")] = "socks" })
o = s:option(DynamicList, option_name("uuid"), translate("ID") .. "/" .. translate("Password")) o = s:option(DynamicList, _n("uuid"), translate("ID") .. "/" .. translate("Password"))
for i = 1, 3 do for i = 1, 3 do
o:value(api.gen_uuid(1)) o:value(api.gen_uuid(1))
end end
o:depends({ [option_name("protocol")] = "vmess" }) o:depends({ [_n("protocol")] = "vmess" })
o:depends({ [option_name("protocol")] = "vless" }) o:depends({ [_n("protocol")] = "vless" })
o:depends({ [option_name("protocol")] = "trojan" }) o:depends({ [_n("protocol")] = "trojan" })
o = s:option(ListValue, option_name("flow"), translate("flow")) o = s:option(ListValue, _n("flow"), translate("flow"))
o.default = "" o.default = ""
o:value("", translate("Disable")) o:value("", translate("Disable"))
o:value("xtls-rprx-vision") o:value("xtls-rprx-vision")
o:depends({ [option_name("protocol")] = "vless", [option_name("tls")] = true, [option_name("transport")] = "raw" }) o:depends({ [_n("protocol")] = "vless", [_n("tls")] = true, [_n("transport")] = "raw" })
o = s:option(Flag, option_name("tls"), translate("TLS")) o = s:option(Flag, _n("tls"), translate("TLS"))
o.default = 0 o.default = 0
o.validate = function(self, value, t) o.validate = function(self, value, t)
if value then if value then
local reality = s.fields[option_name("reality")] and s.fields[option_name("reality")]:formvalue(t) or nil local reality = s.fields[_n("reality")] and s.fields[_n("reality")]:formvalue(t) or nil
if reality and reality == "1" then return value end if reality and reality == "1" then return value end
if value == "1" then if value == "1" then
local ca = s.fields[option_name("tls_certificateFile")] and s.fields[option_name("tls_certificateFile")]:formvalue(t) or "" local ca = s.fields[_n("tls_certificateFile")] and s.fields[_n("tls_certificateFile")]:formvalue(t) or ""
local key = s.fields[option_name("tls_keyFile")] and s.fields[option_name("tls_keyFile")]:formvalue(t) or "" local key = s.fields[_n("tls_keyFile")] and s.fields[_n("tls_keyFile")]:formvalue(t) or ""
if ca == "" or key == "" then if ca == "" or key == "" then
return nil, translate("Public key and Private key path can not be empty!") return nil, translate("Public key and Private key path can not be empty!")
end end
@ -127,32 +127,32 @@ o.validate = function(self, value, t)
return value return value
end end
end end
o:depends({ [option_name("protocol")] = "vmess" }) o:depends({ [_n("protocol")] = "vmess" })
o:depends({ [option_name("protocol")] = "vless" }) o:depends({ [_n("protocol")] = "vless" })
o:depends({ [option_name("protocol")] = "http" }) o:depends({ [_n("protocol")] = "http" })
o:depends({ [option_name("protocol")] = "socks" }) o:depends({ [_n("protocol")] = "socks" })
o:depends({ [option_name("protocol")] = "shadowsocks" }) o:depends({ [_n("protocol")] = "shadowsocks" })
o:depends({ [option_name("protocol")] = "trojan" }) o:depends({ [_n("protocol")] = "trojan" })
-- [[ REALITY部分 ]] -- -- [[ REALITY部分 ]] --
o = s:option(Flag, option_name("reality"), translate("REALITY")) o = s:option(Flag, _n("reality"), translate("REALITY"))
o.default = 0 o.default = 0
o:depends({ [option_name("tls")] = true }) o:depends({ [_n("tls")] = true })
o = s:option(Value, option_name("reality_private_key"), translate("Private Key")) o = s:option(Value, _n("reality_private_key"), translate("Private Key"))
o:depends({ [option_name("reality")] = true }) o:depends({ [_n("reality")] = true })
o = s:option(DynamicList, option_name("reality_shortId"), translate("Short Id")) o = s:option(DynamicList, _n("reality_shortId"), translate("Short Id"))
o:depends({ [option_name("reality")] = true }) o:depends({ [_n("reality")] = true })
o = s:option(Value, option_name("reality_dest"), translate("Dest")) o = s:option(Value, _n("reality_dest"), translate("Dest"))
o.default = "google.com:443" o.default = "google.com:443"
o:depends({ [option_name("reality")] = true }) o:depends({ [_n("reality")] = true })
o = s:option(Value, option_name("reality_serverNames"), translate("serverNames")) o = s:option(Value, _n("reality_serverNames"), translate("serverNames"))
o:depends({ [option_name("reality")] = true }) o:depends({ [_n("reality")] = true })
o = s:option(ListValue, option_name("alpn"), translate("alpn")) o = s:option(ListValue, _n("alpn"), translate("alpn"))
o.default = "h2,http/1.1" o.default = "h2,http/1.1"
o:value("h3,h2,http/1.1") o:value("h3,h2,http/1.1")
o:value("h3,h2") o:value("h3,h2")
@ -160,17 +160,17 @@ o:value("h2,http/1.1")
o:value("h3") o:value("h3")
o:value("h2") o:value("h2")
o:value("http/1.1") o:value("http/1.1")
o:depends({ [option_name("tls")] = true }) o:depends({ [_n("tls")] = true })
-- o = s:option(Value, option_name("minversion"), translate("minversion")) -- o = s:option(Value, _n("minversion"), translate("minversion"))
-- o.default = "1.3" -- o.default = "1.3"
-- o:value("1.3") -- o:value("1.3")
--o:depends({ [option_name("tls")] = true }) --o:depends({ [_n("tls")] = true })
-- [[ TLS部分 ]] -- -- [[ TLS部分 ]] --
o = s:option(FileUpload, option_name("tls_certificateFile"), translate("Public key absolute path"), translate("as:") .. "/etc/ssl/fullchain.pem") o = s:option(FileUpload, _n("tls_certificateFile"), translate("Public key absolute path"), translate("as:") .. "/etc/ssl/fullchain.pem")
o.default = m:get(s.section, "tls_certificateFile") or "/etc/config/ssl/" .. arg[1] .. ".pem" o.default = m:get(s.section, "tls_certificateFile") or "/etc/config/ssl/" .. arg[1] .. ".pem"
o:depends({ [option_name("tls")] = true, [option_name("reality")] = false }) o:depends({ [_n("tls")] = true, [_n("reality")] = false })
o.validate = function(self, value, t) o.validate = function(self, value, t)
if value and value ~= "" then if value and value ~= "" then
if not nixio.fs.access(value) then if not nixio.fs.access(value) then
@ -182,9 +182,9 @@ o.validate = function(self, value, t)
return nil return nil
end end
o = s:option(FileUpload, option_name("tls_keyFile"), translate("Private key absolute path"), translate("as:") .. "/etc/ssl/private.key") o = s:option(FileUpload, _n("tls_keyFile"), translate("Private key absolute path"), translate("as:") .. "/etc/ssl/private.key")
o.default = m:get(s.section, "tls_keyFile") or "/etc/config/ssl/" .. arg[1] .. ".key" o.default = m:get(s.section, "tls_keyFile") or "/etc/config/ssl/" .. arg[1] .. ".key"
o:depends({ [option_name("tls")] = true, [option_name("reality")] = false }) o:depends({ [_n("tls")] = true, [_n("reality")] = false })
o.validate = function(self, value, t) o.validate = function(self, value, t)
if value and value ~= "" then if value and value ~= "" then
if not nixio.fs.access(value) then if not nixio.fs.access(value) then
@ -196,7 +196,7 @@ o.validate = function(self, value, t)
return nil return nil
end end
o = s:option(ListValue, option_name("transport"), translate("Transport")) o = s:option(ListValue, _n("transport"), translate("Transport"))
o:value("raw", "RAW") o:value("raw", "RAW")
o:value("mkcp", "mKCP") o:value("mkcp", "mKCP")
o:value("ws", "WebSocket") o:value("ws", "WebSocket")
@ -206,161 +206,161 @@ o:value("quic", "QUIC")
o:value("grpc", "gRPC") o:value("grpc", "gRPC")
o:value("httpupgrade", "HttpUpgrade") o:value("httpupgrade", "HttpUpgrade")
o:value("xhttp", "XHTTP") o:value("xhttp", "XHTTP")
o:depends({ [option_name("protocol")] = "vmess" }) o:depends({ [_n("protocol")] = "vmess" })
o:depends({ [option_name("protocol")] = "vless" }) o:depends({ [_n("protocol")] = "vless" })
o:depends({ [option_name("protocol")] = "socks" }) o:depends({ [_n("protocol")] = "socks" })
o:depends({ [option_name("protocol")] = "shadowsocks" }) o:depends({ [_n("protocol")] = "shadowsocks" })
o:depends({ [option_name("protocol")] = "trojan" }) o:depends({ [_n("protocol")] = "trojan" })
-- [[ WebSocket部分 ]]-- -- [[ WebSocket部分 ]]--
o = s:option(Value, option_name("ws_host"), translate("WebSocket Host")) o = s:option(Value, _n("ws_host"), translate("WebSocket Host"))
o:depends({ [option_name("transport")] = "ws" }) o:depends({ [_n("transport")] = "ws" })
o = s:option(Value, option_name("ws_path"), translate("WebSocket Path")) o = s:option(Value, _n("ws_path"), translate("WebSocket Path"))
o:depends({ [option_name("transport")] = "ws" }) o:depends({ [_n("transport")] = "ws" })
-- [[ HttpUpgrade部分 ]]-- -- [[ HttpUpgrade部分 ]]--
o = s:option(Value, option_name("httpupgrade_host"), translate("HttpUpgrade Host")) o = s:option(Value, _n("httpupgrade_host"), translate("HttpUpgrade Host"))
o:depends({ [option_name("transport")] = "httpupgrade" }) o:depends({ [_n("transport")] = "httpupgrade" })
o = s:option(Value, option_name("httpupgrade_path"), translate("HttpUpgrade Path")) o = s:option(Value, _n("httpupgrade_path"), translate("HttpUpgrade Path"))
o.placeholder = "/" o.placeholder = "/"
o:depends({ [option_name("transport")] = "httpupgrade" }) o:depends({ [_n("transport")] = "httpupgrade" })
-- [[ HTTP/2部分 ]]-- -- [[ HTTP/2部分 ]]--
o = s:option(Value, option_name("h2_host"), translate("HTTP/2 Host")) o = s:option(Value, _n("h2_host"), translate("HTTP/2 Host"))
o:depends({ [option_name("transport")] = "h2" }) o:depends({ [_n("transport")] = "h2" })
o = s:option(Value, option_name("h2_path"), translate("HTTP/2 Path")) o = s:option(Value, _n("h2_path"), translate("HTTP/2 Path"))
o:depends({ [option_name("transport")] = "h2" }) o:depends({ [_n("transport")] = "h2" })
-- [[ SplitHTTP部分 ]]-- -- [[ SplitHTTP部分 ]]--
o = s:option(Value, option_name("xhttp_host"), translate("XHTTP Host")) o = s:option(Value, _n("xhttp_host"), translate("XHTTP Host"))
o:depends({ [option_name("transport")] = "xhttp" }) o:depends({ [_n("transport")] = "xhttp" })
o = s:option(Value, option_name("xhttp_path"), translate("XHTTP Path")) o = s:option(Value, _n("xhttp_path"), translate("XHTTP Path"))
o.placeholder = "/" o.placeholder = "/"
o:depends({ [option_name("transport")] = "xhttp" }) o:depends({ [_n("transport")] = "xhttp" })
o = s:option(Value, option_name("xhttp_maxuploadsize"), translate("maxUploadSize")) o = s:option(Value, _n("xhttp_maxuploadsize"), translate("maxUploadSize"))
o.default = "1000000" o.default = "1000000"
o:depends({ [option_name("transport")] = "xhttp" }) o:depends({ [_n("transport")] = "xhttp" })
o = s:option(Value, option_name("xhttp_maxconcurrentuploads"), translate("maxConcurrentUploads")) o = s:option(Value, _n("xhttp_maxconcurrentuploads"), translate("maxConcurrentUploads"))
o.default = "10" o.default = "10"
o:depends({ [option_name("transport")] = "xhttp" }) o:depends({ [_n("transport")] = "xhttp" })
o = s:option(Value, option_name("splithttp_maxuploadsize"), translate("maxUploadSize")) o = s:option(Value, _n("splithttp_maxuploadsize"), translate("maxUploadSize"))
o.default = "1000000" o.default = "1000000"
o:depends({ [option_name("transport")] = "splithttp" }) o:depends({ [_n("transport")] = "splithttp" })
o = s:option(Value, option_name("splithttp_maxconcurrentuploads"), translate("maxConcurrentUploads")) o = s:option(Value, _n("splithttp_maxconcurrentuploads"), translate("maxConcurrentUploads"))
o.default = "10" o.default = "10"
o:depends({ [option_name("transport")] = "splithttp" }) o:depends({ [_n("transport")] = "splithttp" })
-- [[ TCP部分 ]]-- -- [[ TCP部分 ]]--
-- TCP伪装 -- TCP伪装
o = s:option(ListValue, option_name("tcp_guise"), translate("Camouflage Type")) o = s:option(ListValue, _n("tcp_guise"), translate("Camouflage Type"))
o:value("none", "none") o:value("none", "none")
o:value("http", "http") o:value("http", "http")
o:depends({ [option_name("transport")] = "raw" }) o:depends({ [_n("transport")] = "raw" })
-- HTTP域名 -- HTTP域名
o = s:option(DynamicList, option_name("tcp_guise_http_host"), translate("HTTP Host")) o = s:option(DynamicList, _n("tcp_guise_http_host"), translate("HTTP Host"))
o:depends({ [option_name("tcp_guise")] = "http" }) o:depends({ [_n("tcp_guise")] = "http" })
-- HTTP路径 -- HTTP路径
o = s:option(DynamicList, option_name("tcp_guise_http_path"), translate("HTTP Path")) o = s:option(DynamicList, _n("tcp_guise_http_path"), translate("HTTP Path"))
o:depends({ [option_name("tcp_guise")] = "http" }) o:depends({ [_n("tcp_guise")] = "http" })
-- [[ mKCP部分 ]]-- -- [[ mKCP部分 ]]--
o = s:option(ListValue, option_name("mkcp_guise"), translate("Camouflage Type"), translate('<br />none: default, no masquerade, data sent is packets with no characteristics.<br />srtp: disguised as an SRTP packet, it will be recognized as video call data (such as FaceTime).<br />utp: packets disguised as uTP will be recognized as bittorrent downloaded data.<br />wechat-video: packets disguised as WeChat video calls.<br />dtls: disguised as DTLS 1.2 packet.<br />wireguard: disguised as a WireGuard packet. (not really WireGuard protocol)')) o = s:option(ListValue, _n("mkcp_guise"), translate("Camouflage Type"), translate('<br />none: default, no masquerade, data sent is packets with no characteristics.<br />srtp: disguised as an SRTP packet, it will be recognized as video call data (such as FaceTime).<br />utp: packets disguised as uTP will be recognized as bittorrent downloaded data.<br />wechat-video: packets disguised as WeChat video calls.<br />dtls: disguised as DTLS 1.2 packet.<br />wireguard: disguised as a WireGuard packet. (not really WireGuard protocol)'))
for a, t in ipairs(header_type_list) do o:value(t) end for a, t in ipairs(header_type_list) do o:value(t) end
o:depends({ [option_name("transport")] = "mkcp" }) o:depends({ [_n("transport")] = "mkcp" })
o = s:option(Value, option_name("mkcp_mtu"), translate("KCP MTU")) o = s:option(Value, _n("mkcp_mtu"), translate("KCP MTU"))
o.default = "1350" o.default = "1350"
o:depends({ [option_name("transport")] = "mkcp" }) o:depends({ [_n("transport")] = "mkcp" })
o = s:option(Value, option_name("mkcp_tti"), translate("KCP TTI")) o = s:option(Value, _n("mkcp_tti"), translate("KCP TTI"))
o.default = "20" o.default = "20"
o:depends({ [option_name("transport")] = "mkcp" }) o:depends({ [_n("transport")] = "mkcp" })
o = s:option(Value, option_name("mkcp_uplinkCapacity"), translate("KCP uplinkCapacity")) o = s:option(Value, _n("mkcp_uplinkCapacity"), translate("KCP uplinkCapacity"))
o.default = "5" o.default = "5"
o:depends({ [option_name("transport")] = "mkcp" }) o:depends({ [_n("transport")] = "mkcp" })
o = s:option(Value, option_name("mkcp_downlinkCapacity"), translate("KCP downlinkCapacity")) o = s:option(Value, _n("mkcp_downlinkCapacity"), translate("KCP downlinkCapacity"))
o.default = "20" o.default = "20"
o:depends({ [option_name("transport")] = "mkcp" }) o:depends({ [_n("transport")] = "mkcp" })
o = s:option(Flag, option_name("mkcp_congestion"), translate("KCP Congestion")) o = s:option(Flag, _n("mkcp_congestion"), translate("KCP Congestion"))
o:depends({ [option_name("transport")] = "mkcp" }) o:depends({ [_n("transport")] = "mkcp" })
o = s:option(Value, option_name("mkcp_readBufferSize"), translate("KCP readBufferSize")) o = s:option(Value, _n("mkcp_readBufferSize"), translate("KCP readBufferSize"))
o.default = "1" o.default = "1"
o:depends({ [option_name("transport")] = "mkcp" }) o:depends({ [_n("transport")] = "mkcp" })
o = s:option(Value, option_name("mkcp_writeBufferSize"), translate("KCP writeBufferSize")) o = s:option(Value, _n("mkcp_writeBufferSize"), translate("KCP writeBufferSize"))
o.default = "1" o.default = "1"
o:depends({ [option_name("transport")] = "mkcp" }) o:depends({ [_n("transport")] = "mkcp" })
o = s:option(Value, option_name("mkcp_seed"), translate("KCP Seed")) o = s:option(Value, _n("mkcp_seed"), translate("KCP Seed"))
o:depends({ [option_name("transport")] = "mkcp" }) o:depends({ [_n("transport")] = "mkcp" })
-- [[ DomainSocket部分 ]]-- -- [[ DomainSocket部分 ]]--
o = s:option(Value, option_name("ds_path"), "Path", translate("A legal file path. This file must not exist before running.")) o = s:option(Value, _n("ds_path"), "Path", translate("A legal file path. This file must not exist before running."))
o:depends({ [option_name("transport")] = "ds" }) o:depends({ [_n("transport")] = "ds" })
-- [[ QUIC部分 ]]-- -- [[ QUIC部分 ]]--
o = s:option(ListValue, option_name("quic_security"), translate("Encrypt Method")) o = s:option(ListValue, _n("quic_security"), translate("Encrypt Method"))
o:value("none") o:value("none")
o:value("aes-128-gcm") o:value("aes-128-gcm")
o:value("chacha20-poly1305") o:value("chacha20-poly1305")
o:depends({ [option_name("transport")] = "quic" }) o:depends({ [_n("transport")] = "quic" })
o = s:option(Value, option_name("quic_key"), translate("Encrypt Method") .. translate("Key")) o = s:option(Value, _n("quic_key"), translate("Encrypt Method") .. translate("Key"))
o:depends({ [option_name("transport")] = "quic" }) o:depends({ [_n("transport")] = "quic" })
o = s:option(ListValue, option_name("quic_guise"), translate("Camouflage Type")) o = s:option(ListValue, _n("quic_guise"), translate("Camouflage Type"))
for a, t in ipairs(header_type_list) do o:value(t) end for a, t in ipairs(header_type_list) do o:value(t) end
o:depends({ [option_name("transport")] = "quic" }) o:depends({ [_n("transport")] = "quic" })
-- [[ gRPC部分 ]]-- -- [[ gRPC部分 ]]--
o = s:option(Value, option_name("grpc_serviceName"), "ServiceName") o = s:option(Value, _n("grpc_serviceName"), "ServiceName")
o:depends({ [option_name("transport")] = "grpc" }) o:depends({ [_n("transport")] = "grpc" })
o = s:option(Flag, option_name("acceptProxyProtocol"), translate("acceptProxyProtocol"), translate("Whether to receive PROXY protocol, when this node want to be fallback or forwarded by proxy, it must be enable, otherwise it cannot be used.")) o = s:option(Flag, _n("acceptProxyProtocol"), translate("acceptProxyProtocol"), translate("Whether to receive PROXY protocol, when this node want to be fallback or forwarded by proxy, it must be enable, otherwise it cannot be used."))
o.default = "0" o.default = "0"
-- [[ Fallback部分 ]]-- -- [[ Fallback部分 ]]--
o = s:option(Flag, option_name("fallback"), translate("Fallback")) o = s:option(Flag, _n("fallback"), translate("Fallback"))
o:depends({ [option_name("protocol")] = "vless", [option_name("transport")] = "raw" }) o:depends({ [_n("protocol")] = "vless", [_n("transport")] = "raw" })
o:depends({ [option_name("protocol")] = "trojan", [option_name("transport")] = "raw" }) o:depends({ [_n("protocol")] = "trojan", [_n("transport")] = "raw" })
--[[ --[[
o = s:option(Value, option_name("fallback_alpn"), "Fallback alpn") o = s:option(Value, _n("fallback_alpn"), "Fallback alpn")
o:depends({ [option_name("fallback")] = true }) o:depends({ [_n("fallback")] = true })
o = s:option(Value, option_name("fallback_path"), "Fallback path") o = s:option(Value, _n("fallback_path"), "Fallback path")
o:depends({ [option_name("fallback")] = true }) o:depends({ [_n("fallback")] = true })
o = s:option(Value, option_name("fallback_dest"), "Fallback dest") o = s:option(Value, _n("fallback_dest"), "Fallback dest")
o:depends({ [option_name("fallback")] = true }) o:depends({ [_n("fallback")] = true })
o = s:option(Value, option_name("fallback_xver"), "Fallback xver") o = s:option(Value, _n("fallback_xver"), "Fallback xver")
o.default = 0 o.default = 0
o:depends({ [option_name("fallback")] = true }) o:depends({ [_n("fallback")] = true })
]]-- ]]--
o = s:option(DynamicList, option_name("fallback_list"), "Fallback", translate("dest,path")) o = s:option(DynamicList, _n("fallback_list"), "Fallback", translate("dest,path"))
o:depends({ [option_name("fallback")] = true }) o:depends({ [_n("fallback")] = true })
o = s:option(Flag, option_name("bind_local"), translate("Bind Local"), translate("When selected, it can only be accessed localhost.")) o = s:option(Flag, _n("bind_local"), translate("Bind Local"), translate("When selected, it can only be accessed localhost."))
o.default = "0" o.default = "0"
o = s:option(Flag, option_name("accept_lan"), translate("Accept LAN Access"), translate("When selected, it can accessed lan , this will not be safe!")) o = s:option(Flag, _n("accept_lan"), translate("Accept LAN Access"), translate("When selected, it can accessed lan , this will not be safe!"))
o.default = "0" o.default = "0"
local nodes_table = {} local nodes_table = {}
@ -373,46 +373,45 @@ for k, e in ipairs(api.get_valid_nodes()) do
end end
end end
o = s:option(ListValue, option_name("outbound_node"), translate("outbound node")) o = s:option(ListValue, _n("outbound_node"), translate("outbound node"))
o:value("nil", translate("Close")) o:value("", translate("Close"))
o:value("_socks", translate("Custom Socks")) o:value("_socks", translate("Custom Socks"))
o:value("_http", translate("Custom HTTP")) o:value("_http", translate("Custom HTTP"))
o:value("_iface", translate("Custom Interface")) o:value("_iface", translate("Custom Interface"))
for k, v in pairs(nodes_table) do o:value(v.id, v.remarks) end for k, v in pairs(nodes_table) do o:value(v.id, v.remarks) end
o.default = "nil"
o = s:option(Value, option_name("outbound_node_address"), translate("Address (Support Domain Name)")) o = s:option(Value, _n("outbound_node_address"), translate("Address (Support Domain Name)"))
o:depends({ [option_name("outbound_node")] = "_socks"}) o:depends({ [_n("outbound_node")] = "_socks"})
o:depends({ [option_name("outbound_node")] = "_http"}) o:depends({ [_n("outbound_node")] = "_http"})
o = s:option(Value, option_name("outbound_node_port"), translate("Port")) o = s:option(Value, _n("outbound_node_port"), translate("Port"))
o.datatype = "port" o.datatype = "port"
o:depends({ [option_name("outbound_node")] = "_socks"}) o:depends({ [_n("outbound_node")] = "_socks"})
o:depends({ [option_name("outbound_node")] = "_http"}) o:depends({ [_n("outbound_node")] = "_http"})
o = s:option(Value, option_name("outbound_node_username"), translate("Username")) o = s:option(Value, _n("outbound_node_username"), translate("Username"))
o:depends({ [option_name("outbound_node")] = "_socks"}) o:depends({ [_n("outbound_node")] = "_socks"})
o:depends({ [option_name("outbound_node")] = "_http"}) o:depends({ [_n("outbound_node")] = "_http"})
o = s:option(Value, option_name("outbound_node_password"), translate("Password")) o = s:option(Value, _n("outbound_node_password"), translate("Password"))
o.password = true o.password = true
o:depends({ [option_name("outbound_node")] = "_socks"}) o:depends({ [_n("outbound_node")] = "_socks"})
o:depends({ [option_name("outbound_node")] = "_http"}) o:depends({ [_n("outbound_node")] = "_http"})
o = s:option(Value, option_name("outbound_node_iface"), translate("Interface")) o = s:option(Value, _n("outbound_node_iface"), translate("Interface"))
o.default = "eth1" o.default = "eth1"
o:depends({ [option_name("outbound_node")] = "_iface"}) o:depends({ [_n("outbound_node")] = "_iface"})
o = s:option(Flag, option_name("log"), translate("Log")) o = s:option(Flag, _n("log"), translate("Log"))
o.default = "1" o.default = "1"
o.rmempty = false o.rmempty = false
o = s:option(ListValue, option_name("loglevel"), translate("Log Level")) o = s:option(ListValue, _n("loglevel"), translate("Log Level"))
o.default = "warning" o.default = "warning"
o:value("debug") o:value("debug")
o:value("info") o:value("info")
o:value("warning") o:value("warning")
o:value("error") o:value("error")
o:depends({ [option_name("log")] = true }) o:depends({ [_n("log")] = true })
api.luci_types(arg[1], m, s, type_name, option_prefix) api.luci_types(arg[1], m, s, type_name, option_prefix)

View File

@ -14,7 +14,7 @@ local type_name = "sing-box"
local option_prefix = "singbox_" local option_prefix = "singbox_"
local function option_name(name) local function _n(name)
return option_prefix .. name return option_prefix .. name
end end
@ -27,7 +27,7 @@ local ss_method_list = {
s.fields["type"]:value(type_name, "Sing-Box") s.fields["type"]:value(type_name, "Sing-Box")
o = s:option(ListValue, option_name("protocol"), translate("Protocol")) o = s:option(ListValue, _n("protocol"), translate("Protocol"))
o:value("mixed", "Mixed") o:value("mixed", "Mixed")
o:value("socks", "Socks") o:value("socks", "Socks")
o:value("http", "HTTP") o:value("http", "HTTP")
@ -47,166 +47,166 @@ if singbox_tags:find("with_quic") then
end end
o:value("direct", "Direct") o:value("direct", "Direct")
o = s:option(Value, option_name("port"), translate("Listen Port")) o = s:option(Value, _n("port"), translate("Listen Port"))
o.datatype = "port" o.datatype = "port"
o = s:option(Flag, option_name("auth"), translate("Auth")) o = s:option(Flag, _n("auth"), translate("Auth"))
o.validate = function(self, value, t) o.validate = function(self, value, t)
if value and value == "1" then if value and value == "1" then
local user_v = s.fields[option_name("username")] and s.fields[option_name("username")]:formvalue(t) or "" local user_v = s.fields[_n("username")] and s.fields[_n("username")]:formvalue(t) or ""
local pass_v = s.fields[option_name("password")] and s.fields[option_name("password")]:formvalue(t) or "" local pass_v = s.fields[_n("password")] and s.fields[_n("password")]:formvalue(t) or ""
if user_v == "" or pass_v == "" then if user_v == "" or pass_v == "" then
return nil, translate("Username and Password must be used together!") return nil, translate("Username and Password must be used together!")
end end
end end
return value return value
end end
o:depends({ [option_name("protocol")] = "mixed" }) o:depends({ [_n("protocol")] = "mixed" })
o:depends({ [option_name("protocol")] = "socks" }) o:depends({ [_n("protocol")] = "socks" })
o:depends({ [option_name("protocol")] = "http" }) o:depends({ [_n("protocol")] = "http" })
o = s:option(Value, option_name("username"), translate("Username")) o = s:option(Value, _n("username"), translate("Username"))
o:depends({ [option_name("auth")] = true }) o:depends({ [_n("auth")] = true })
o:depends({ [option_name("protocol")] = "naive" }) o:depends({ [_n("protocol")] = "naive" })
o = s:option(Value, option_name("password"), translate("Password")) o = s:option(Value, _n("password"), translate("Password"))
o.password = true o.password = true
o:depends({ [option_name("auth")] = true }) o:depends({ [_n("auth")] = true })
o:depends({ [option_name("protocol")] = "shadowsocks" }) o:depends({ [_n("protocol")] = "shadowsocks" })
o:depends({ [option_name("protocol")] = "naive" }) o:depends({ [_n("protocol")] = "naive" })
o:depends({ [option_name("protocol")] = "tuic" }) o:depends({ [_n("protocol")] = "tuic" })
if singbox_tags:find("with_quic") then if singbox_tags:find("with_quic") then
o = s:option(Value, option_name("hysteria_up_mbps"), translate("Max upload Mbps")) o = s:option(Value, _n("hysteria_up_mbps"), translate("Max upload Mbps"))
o.default = "100" o.default = "100"
o:depends({ [option_name("protocol")] = "hysteria" }) o:depends({ [_n("protocol")] = "hysteria" })
o = s:option(Value, option_name("hysteria_down_mbps"), translate("Max download Mbps")) o = s:option(Value, _n("hysteria_down_mbps"), translate("Max download Mbps"))
o.default = "100" o.default = "100"
o:depends({ [option_name("protocol")] = "hysteria" }) o:depends({ [_n("protocol")] = "hysteria" })
o = s:option(Value, option_name("hysteria_obfs"), translate("Obfs Password")) o = s:option(Value, _n("hysteria_obfs"), translate("Obfs Password"))
o:depends({ [option_name("protocol")] = "hysteria" }) o:depends({ [_n("protocol")] = "hysteria" })
o = s:option(ListValue, option_name("hysteria_auth_type"), translate("Auth Type")) o = s:option(ListValue, _n("hysteria_auth_type"), translate("Auth Type"))
o:value("disable", translate("Disable")) o:value("disable", translate("Disable"))
o:value("string", translate("STRING")) o:value("string", translate("STRING"))
o:value("base64", translate("BASE64")) o:value("base64", translate("BASE64"))
o:depends({ [option_name("protocol")] = "hysteria" }) o:depends({ [_n("protocol")] = "hysteria" })
o = s:option(Value, option_name("hysteria_auth_password"), translate("Auth Password")) o = s:option(Value, _n("hysteria_auth_password"), translate("Auth Password"))
o.password = true o.password = true
o:depends({ [option_name("protocol")] = "hysteria", [option_name("hysteria_auth_type")] = "string"}) o:depends({ [_n("protocol")] = "hysteria", [_n("hysteria_auth_type")] = "string"})
o:depends({ [option_name("protocol")] = "hysteria", [option_name("hysteria_auth_type")] = "base64"}) o:depends({ [_n("protocol")] = "hysteria", [_n("hysteria_auth_type")] = "base64"})
o = s:option(Value, option_name("hysteria_recv_window_conn"), translate("QUIC stream receive window")) o = s:option(Value, _n("hysteria_recv_window_conn"), translate("QUIC stream receive window"))
o:depends({ [option_name("protocol")] = "hysteria" }) o:depends({ [_n("protocol")] = "hysteria" })
o = s:option(Value, option_name("hysteria_recv_window_client"), translate("QUIC connection receive window")) o = s:option(Value, _n("hysteria_recv_window_client"), translate("QUIC connection receive window"))
o:depends({ [option_name("protocol")] = "hysteria" }) o:depends({ [_n("protocol")] = "hysteria" })
o = s:option(Value, option_name("hysteria_max_conn_client"), translate("QUIC concurrent bidirectional streams")) o = s:option(Value, _n("hysteria_max_conn_client"), translate("QUIC concurrent bidirectional streams"))
o.default = "1024" o.default = "1024"
o:depends({ [option_name("protocol")] = "hysteria" }) o:depends({ [_n("protocol")] = "hysteria" })
o = s:option(Flag, option_name("hysteria_disable_mtu_discovery"), translate("Disable MTU detection")) o = s:option(Flag, _n("hysteria_disable_mtu_discovery"), translate("Disable MTU detection"))
o:depends({ [option_name("protocol")] = "hysteria" }) o:depends({ [_n("protocol")] = "hysteria" })
o = s:option(Value, option_name("hysteria_alpn"), translate("QUIC TLS ALPN")) o = s:option(Value, _n("hysteria_alpn"), translate("QUIC TLS ALPN"))
o:depends({ [option_name("protocol")] = "hysteria" }) o:depends({ [_n("protocol")] = "hysteria" })
end end
if singbox_tags:find("with_quic") then if singbox_tags:find("with_quic") then
o = s:option(ListValue, option_name("tuic_congestion_control"), translate("Congestion control algorithm")) o = s:option(ListValue, _n("tuic_congestion_control"), translate("Congestion control algorithm"))
o.default = "cubic" o.default = "cubic"
o:value("bbr", translate("BBR")) o:value("bbr", translate("BBR"))
o:value("cubic", translate("CUBIC")) o:value("cubic", translate("CUBIC"))
o:value("new_reno", translate("New Reno")) o:value("new_reno", translate("New Reno"))
o:depends({ [option_name("protocol")] = "tuic" }) o:depends({ [_n("protocol")] = "tuic" })
o = s:option(Flag, option_name("tuic_zero_rtt_handshake"), translate("Enable 0-RTT QUIC handshake")) o = s:option(Flag, _n("tuic_zero_rtt_handshake"), translate("Enable 0-RTT QUIC handshake"))
o.default = 0 o.default = 0
o:depends({ [option_name("protocol")] = "tuic" }) o:depends({ [_n("protocol")] = "tuic" })
o = s:option(Value, option_name("tuic_heartbeat"), translate("Heartbeat interval(second)")) o = s:option(Value, _n("tuic_heartbeat"), translate("Heartbeat interval(second)"))
o.datatype = "uinteger" o.datatype = "uinteger"
o.default = "3" o.default = "3"
o:depends({ [option_name("protocol")] = "tuic" }) o:depends({ [_n("protocol")] = "tuic" })
o = s:option(Value, option_name("tuic_alpn"), translate("QUIC TLS ALPN")) o = s:option(Value, _n("tuic_alpn"), translate("QUIC TLS ALPN"))
o:depends({ [option_name("protocol")] = "tuic" }) o:depends({ [_n("protocol")] = "tuic" })
end end
if singbox_tags:find("with_quic") then if singbox_tags:find("with_quic") then
o = s:option(Flag, option_name("hysteria2_ignore_client_bandwidth"), translate("Commands the client to use the BBR flow control algorithm")) o = s:option(Flag, _n("hysteria2_ignore_client_bandwidth"), translate("Commands the client to use the BBR flow control algorithm"))
o.default = 0 o.default = 0
o:depends({ [option_name("protocol")] = "hysteria2" }) o:depends({ [_n("protocol")] = "hysteria2" })
o = s:option(Value, option_name("hysteria2_up_mbps"), translate("Max upload Mbps")) o = s:option(Value, _n("hysteria2_up_mbps"), translate("Max upload Mbps"))
o:depends({ [option_name("protocol")] = "hysteria2", [option_name("hysteria2_ignore_client_bandwidth")] = false }) o:depends({ [_n("protocol")] = "hysteria2", [_n("hysteria2_ignore_client_bandwidth")] = false })
o = s:option(Value, option_name("hysteria2_down_mbps"), translate("Max download Mbps")) o = s:option(Value, _n("hysteria2_down_mbps"), translate("Max download Mbps"))
o:depends({ [option_name("protocol")] = "hysteria2", [option_name("hysteria2_ignore_client_bandwidth")] = false }) o:depends({ [_n("protocol")] = "hysteria2", [_n("hysteria2_ignore_client_bandwidth")] = false })
o = s:option(ListValue, option_name("hysteria2_obfs_type"), translate("Obfs Type")) o = s:option(ListValue, _n("hysteria2_obfs_type"), translate("Obfs Type"))
o:value("", translate("Disable")) o:value("", translate("Disable"))
o:value("salamander") o:value("salamander")
o:depends({ [option_name("protocol")] = "hysteria2" }) o:depends({ [_n("protocol")] = "hysteria2" })
o = s:option(Value, option_name("hysteria2_obfs_password"), translate("Obfs Password")) o = s:option(Value, _n("hysteria2_obfs_password"), translate("Obfs Password"))
o:depends({ [option_name("protocol")] = "hysteria2" }) o:depends({ [_n("protocol")] = "hysteria2" })
o = s:option(Value, option_name("hysteria2_auth_password"), translate("Auth Password")) o = s:option(Value, _n("hysteria2_auth_password"), translate("Auth Password"))
o.password = true o.password = true
o:depends({ [option_name("protocol")] = "hysteria2"}) o:depends({ [_n("protocol")] = "hysteria2"})
end end
o = s:option(ListValue, option_name("d_protocol"), translate("Destination protocol")) o = s:option(ListValue, _n("d_protocol"), translate("Destination protocol"))
o:value("tcp", "TCP") o:value("tcp", "TCP")
o:value("udp", "UDP") o:value("udp", "UDP")
o:value("tcp,udp", "TCP,UDP") o:value("tcp,udp", "TCP,UDP")
o:depends({ [option_name("protocol")] = "direct" }) o:depends({ [_n("protocol")] = "direct" })
o = s:option(Value, option_name("d_address"), translate("Destination address")) o = s:option(Value, _n("d_address"), translate("Destination address"))
o:depends({ [option_name("protocol")] = "direct" }) o:depends({ [_n("protocol")] = "direct" })
o = s:option(Value, option_name("d_port"), translate("Destination port")) o = s:option(Value, _n("d_port"), translate("Destination port"))
o.datatype = "port" o.datatype = "port"
o:depends({ [option_name("protocol")] = "direct" }) o:depends({ [_n("protocol")] = "direct" })
o = s:option(Value, option_name("decryption"), translate("Encrypt Method")) o = s:option(Value, _n("decryption"), translate("Encrypt Method"))
o.default = "none" o.default = "none"
o:depends({ [option_name("protocol")] = "vless" }) o:depends({ [_n("protocol")] = "vless" })
o = s:option(ListValue, option_name("ss_method"), translate("Encrypt Method")) o = s:option(ListValue, _n("ss_method"), translate("Encrypt Method"))
o.rewrite_option = "method" o.rewrite_option = "method"
for a, t in ipairs(ss_method_list) do o:value(t) end for a, t in ipairs(ss_method_list) do o:value(t) end
o:depends({ [option_name("protocol")] = "shadowsocks" }) o:depends({ [_n("protocol")] = "shadowsocks" })
o = s:option(DynamicList, option_name("uuid"), translate("ID") .. "/" .. translate("Password")) o = s:option(DynamicList, _n("uuid"), translate("ID") .. "/" .. translate("Password"))
for i = 1, 3 do for i = 1, 3 do
o:value(api.gen_uuid(1)) o:value(api.gen_uuid(1))
end end
o:depends({ [option_name("protocol")] = "vmess" }) o:depends({ [_n("protocol")] = "vmess" })
o:depends({ [option_name("protocol")] = "vless" }) o:depends({ [_n("protocol")] = "vless" })
o:depends({ [option_name("protocol")] = "trojan" }) o:depends({ [_n("protocol")] = "trojan" })
o:depends({ [option_name("protocol")] = "tuic" }) o:depends({ [_n("protocol")] = "tuic" })
o = s:option(ListValue, option_name("flow"), translate("flow")) o = s:option(ListValue, _n("flow"), translate("flow"))
o.default = "" o.default = ""
o:value("", translate("Disable")) o:value("", translate("Disable"))
o:value("xtls-rprx-vision") o:value("xtls-rprx-vision")
o:depends({ [option_name("protocol")] = "vless" }) o:depends({ [_n("protocol")] = "vless" })
o = s:option(Flag, option_name("tls"), translate("TLS")) o = s:option(Flag, _n("tls"), translate("TLS"))
o.default = 0 o.default = 0
o.validate = function(self, value, t) o.validate = function(self, value, t)
if value then if value then
local reality = s.fields[option_name("reality")] and s.fields[option_name("reality")]:formvalue(t) or nil local reality = s.fields[_n("reality")] and s.fields[_n("reality")]:formvalue(t) or nil
if reality and reality == "1" then return value end if reality and reality == "1" then return value end
if value == "1" then if value == "1" then
local ca = s.fields[option_name("tls_certificateFile")] and s.fields[option_name("tls_certificateFile")]:formvalue(t) or "" local ca = s.fields[_n("tls_certificateFile")] and s.fields[_n("tls_certificateFile")]:formvalue(t) or ""
local key = s.fields[option_name("tls_keyFile")] and s.fields[option_name("tls_keyFile")]:formvalue(t) or "" local key = s.fields[_n("tls_keyFile")] and s.fields[_n("tls_keyFile")]:formvalue(t) or ""
if ca == "" or key == "" then if ca == "" or key == "" then
return nil, translate("Public key and Private key path can not be empty!") return nil, translate("Public key and Private key path can not be empty!")
end end
@ -214,45 +214,45 @@ o.validate = function(self, value, t)
return value return value
end end
end end
o:depends({ [option_name("protocol")] = "http" }) o:depends({ [_n("protocol")] = "http" })
o:depends({ [option_name("protocol")] = "vmess" }) o:depends({ [_n("protocol")] = "vmess" })
o:depends({ [option_name("protocol")] = "vless" }) o:depends({ [_n("protocol")] = "vless" })
o:depends({ [option_name("protocol")] = "trojan" }) o:depends({ [_n("protocol")] = "trojan" })
if singbox_tags:find("with_reality_server") then if singbox_tags:find("with_reality_server") then
-- [[ REALITY部分 ]] -- -- [[ REALITY部分 ]] --
o = s:option(Flag, option_name("reality"), translate("REALITY")) o = s:option(Flag, _n("reality"), translate("REALITY"))
o.default = 0 o.default = 0
o:depends({ [option_name("protocol")] = "http", [option_name("tls")] = true }) o:depends({ [_n("protocol")] = "http", [_n("tls")] = true })
o:depends({ [option_name("protocol")] = "vmess", [option_name("tls")] = true }) o:depends({ [_n("protocol")] = "vmess", [_n("tls")] = true })
o:depends({ [option_name("protocol")] = "vless", [option_name("tls")] = true }) o:depends({ [_n("protocol")] = "vless", [_n("tls")] = true })
o:depends({ [option_name("protocol")] = "trojan", [option_name("tls")] = true }) o:depends({ [_n("protocol")] = "trojan", [_n("tls")] = true })
o = s:option(Value, option_name("reality_private_key"), translate("Private Key")) o = s:option(Value, _n("reality_private_key"), translate("Private Key"))
o:depends({ [option_name("reality")] = true }) o:depends({ [_n("reality")] = true })
o = s:option(Value, option_name("reality_shortId"), translate("Short Id")) o = s:option(Value, _n("reality_shortId"), translate("Short Id"))
o:depends({ [option_name("reality")] = true }) o:depends({ [_n("reality")] = true })
o = s:option(Value, option_name("reality_handshake_server"), translate("Handshake Server")) o = s:option(Value, _n("reality_handshake_server"), translate("Handshake Server"))
o.default = "google.com" o.default = "google.com"
o:depends({ [option_name("reality")] = true }) o:depends({ [_n("reality")] = true })
o = s:option(Value, option_name("reality_handshake_server_port"), translate("Handshake Server Port")) o = s:option(Value, _n("reality_handshake_server_port"), translate("Handshake Server Port"))
o.datatype = "port" o.datatype = "port"
o.default = "443" o.default = "443"
o:depends({ [option_name("reality")] = true }) o:depends({ [_n("reality")] = true })
end end
-- [[ TLS部分 ]] -- -- [[ TLS部分 ]] --
o = s:option(FileUpload, option_name("tls_certificateFile"), translate("Public key absolute path"), translate("as:") .. "/etc/ssl/fullchain.pem") o = s:option(FileUpload, _n("tls_certificateFile"), translate("Public key absolute path"), translate("as:") .. "/etc/ssl/fullchain.pem")
o.default = m:get(s.section, "tls_certificateFile") or "/etc/config/ssl/" .. arg[1] .. ".pem" o.default = m:get(s.section, "tls_certificateFile") or "/etc/config/ssl/" .. arg[1] .. ".pem"
o:depends({ [option_name("tls")] = true, [option_name("reality")] = false }) o:depends({ [_n("tls")] = true, [_n("reality")] = false })
o:depends({ [option_name("protocol")] = "naive" }) o:depends({ [_n("protocol")] = "naive" })
o:depends({ [option_name("protocol")] = "hysteria" }) o:depends({ [_n("protocol")] = "hysteria" })
o:depends({ [option_name("protocol")] = "tuic" }) o:depends({ [_n("protocol")] = "tuic" })
o:depends({ [option_name("protocol")] = "hysteria2" }) o:depends({ [_n("protocol")] = "hysteria2" })
o.validate = function(self, value, t) o.validate = function(self, value, t)
if value and value ~= "" then if value and value ~= "" then
if not nixio.fs.access(value) then if not nixio.fs.access(value) then
@ -264,13 +264,13 @@ o.validate = function(self, value, t)
return nil return nil
end end
o = s:option(FileUpload, option_name("tls_keyFile"), translate("Private key absolute path"), translate("as:") .. "/etc/ssl/private.key") o = s:option(FileUpload, _n("tls_keyFile"), translate("Private key absolute path"), translate("as:") .. "/etc/ssl/private.key")
o.default = m:get(s.section, "tls_keyFile") or "/etc/config/ssl/" .. arg[1] .. ".key" o.default = m:get(s.section, "tls_keyFile") or "/etc/config/ssl/" .. arg[1] .. ".key"
o:depends({ [option_name("tls")] = true, [option_name("reality")] = false }) o:depends({ [_n("tls")] = true, [_n("reality")] = false })
o:depends({ [option_name("protocol")] = "naive" }) o:depends({ [_n("protocol")] = "naive" })
o:depends({ [option_name("protocol")] = "hysteria" }) o:depends({ [_n("protocol")] = "hysteria" })
o:depends({ [option_name("protocol")] = "tuic" }) o:depends({ [_n("protocol")] = "tuic" })
o:depends({ [option_name("protocol")] = "hysteria2" }) o:depends({ [_n("protocol")] = "hysteria2" })
o.validate = function(self, value, t) o.validate = function(self, value, t)
if value and value ~= "" then if value and value ~= "" then
if not nixio.fs.access(value) then if not nixio.fs.access(value) then
@ -283,19 +283,19 @@ o.validate = function(self, value, t)
end end
if singbox_tags:find("with_ech") then if singbox_tags:find("with_ech") then
o = s:option(Flag, option_name("ech"), translate("ECH")) o = s:option(Flag, _n("ech"), translate("ECH"))
o.default = "0" o.default = "0"
o:depends({ [option_name("tls")] = true, [option_name("flow")] = "", [option_name("reality")] = false }) o:depends({ [_n("tls")] = true, [_n("flow")] = "", [_n("reality")] = false })
o:depends({ [option_name("protocol")] = "naive" }) o:depends({ [_n("protocol")] = "naive" })
o:depends({ [option_name("protocol")] = "hysteria" }) o:depends({ [_n("protocol")] = "hysteria" })
o:depends({ [option_name("protocol")] = "tuic" }) o:depends({ [_n("protocol")] = "tuic" })
o:depends({ [option_name("protocol")] = "hysteria2" }) o:depends({ [_n("protocol")] = "hysteria2" })
o = s:option(TextValue, option_name("ech_key"), translate("ECH Key")) o = s:option(TextValue, _n("ech_key"), translate("ECH Key"))
o.default = "" o.default = ""
o.rows = 5 o.rows = 5
o.wrap = "off" o.wrap = "off"
o:depends({ [option_name("ech")] = true }) o:depends({ [_n("ech")] = true })
o.validate = function(self, value) o.validate = function(self, value)
value = value:gsub("^%s+", ""):gsub("%s+$","\n"):gsub("\r\n","\n"):gsub("[ \t]*\n[ \t]*", "\n") value = value:gsub("^%s+", ""):gsub("%s+$","\n"):gsub("\r\n","\n"):gsub("[ \t]*\n[ \t]*", "\n")
value = value:gsub("^%s*\n", "") value = value:gsub("^%s*\n", "")
@ -305,80 +305,80 @@ if singbox_tags:find("with_ech") then
return value return value
end end
o = s:option(Flag, option_name("pq_signature_schemes_enabled"), translate("PQ signature schemes")) o = s:option(Flag, _n("pq_signature_schemes_enabled"), translate("PQ signature schemes"))
o.default = "0" o.default = "0"
o:depends({ [option_name("ech")] = true }) o:depends({ [_n("ech")] = true })
o = s:option(Flag, option_name("dynamic_record_sizing_disabled"), translate("Disable adaptive sizing of TLS records")) o = s:option(Flag, _n("dynamic_record_sizing_disabled"), translate("Disable adaptive sizing of TLS records"))
o.default = "0" o.default = "0"
o:depends({ [option_name("ech")] = true }) o:depends({ [_n("ech")] = true })
end end
o = s:option(ListValue, option_name("transport"), translate("Transport")) o = s:option(ListValue, _n("transport"), translate("Transport"))
o:value("tcp", "TCP") o:value("tcp", "TCP")
o:value("http", "HTTP") o:value("http", "HTTP")
o:value("ws", "WebSocket") o:value("ws", "WebSocket")
o:value("httpupgrade", "HTTPUpgrade") o:value("httpupgrade", "HTTPUpgrade")
o:value("quic", "QUIC") o:value("quic", "QUIC")
o:value("grpc", "gRPC") o:value("grpc", "gRPC")
o:depends({ [option_name("protocol")] = "shadowsocks" }) o:depends({ [_n("protocol")] = "shadowsocks" })
o:depends({ [option_name("protocol")] = "vmess" }) o:depends({ [_n("protocol")] = "vmess" })
o:depends({ [option_name("protocol")] = "vless" }) o:depends({ [_n("protocol")] = "vless" })
o:depends({ [option_name("protocol")] = "trojan" }) o:depends({ [_n("protocol")] = "trojan" })
-- [[ HTTP部分 ]]-- -- [[ HTTP部分 ]]--
o = s:option(Value, option_name("http_host"), translate("HTTP Host")) o = s:option(Value, _n("http_host"), translate("HTTP Host"))
o:depends({ [option_name("transport")] = "http" }) o:depends({ [_n("transport")] = "http" })
o = s:option(Value, option_name("http_path"), translate("HTTP Path")) o = s:option(Value, _n("http_path"), translate("HTTP Path"))
o:depends({ [option_name("transport")] = "http" }) o:depends({ [_n("transport")] = "http" })
-- [[ WebSocket部分 ]]-- -- [[ WebSocket部分 ]]--
o = s:option(Value, option_name("ws_host"), translate("WebSocket Host")) o = s:option(Value, _n("ws_host"), translate("WebSocket Host"))
o:depends({ [option_name("transport")] = "ws" }) o:depends({ [_n("transport")] = "ws" })
o = s:option(Value, option_name("ws_path"), translate("WebSocket Path")) o = s:option(Value, _n("ws_path"), translate("WebSocket Path"))
o:depends({ [option_name("transport")] = "ws" }) o:depends({ [_n("transport")] = "ws" })
-- [[ HTTPUpgrade部分 ]]-- -- [[ HTTPUpgrade部分 ]]--
o = s:option(Value, option_name("httpupgrade_host"), translate("HTTPUpgrade Host")) o = s:option(Value, _n("httpupgrade_host"), translate("HTTPUpgrade Host"))
o:depends({ [option_name("transport")] = "httpupgrade" }) o:depends({ [_n("transport")] = "httpupgrade" })
o = s:option(Value, option_name("httpupgrade_path"), translate("HTTPUpgrade Path")) o = s:option(Value, _n("httpupgrade_path"), translate("HTTPUpgrade Path"))
o:depends({ [option_name("transport")] = "httpupgrade" }) o:depends({ [_n("transport")] = "httpupgrade" })
-- [[ gRPC部分 ]]-- -- [[ gRPC部分 ]]--
o = s:option(Value, option_name("grpc_serviceName"), "ServiceName") o = s:option(Value, _n("grpc_serviceName"), "ServiceName")
o:depends({ [option_name("transport")] = "grpc" }) o:depends({ [_n("transport")] = "grpc" })
-- [[ Mux ]]-- -- [[ Mux ]]--
o = s:option(Flag, option_name("mux"), translate("Mux")) o = s:option(Flag, _n("mux"), translate("Mux"))
o.rmempty = false o.rmempty = false
o:depends({ [option_name("protocol")] = "vmess" }) o:depends({ [_n("protocol")] = "vmess" })
o:depends({ [option_name("protocol")] = "vless", [option_name("flow")] = "" }) o:depends({ [_n("protocol")] = "vless", [_n("flow")] = "" })
o:depends({ [option_name("protocol")] = "shadowsocks" }) o:depends({ [_n("protocol")] = "shadowsocks" })
o:depends({ [option_name("protocol")] = "trojan" }) o:depends({ [_n("protocol")] = "trojan" })
-- [[ TCP Brutal ]]-- -- [[ TCP Brutal ]]--
o = s:option(Flag, option_name("tcpbrutal"), translate("TCP Brutal")) o = s:option(Flag, _n("tcpbrutal"), translate("TCP Brutal"))
o.default = 0 o.default = 0
o:depends({ [option_name("mux")] = true }) o:depends({ [_n("mux")] = true })
o = s:option(Value, option_name("tcpbrutal_up_mbps"), translate("Max upload Mbps")) o = s:option(Value, _n("tcpbrutal_up_mbps"), translate("Max upload Mbps"))
o.default = "10" o.default = "10"
o:depends({ [option_name("tcpbrutal")] = true }) o:depends({ [_n("tcpbrutal")] = true })
o = s:option(Value, option_name("tcpbrutal_down_mbps"), translate("Max download Mbps")) o = s:option(Value, _n("tcpbrutal_down_mbps"), translate("Max download Mbps"))
o.default = "50" o.default = "50"
o:depends({ [option_name("tcpbrutal")] = true }) o:depends({ [_n("tcpbrutal")] = true })
o = s:option(Flag, option_name("bind_local"), translate("Bind Local"), translate("When selected, it can only be accessed localhost.")) o = s:option(Flag, _n("bind_local"), translate("Bind Local"), translate("When selected, it can only be accessed localhost."))
o.default = "0" o.default = "0"
o = s:option(Flag, option_name("accept_lan"), translate("Accept LAN Access"), translate("When selected, it can accessed lan , this will not be safe!")) o = s:option(Flag, _n("accept_lan"), translate("Accept LAN Access"), translate("When selected, it can accessed lan , this will not be safe!"))
o.default = "0" o.default = "0"
local nodes_table = {} local nodes_table = {}
@ -391,46 +391,45 @@ for k, e in ipairs(api.get_valid_nodes()) do
end end
end end
o = s:option(ListValue, option_name("outbound_node"), translate("outbound node")) o = s:option(ListValue, _n("outbound_node"), translate("outbound node"))
o:value("nil", translate("Close")) o:value("", translate("Close"))
o:value("_socks", translate("Custom Socks")) o:value("_socks", translate("Custom Socks"))
o:value("_http", translate("Custom HTTP")) o:value("_http", translate("Custom HTTP"))
o:value("_iface", translate("Custom Interface")) o:value("_iface", translate("Custom Interface"))
for k, v in pairs(nodes_table) do o:value(v.id, v.remarks) end for k, v in pairs(nodes_table) do o:value(v.id, v.remarks) end
o.default = "nil"
o = s:option(Value, option_name("outbound_node_address"), translate("Address (Support Domain Name)")) o = s:option(Value, _n("outbound_node_address"), translate("Address (Support Domain Name)"))
o:depends({ [option_name("outbound_node")] = "_socks" }) o:depends({ [_n("outbound_node")] = "_socks" })
o:depends({ [option_name("outbound_node")] = "_http" }) o:depends({ [_n("outbound_node")] = "_http" })
o = s:option(Value, option_name("outbound_node_port"), translate("Port")) o = s:option(Value, _n("outbound_node_port"), translate("Port"))
o.datatype = "port" o.datatype = "port"
o:depends({ [option_name("outbound_node")] = "_socks" }) o:depends({ [_n("outbound_node")] = "_socks" })
o:depends({ [option_name("outbound_node")] = "_http" }) o:depends({ [_n("outbound_node")] = "_http" })
o = s:option(Value, option_name("outbound_node_username"), translate("Username")) o = s:option(Value, _n("outbound_node_username"), translate("Username"))
o:depends({ [option_name("outbound_node")] = "_socks" }) o:depends({ [_n("outbound_node")] = "_socks" })
o:depends({ [option_name("outbound_node")] = "_http" }) o:depends({ [_n("outbound_node")] = "_http" })
o = s:option(Value, option_name("outbound_node_password"), translate("Password")) o = s:option(Value, _n("outbound_node_password"), translate("Password"))
o.password = true o.password = true
o:depends({ [option_name("outbound_node")] = "_socks" }) o:depends({ [_n("outbound_node")] = "_socks" })
o:depends({ [option_name("outbound_node")] = "_http" }) o:depends({ [_n("outbound_node")] = "_http" })
o = s:option(Value, option_name("outbound_node_iface"), translate("Interface")) o = s:option(Value, _n("outbound_node_iface"), translate("Interface"))
o.default = "eth1" o.default = "eth1"
o:depends({ [option_name("outbound_node")] = "_iface" }) o:depends({ [_n("outbound_node")] = "_iface" })
o = s:option(Flag, option_name("log"), translate("Log")) o = s:option(Flag, _n("log"), translate("Log"))
o.default = "1" o.default = "1"
o.rmempty = false o.rmempty = false
o = s:option(ListValue, option_name("loglevel"), translate("Log Level")) o = s:option(ListValue, _n("loglevel"), translate("Log Level"))
o.default = "info" o.default = "info"
o:value("debug") o:value("debug")
o:value("info") o:value("info")
o:value("warn") o:value("warn")
o:value("error") o:value("error")
o:depends({ [option_name("log")] = true }) o:depends({ [_n("log")] = true })
api.luci_types(arg[1], m, s, type_name, option_prefix) api.luci_types(arg[1], m, s, type_name, option_prefix)

View File

@ -10,7 +10,7 @@ local type_name = "SS-Rust"
local option_prefix = "ssrust_" local option_prefix = "ssrust_"
local function option_name(name) local function _n(name)
return option_prefix .. name return option_prefix .. name
end end
@ -24,23 +24,23 @@ local ssrust_encrypt_method_list = {
s.fields["type"]:value(type_name, translate("Shadowsocks Rust")) s.fields["type"]:value(type_name, translate("Shadowsocks Rust"))
o = s:option(Value, option_name("port"), translate("Listen Port")) o = s:option(Value, _n("port"), translate("Listen Port"))
o.datatype = "port" o.datatype = "port"
o = s:option(Value, option_name("password"), translate("Password")) o = s:option(Value, _n("password"), translate("Password"))
o.password = true o.password = true
o = s:option(ListValue, option_name("method"), translate("Encrypt Method")) o = s:option(ListValue, _n("method"), translate("Encrypt Method"))
for a, t in ipairs(ssrust_encrypt_method_list) do o:value(t) end for a, t in ipairs(ssrust_encrypt_method_list) do o:value(t) end
o = s:option(Value, option_name("timeout"), translate("Connection Timeout")) o = s:option(Value, _n("timeout"), translate("Connection Timeout"))
o.datatype = "uinteger" o.datatype = "uinteger"
o.default = 300 o.default = 300
o = s:option(Flag, option_name("tcp_fast_open"), "TCP " .. translate("Fast Open")) o = s:option(Flag, _n("tcp_fast_open"), "TCP " .. translate("Fast Open"))
o.default = "0" o.default = "0"
o = s:option(Flag, option_name("log"), translate("Log")) o = s:option(Flag, _n("log"), translate("Log"))
o.default = "1" o.default = "1"
o.rmempty = false o.rmempty = false

View File

@ -10,7 +10,7 @@ local type_name = "SS"
local option_prefix = "ss_" local option_prefix = "ss_"
local function option_name(name) local function _n(name)
return option_prefix .. name return option_prefix .. name
end end
@ -27,23 +27,23 @@ local ss_encrypt_method_list = {
s.fields["type"]:value(type_name, translate("Shadowsocks")) s.fields["type"]:value(type_name, translate("Shadowsocks"))
o = s:option(Value, option_name("port"), translate("Listen Port")) o = s:option(Value, _n("port"), translate("Listen Port"))
o.datatype = "port" o.datatype = "port"
o = s:option(Value, option_name("password"), translate("Password")) o = s:option(Value, _n("password"), translate("Password"))
o.password = true o.password = true
o = s:option(ListValue, option_name("method"), translate("Encrypt Method")) o = s:option(ListValue, _n("method"), translate("Encrypt Method"))
for a, t in ipairs(ss_encrypt_method_list) do o:value(t) end for a, t in ipairs(ss_encrypt_method_list) do o:value(t) end
o = s:option(Value, option_name("timeout"), translate("Connection Timeout")) o = s:option(Value, _n("timeout"), translate("Connection Timeout"))
o.datatype = "uinteger" o.datatype = "uinteger"
o.default = 300 o.default = 300
o = s:option(Flag, option_name("tcp_fast_open"), "TCP " .. translate("Fast Open")) o = s:option(Flag, _n("tcp_fast_open"), "TCP " .. translate("Fast Open"))
o.default = "0" o.default = "0"
o = s:option(Flag, option_name("log"), translate("Log")) o = s:option(Flag, _n("log"), translate("Log"))
o.default = "1" o.default = "1"
o.rmempty = false o.rmempty = false

View File

@ -10,7 +10,7 @@ local type_name = "SSR"
local option_prefix = "ssr_" local option_prefix = "ssr_"
local function option_name(name) local function _n(name)
return option_prefix .. name return option_prefix .. name
end end
@ -37,37 +37,37 @@ local ssr_obfs_list = {
s.fields["type"]:value(type_name, translate("ShadowsocksR")) s.fields["type"]:value(type_name, translate("ShadowsocksR"))
o = s:option(Value, option_name("port"), translate("Listen Port")) o = s:option(Value, _n("port"), translate("Listen Port"))
o.datatype = "port" o.datatype = "port"
o = s:option(Value, option_name("password"), translate("Password")) o = s:option(Value, _n("password"), translate("Password"))
o.password = true o.password = true
o = s:option(ListValue, option_name("method"), translate("Encrypt Method")) o = s:option(ListValue, _n("method"), translate("Encrypt Method"))
for a, t in ipairs(ssr_encrypt_method_list) do o:value(t) end for a, t in ipairs(ssr_encrypt_method_list) do o:value(t) end
o = s:option(ListValue, option_name("protocol"), translate("Protocol")) o = s:option(ListValue, _n("protocol"), translate("Protocol"))
for a, t in ipairs(ssr_protocol_list) do o:value(t) end for a, t in ipairs(ssr_protocol_list) do o:value(t) end
o = s:option(Value, option_name("protocol_param"), translate("Protocol_param")) o = s:option(Value, _n("protocol_param"), translate("Protocol_param"))
o = s:option(ListValue, option_name("obfs"), translate("Obfs")) o = s:option(ListValue, _n("obfs"), translate("Obfs"))
for a, t in ipairs(ssr_obfs_list) do o:value(t) end for a, t in ipairs(ssr_obfs_list) do o:value(t) end
o = s:option(Value, option_name("obfs_param"), translate("Obfs_param")) o = s:option(Value, _n("obfs_param"), translate("Obfs_param"))
o = s:option(Value, option_name("timeout"), translate("Connection Timeout")) o = s:option(Value, _n("timeout"), translate("Connection Timeout"))
o.datatype = "uinteger" o.datatype = "uinteger"
o.default = 300 o.default = 300
o = s:option(Flag, option_name("tcp_fast_open"), "TCP " .. translate("Fast Open")) o = s:option(Flag, _n("tcp_fast_open"), "TCP " .. translate("Fast Open"))
o.default = "0" o.default = "0"
o = s:option(Flag, option_name("udp_forward"), translate("UDP Forward")) o = s:option(Flag, _n("udp_forward"), translate("UDP Forward"))
o.default = "1" o.default = "1"
o.rmempty = false o.rmempty = false
o = s:option(Flag, option_name("log"), translate("Log")) o = s:option(Flag, _n("log"), translate("Log"))
o.default = "1" o.default = "1"
o.rmempty = false o.rmempty = false

View File

@ -347,6 +347,26 @@ function get_domain_from_url(url)
return url return url
end end
function get_node_name(node_id)
local e
if type(node_id) == "table" then
e = node_id
else
e = uci:get_all(appname, node_id)
end
if e then
if e.type and e.remarks then
if e.protocol and (e.protocol == "_balancing" or e.protocol == "_shunt" or e.protocol == "_iface") then
local type = e.type
if type == "sing-box" then type = "Sing-Box" end
local remark = "%s[%s] " % {type .. " " .. i18n.translatef(e.protocol), e.remarks}
return remark
end
end
end
return ""
end
function get_valid_nodes() function get_valid_nodes()
local show_node_info = uci_get_type("global_other", "show_node_info") or "0" local show_node_info = uci_get_type("global_other", "show_node_info") or "0"
local nodes = {} local nodes = {}

View File

@ -21,7 +21,7 @@ end
function gen_outbound(flag, node, tag, proxy_table) function gen_outbound(flag, node, tag, proxy_table)
local result = nil local result = nil
if node and node ~= "nil" then if node then
local node_id = node[".name"] local node_id = node[".name"]
if tag == nil then if tag == nil then
tag = node_id tag = node_id
@ -47,7 +47,7 @@ function gen_outbound(flag, node, tag, proxy_table)
"127.0.0.1", --bind "127.0.0.1", --bind
new_port, --socks port new_port, --socks port
config_file, --config file config_file, --config file
(proxy_tag and proxy_tag ~= "nil" and relay_port) and tostring(relay_port) or "" --relay port (proxy_tag and relay_port) and tostring(relay_port) or "" --relay port
) )
) )
) )
@ -57,7 +57,7 @@ function gen_outbound(flag, node, tag, proxy_table)
port = new_port port = new_port
} }
else else
if proxy_tag and proxy_tag ~= "nil" then if proxy_tag then
node.detour = proxy_tag node.detour = proxy_tag
end end
end end
@ -676,7 +676,7 @@ function gen_config_server(node)
} }
} }
if node.outbound_node and node.outbound_node ~= "nil" then if node.outbound_node then
local outbound = nil local outbound = nil
if node.outbound_node == "_iface" and node.outbound_node_iface then if node.outbound_node == "_iface" and node.outbound_node_iface then
outbound = { outbound = {
@ -896,7 +896,7 @@ function gen_config(var)
end end
if node.chain_proxy == "1" and node.preproxy_node then if node.chain_proxy == "1" and node.preproxy_node then
if outbound["_flag_proxy_tag"] and outbound["_flag_proxy_tag"] ~= "nil" then if outbound["_flag_proxy_tag"] then
--Ignore --Ignore
else else
local preproxy_node = uci:get_all(appname, node.preproxy_node) local preproxy_node = uci:get_all(appname, node.preproxy_node)
@ -942,7 +942,7 @@ function gen_config(var)
local function gen_shunt_node(rule_name, _node_id) local function gen_shunt_node(rule_name, _node_id)
if not rule_name then return nil end if not rule_name then return nil end
if not _node_id then _node_id = node[rule_name] or "nil" end if not _node_id then _node_id = node[rule_name] end
local rule_outboundTag local rule_outboundTag
if _node_id == "_direct" then if _node_id == "_direct" then
rule_outboundTag = "direct" rule_outboundTag = "direct"
@ -967,7 +967,7 @@ function gen_config(var)
rule_outboundTag = _outbound.tag rule_outboundTag = _outbound.tag
end end
end end
elseif _node_id ~= "nil" then elseif _node_id then
local _node = uci:get_all(appname, _node_id) local _node = uci:get_all(appname, _node_id)
if not _node then return nil end if not _node then return nil end
@ -1169,7 +1169,7 @@ function gen_config(var)
rule.domain_regex = #domain_table.domain_regex > 0 and domain_table.domain_regex or nil rule.domain_regex = #domain_table.domain_regex > 0 and domain_table.domain_regex or nil
rule.geosite = #domain_table.geosite > 0 and domain_table.geosite or nil rule.geosite = #domain_table.geosite > 0 and domain_table.geosite or nil
if outboundTag and outboundTag ~= "nil" then if outboundTag then
table.insert(dns_domain_rules, api.clone(domain_table)) table.insert(dns_domain_rules, api.clone(domain_table))
end end
end end
@ -1468,7 +1468,7 @@ function gen_config(var)
tag = "block" tag = "block"
}) })
for index, value in ipairs(config.outbounds) do for index, value in ipairs(config.outbounds) do
if (not value["_flag_proxy_tag"] or value["_flag_proxy_tag"] == "nil") and not value.detour and value["_id"] and value.server and value.server_port then if not value["_flag_proxy_tag"] and not value.detour and value["_id"] and value.server and value.server_port then
sys.call(string.format("echo '%s' >> %s", value["_id"], api.TMP_PATH .. "/direct_node_list")) sys.call(string.format("echo '%s' >> %s", value["_id"], api.TMP_PATH .. "/direct_node_list"))
end end
for k, v in pairs(config.outbounds[index]) do for k, v in pairs(config.outbounds[index]) do

View File

@ -49,7 +49,7 @@ end
function gen_outbound(flag, node, tag, proxy_table) function gen_outbound(flag, node, tag, proxy_table)
local result = nil local result = nil
if node and node ~= "nil" then if node then
local node_id = node[".name"] local node_id = node[".name"]
if tag == nil then if tag == nil then
tag = node_id tag = node_id
@ -79,7 +79,7 @@ function gen_outbound(flag, node, tag, proxy_table)
"127.0.0.1", --bind "127.0.0.1", --bind
new_port, --socks port new_port, --socks port
config_file, --config file config_file, --config file
(proxy_tag and proxy_tag ~= "nil" and relay_port) and tostring(relay_port) or "" --relay port (proxy_tag and relay_port) and tostring(relay_port) or "" --relay port
) )
) )
) )
@ -92,7 +92,7 @@ function gen_outbound(flag, node, tag, proxy_table)
else else
if node.flow == "xtls-rprx-vision" then if node.flow == "xtls-rprx-vision" then
else else
if proxy_tag and proxy_tag ~= "nil" then if proxy_tag then
node.proxySettings = { node.proxySettings = {
tag = proxy_tag, tag = proxy_tag,
transportLayer = true transportLayer = true
@ -402,7 +402,7 @@ function gen_config_server(node)
} }
} }
if node.outbound_node and node.outbound_node ~= "nil" then if node.outbound_node then
local outbound = nil local outbound = nil
if node.outbound_node == "_iface" and node.outbound_node_iface then if node.outbound_node == "_iface" and node.outbound_node_iface then
outbound = { outbound = {
@ -735,7 +735,7 @@ function gen_config(var)
-- fallback node -- fallback node
local fallback_node_tag = nil local fallback_node_tag = nil
local fallback_node_id = _node.fallback_node local fallback_node_id = _node.fallback_node
if fallback_node_id == "" or fallback_node_id == "nil" then fallback_node_id = nil end if not fallback_node_id or fallback_node_id == "" then fallback_node_id = nil end
if fallback_node_id then if fallback_node_id then
local is_new_node = true local is_new_node = true
for _, outbound in ipairs(outbounds) do for _, outbound in ipairs(outbounds) do
@ -784,7 +784,7 @@ function gen_config(var)
local last_insert_outbound local last_insert_outbound
if node.chain_proxy == "1" and node.preproxy_node then if node.chain_proxy == "1" and node.preproxy_node then
if outbound["_flag_proxy_tag"] and outbound["_flag_proxy_tag"] ~= "nil" then if outbound["_flag_proxy_tag"] then
--Ignore --Ignore
else else
local preproxy_node = uci:get_all(appname, node.preproxy_node) local preproxy_node = uci:get_all(appname, node.preproxy_node)
@ -841,7 +841,7 @@ function gen_config(var)
local function gen_shunt_node(rule_name, _node_id) local function gen_shunt_node(rule_name, _node_id)
if not rule_name then return nil, nil end if not rule_name then return nil, nil end
if not _node_id then _node_id = node[rule_name] or "nil" end if not _node_id then _node_id = node[rule_name] end
if _node_id == "_direct" then if _node_id == "_direct" then
return "direct", nil return "direct", nil
elseif _node_id == "_blackhole" then elseif _node_id == "_blackhole" then
@ -872,7 +872,7 @@ function gen_config(var)
end end
end end
return socks_tag, nil return socks_tag, nil
elseif _node_id ~= "nil" then elseif _node_id then
local _node = uci:get_all(appname, _node_id) local _node = uci:get_all(appname, _node_id)
if not _node then return nil, nil end if not _node then return nil, nil end
@ -1031,7 +1031,7 @@ function gen_config(var)
table.insert(domains, w) table.insert(domains, w)
table.insert(domain_table.domain, w) table.insert(domain_table.domain, w)
end) end)
if (outboundTag and outboundTag ~= "nil") or (balancerTag and balancerTag ~= "nil") then if outboundTag or balancerTag then
table.insert(dns_domain_rules, api.clone(domain_table)) table.insert(dns_domain_rules, api.clone(domain_table))
end end
if #domains == 0 then domains = nil end if #domains == 0 then domains = nil end
@ -1549,7 +1549,7 @@ function gen_config(var)
end end
for index, value in ipairs(config.outbounds) do for index, value in ipairs(config.outbounds) do
if (not value["_flag_proxy_tag"] or value["_flag_proxy_tag"] == "nil") and value["_id"] and value.server and value.server_port then if not value["_flag_proxy_tag"] and value["_id"] and value.server and value.server_port then
sys.call(string.format("echo '%s' >> %s", value["_id"], api.TMP_PATH .. "/direct_node_list")) sys.call(string.format("echo '%s' >> %s", value["_id"], api.TMP_PATH .. "/direct_node_list"))
end end
for k, v in pairs(config.outbounds[index]) do for k, v in pairs(config.outbounds[index]) do

View File

@ -0,0 +1,3 @@
<div id="cbi-<%=self.config.."-"..section.."-"..self.option%>" data-index="<%=self.index%>" data-depends="<%=pcdata(self:deplist2json(section))%>" style="display: none !important">
<input type="hidden" id="<%=cbid%>" value="<%=pcdata(self:cfgvalue(section) or self.default or "")%>" />
</div>

View File

@ -53,7 +53,7 @@ local api = require "luci.passwall2.api"
var dom_id = dom.id.split(cbi_id).join(cbi_id.split("-").join(".")).split("cbi.").join("cbid.") var dom_id = dom.id.split(cbi_id).join(cbi_id.split("-").join(".")).split("cbi.").join("cbid.")
var node_select = document.getElementsByName(dom_id)[0]; var node_select = document.getElementsByName(dom_id)[0];
var node_select_value = node_select.value; var node_select_value = node_select.value;
if (node_select_value && node_select_value != "nil" && node_select_value.indexOf("_default") != 0 && node_select_value.indexOf("_direct") != 0 && node_select_value.indexOf("_blackhole") != 0) { if (node_select_value && node_select_value != "" && node_select_value.indexOf("_default") != 0 && node_select_value.indexOf("_direct") != 0 && node_select_value.indexOf("_blackhole") != 0) {
if (node_select.tagName == "INPUT") { if (node_select.tagName == "INPUT") {
node_select = document.getElementById("cbi.combobox." + dom_id); node_select = document.getElementById("cbi.combobox." + dom_id);
} }
@ -106,7 +106,7 @@ local api = require "luci.passwall2.api"
var dom_id = dom_id.replace("cbi-", "cbid-").replace(new RegExp("-", 'g'), "."); var dom_id = dom_id.replace("cbi-", "cbid-").replace(new RegExp("-", 'g'), ".");
var node_select = document.getElementsByName(dom_id)[0]; var node_select = document.getElementsByName(dom_id)[0];
var node_select_value = node_select.value; var node_select_value = node_select.value;
if (node_select_value && node_select_value != "nil") { if (node_select_value && node_select_value != "") {
var v = document.getElementById(dom_id + "-" + node_select_value); var v = document.getElementById(dom_id + "-" + node_select_value);
if (v) { if (v) {
node_select.title = v.text; node_select.title = v.text;

View File

@ -4,8 +4,8 @@ local uci = api.uci
local default_node_type = "" local default_node_type = ""
local shunt_rule_list = {} local shunt_rule_list = {}
local node = api.uci_get_type("global", "node", "nil") local node = api.uci_get_type("global", "node")
if node ~= "nil" then if node then
local node_type = api.uci_get_type_id(node, "type") local node_type = api.uci_get_type_id(node, "type")
local node_protocol = api.uci_get_type_id(node, "protocol") local node_protocol = api.uci_get_type_id(node, "protocol")
if node_type == "Xray" and node_protocol == "_shunt" then if node_type == "Xray" and node_protocol == "_shunt" then

View File

@ -574,17 +574,32 @@ msgstr "单位:秒"
msgid "Units:minutes" msgid "Units:minutes"
msgstr "单位:分钟" msgstr "单位:分钟"
msgid "Open and close automatically" msgid "stop automatically mode"
msgstr "定时自动开关" msgstr "定时关闭模式"
msgid "Automatically turn off time" msgid "stop Time(Every day)"
msgstr "自动关闭时间" msgstr "关闭时间(每天)"
msgid "Automatically turn on time" msgid "stop Interval(Hour)"
msgstr "自动开启时间" msgstr "关闭间隔(小时)"
msgid "Automatically restart time" msgid "start automatically mode"
msgstr "自动重启时间" msgstr "定时开启模式"
msgid "start Time(Every day)"
msgstr "开启时间(每天)"
msgid "start Interval(Hour)"
msgstr "开启间隔(小时)"
msgid "restart automatically mode"
msgstr "定时重启模式"
msgid "restart Time(Every day)"
msgstr "重启时间(每天)"
msgid "restart Interval(Hour)"
msgstr "重启间隔(小时)"
msgid "Forwarding Settings" msgid "Forwarding Settings"
msgstr "转发配置" msgstr "转发配置"
@ -820,6 +835,9 @@ msgstr "每周日"
msgid "hour" msgid "hour"
msgstr "小时" msgstr "小时"
msgid "Hour"
msgstr "小时"
msgid "Location of V2ray/Xray asset" msgid "Location of V2ray/Xray asset"
msgstr "V2ray/Xray 资源文件目录" msgstr "V2ray/Xray 资源文件目录"

View File

@ -21,7 +21,6 @@ config global_haproxy
option balancing_enable '0' option balancing_enable '0'
config global_delay config global_delay
option auto_on '0'
option start_daemon '1' option start_daemon '1'
option start_delay '60' option start_delay '60'
@ -76,13 +75,10 @@ config nodes 'myshunt'
option ProxyGame '_default' option ProxyGame '_default'
option Direct '_direct' option Direct '_direct'
option GooglePlay '_default' option GooglePlay '_default'
option Netflix 'nil'
option OpenAI 'nil'
option Proxy '_default' option Proxy '_default'
option China '_direct' option China '_direct'
option QUIC '_blackhole' option QUIC '_blackhole'
option UDP 'nil' option default_node '_direct'
option default_node 'nil'
option domainStrategy 'IPOnDemand' option domainStrategy 'IPOnDemand'
option domainMatcher 'hybrid' option domainMatcher 'hybrid'

View File

@ -278,7 +278,7 @@ ln_run() {
lua_api() { lua_api() {
local func=${1} local func=${1}
[ -z "${func}" ] && { [ -z "${func}" ] && {
echo "nil" echo ""
return return
} }
echo $(lua -e "local api = require 'luci.passwall2.api' print(api.${func})") echo $(lua -e "local api = require 'luci.passwall2.api' print(api.${func})")
@ -442,6 +442,8 @@ run_xray() {
lua $UTIL_XRAY gen_config -node $node -redir_port $redir_port -tcp_proxy_way $tcp_proxy_way -loglevel $loglevel ${_extra_param} > $config_file lua $UTIL_XRAY gen_config -node $node -redir_port $redir_port -tcp_proxy_way $tcp_proxy_way -loglevel $loglevel ${_extra_param} > $config_file
ln_run "$(first_type $(config_t_get global_app ${type}_file) ${type})" ${type} $log_file run -c "$config_file" ln_run "$(first_type $(config_t_get global_app ${type}_file) ${type})" ${type} $log_file run -c "$config_file"
[ -n "${redir_port}" ] && set_cache_var "node_${node}_redir_port" "${redir_port}"
} }
run_singbox() { run_singbox() {
@ -541,6 +543,8 @@ run_singbox() {
lua $UTIL_SINGBOX gen_config -node $node -redir_port $redir_port -tcp_proxy_way $tcp_proxy_way ${_extra_param} > $config_file lua $UTIL_SINGBOX gen_config -node $node -redir_port $redir_port -tcp_proxy_way $tcp_proxy_way ${_extra_param} > $config_file
ln_run "$(first_type $(config_t_get global_app singbox_file) sing-box)" "sing-box" "${log_file}" run -c "$config_file" ln_run "$(first_type $(config_t_get global_app singbox_file) sing-box)" "sing-box" "${log_file}" run -c "$config_file"
[ -n "${redir_port}" ] && set_cache_var "node_${node}_redir_port" "${redir_port}"
} }
run_socks() { run_socks() {
@ -701,11 +705,10 @@ socks_node_switch() {
} }
run_global() { run_global() {
[ "$NODE" = "nil" ] && return 1 [ -z "$NODE" ] && return 1
TYPE=$(echo $(config_n_get $NODE type nil) | tr 'A-Z' 'a-z') TYPE=$(echo $(config_n_get $NODE type) | tr 'A-Z' 'a-z')
[ "$TYPE" = "nil" ] && return 1 [ -z "$TYPE" ] && return 1
mkdir -p $TMP_ACL_PATH/default mkdir -p $TMP_ACL_PATH/default
set_cache_var "GLOBAL_node" "$NODE"
if [ $PROXY_IPV6 == "1" ]; then if [ $PROXY_IPV6 == "1" ]; then
echolog "开启实验性IPv6透明代理(TProxy)请确认您的节点及类型支持IPv6" echolog "开启实验性IPv6透明代理(TProxy)请确认您的节点及类型支持IPv6"
@ -774,6 +777,9 @@ run_global() {
GLOBAL_DNSMASQ_PORT=$(get_new_port 11400) GLOBAL_DNSMASQ_PORT=$(get_new_port 11400)
run_copy_dnsmasq flag="default" listen_port=$GLOBAL_DNSMASQ_PORT tun_dns="${TUN_DNS}" run_copy_dnsmasq flag="default" listen_port=$GLOBAL_DNSMASQ_PORT tun_dns="${TUN_DNS}"
DNS_REDIRECT_PORT=${GLOBAL_DNSMASQ_PORT} DNS_REDIRECT_PORT=${GLOBAL_DNSMASQ_PORT}
set_cache_var "ACL_GLOBAL_node" "$NODE"
set_cache_var "ACL_GLOBAL_redir_port" "$REDIR_PORT"
} }
start_socks() { start_socks() {
@ -784,8 +790,8 @@ start_socks() {
for id in $ids; do for id in $ids; do
local enabled=$(config_n_get $id enabled 0) local enabled=$(config_n_get $id enabled 0)
[ "$enabled" == "0" ] && continue [ "$enabled" == "0" ] && continue
local node=$(config_n_get $id node nil) local node=$(config_n_get $id node)
[ "$node" == "nil" ] && continue [ -z "$node" ] && continue
local bind_local=$(config_n_get $id bind_local 0) local bind_local=$(config_n_get $id bind_local 0)
local bind="0.0.0.0" local bind="0.0.0.0"
[ "$bind_local" = "1" ] && bind="127.0.0.1" [ "$bind_local" = "1" ] && bind="127.0.0.1"
@ -846,23 +852,43 @@ start_crontab() {
return return
} }
auto_on=$(config_t_get global_delay auto_on 0) stop_week_mode=$(config_t_get global_delay stop_week_mode)
if [ "$auto_on" = "1" ]; then stop_time_mode=$(config_t_get global_delay stop_time_mode)
time_off=$(config_t_get global_delay time_off) if [ -n "$stop_week_mode" ]; then
time_on=$(config_t_get global_delay time_on) local t="0 $stop_time_mode * * $stop_week_mode"
time_restart=$(config_t_get global_delay time_restart) [ "$stop_week_mode" = "7" ] && t="0 $stop_time_mode * * *"
[ -z "$time_off" -o "$time_off" != "nil" ] && { if [ "$stop_week_mode" = "8" ]; then
echo "0 $time_off * * * /etc/init.d/$CONFIG stop" >>/etc/crontabs/root update_loop=1
echolog "配置定时任务:每天 $time_off 点关闭服务。" else
} echo "$t /etc/init.d/$CONFIG stop > /dev/null 2>&1 &" >>/etc/crontabs/root
[ -z "$time_on" -o "$time_on" != "nil" ] && { fi
echo "0 $time_on * * * /etc/init.d/$CONFIG start" >>/etc/crontabs/root echolog "配置定时任务:自动关闭服务。"
echolog "配置定时任务:每天 $time_on 点开启服务。" fi
}
[ -z "$time_restart" -o "$time_restart" != "nil" ] && { start_week_mode=$(config_t_get global_delay start_week_mode)
echo "0 $time_restart * * * /etc/init.d/$CONFIG restart" >>/etc/crontabs/root start_time_mode=$(config_t_get global_delay start_time_mode)
echolog "配置定时任务:每天 $time_restart 点重启服务。" if [ -n "$start_week_mode" ]; then
} local t="0 $start_time_mode * * $start_week_mode"
[ "$start_week_mode" = "7" ] && t="0 $start_time_mode * * *"
if [ "$start_week_mode" = "8" ]; then
update_loop=1
else
echo "$t /etc/init.d/$CONFIG start > /dev/null 2>&1 &" >>/etc/crontabs/root
fi
echolog "配置定时任务:自动开启服务。"
fi
restart_week_mode=$(config_t_get global_delay restart_week_mode)
restart_time_mode=$(config_t_get global_delay restart_time_mode)
if [ -n "$restart_week_mode" ]; then
local t="0 $restart_time_mode * * $restart_week_mode"
[ "$restart_week_mode" = "7" ] && t="0 $restart_time_mode * * *"
if [ "$restart_week_mode" = "8" ]; then
update_loop=1
else
echo "$t /etc/init.d/$CONFIG restart > /dev/null 2>&1 &" >>/etc/crontabs/root
fi
echolog "配置定时任务:自动重启服务。"
fi fi
autoupdate=$(config_t_get global_rules auto_update) autoupdate=$(config_t_get global_rules auto_update)
@ -1098,7 +1124,7 @@ acl_app() {
dnsmasq_port=${GLOBAL_DNSMASQ_PORT:-11400} dnsmasq_port=${GLOBAL_DNSMASQ_PORT:-11400}
for item in $items; do for item in $items; do
index=$(expr $index + 1) index=$(expr $index + 1)
local enabled sid remarks sources node direct_dns_query_strategy remote_dns_protocol remote_dns remote_dns_doh remote_dns_client_ip remote_dns_detour remote_fakedns remote_dns_query_strategy interface use_interface local enabled sid remarks sources interface tcp_no_redir_ports udp_no_redir_ports node direct_dns_query_strategy write_ipset_direct remote_dns_protocol remote_dns remote_dns_doh remote_dns_client_ip remote_dns_detour remote_fakedns remote_dns_query_strategy
local _ip _mac _iprange _ipset _ip_or_mac source_list config_file local _ip _mac _iprange _ipset _ip_or_mac source_list config_file
sid=$(uci -q show "${CONFIG}.${item}" | grep "=acl_rule" | awk -F '=' '{print $1}' | awk -F '.' '{print $2}') sid=$(uci -q show "${CONFIG}.${item}" | grep "=acl_rule" | awk -F '=' '{print $1}' | awk -F '.' '{print $2}')
eval $(uci -q show "${CONFIG}.${item}" | cut -d'.' -sf 3-) eval $(uci -q show "${CONFIG}.${item}" | cut -d'.' -sf 3-)
@ -1127,30 +1153,46 @@ acl_app() {
mkdir -p $TMP_ACL_PATH/$sid mkdir -p $TMP_ACL_PATH/$sid
[ ! -z "${source_list}" ] && echo -e "${source_list}" | sed '/^$/d' > $TMP_ACL_PATH/$sid/source_list [ ! -z "${source_list}" ] && echo -e "${source_list}" | sed '/^$/d' > $TMP_ACL_PATH/$sid/source_list
tcp_proxy_mode="global"
udp_proxy_mode="global"
node=${node:-default} node=${node:-default}
direct_dns_query_strategy=${direct_dns_query_strategy:-UseIP} tcp_no_redir_ports=${tcp_no_redir_ports:-default}
remote_dns_protocol=${remote_dns_protocol:-tcp} udp_no_redir_ports=${udp_no_redir_ports:-default}
remote_dns=${remote_dns:-1.1.1.1} [ "$tcp_no_redir_ports" = "default" ] && tcp_no_redir_ports=$TCP_NO_REDIR_PORTS
[ "$remote_dns_protocol" = "doh" ] && remote_dns=${remote_dns_doh:-https://1.1.1.1/dns-query} [ "$udp_no_redir_ports" = "default" ] && udp_no_redir_ports=$UDP_NO_REDIR_PORTS
remote_dns_detour=${remote_dns_detour:-remote} [ "$tcp_no_redir_ports" == "1:65535" ] && [ "$udp_no_redir_ports" == "1:65535" ] && unset node
remote_fakedns=${remote_fakedns:-0}
remote_dns_query_strategy=${remote_dns_query_strategy:-UseIPv4}
write_ipset_direct=${write_ipset_direct:-1} [ -n "$node" ] && {
tcp_proxy_mode="global"
udp_proxy_mode="global"
direct_dns_query_strategy=${direct_dns_query_strategy:-UseIP}
write_ipset_direct=${write_ipset_direct:-1}
remote_dns_protocol=${remote_dns_protocol:-tcp}
remote_dns=${remote_dns:-1.1.1.1}
[ "$remote_dns_protocol" = "doh" ] && remote_dns=${remote_dns_doh:-https://1.1.1.1/dns-query}
remote_dns_detour=${remote_dns_detour:-remote}
remote_fakedns=${remote_fakedns:-0}
remote_dns_query_strategy=${remote_dns_query_strategy:-UseIPv4}
local GLOBAL_node=$(get_cache_var "ACL_GLOBAL_node")
[ -n "${GLOBAL_node}" ] && GLOBAL_redir_port=$(get_cache_var "ACL_GLOBAL_redir_port")
[ "$node" != "nil" ] && {
if [ "$node" = "default" ]; then if [ "$node" = "default" ]; then
node=$NODE if [ -n "${GLOBAL_node}" ]; then
redir_port=$REDIR_PORT set_cache_var "ACL_${sid}_node" "${GLOBAL_node}"
set_cache_var "ACL_${sid}_redir_port" "${GLOBAL_redir_port}"
set_cache_var "ACL_${sid}_dns_port" "${GLOBAL_DNSMASQ_PORT}"
set_cache_var "ACL_${sid}_default" "1"
else
echolog " - 全局节点未启用,跳过【${remarks}"
fi
else else
[ "$(config_get_type $node nil)" = "nodes" ] && { [ "$(config_get_type $node)" = "nodes" ] && {
if [ "$node" = "$NODE" ]; then if [ -n "${GLOBAL_node}" ] && [ "$node" = "${GLOBAL_node}" ]; then
redir_port=$REDIR_PORT set_cache_var "ACL_${sid}_node" "${GLOBAL_node}"
set_cache_var "ACL_${sid}_redir_port" "${GLOBAL_redir_port}"
set_cache_var "ACL_${sid}_dns_port" "${GLOBAL_DNSMASQ_PORT}"
set_cache_var "ACL_${sid}_default" "1"
else else
redir_port=$(get_new_port $(expr $redir_port + 1)) redir_port=$(get_new_port $(expr $redir_port + 1))
eval node_${node}_redir_port=$redir_port
local type=$(echo $(config_n_get $node type) | tr 'A-Z' 'a-z') local type=$(echo $(config_n_get $node type) | tr 'A-Z' 'a-z')
if [ -n "${type}" ]; then if [ -n "${type}" ]; then
@ -1169,16 +1211,14 @@ acl_app() {
fi fi
dnsmasq_port=$(get_new_port $(expr $dnsmasq_port + 1)) dnsmasq_port=$(get_new_port $(expr $dnsmasq_port + 1))
run_copy_dnsmasq flag="$sid" listen_port=$dnsmasq_port tun_dns="127.0.0.1#${dns_port}" run_copy_dnsmasq flag="$sid" listen_port=$dnsmasq_port tun_dns="127.0.0.1#${dns_port}"
eval node_${node}_$(echo -n "${tcp_proxy_mode}${remote_dns}" | md5sum | cut -d " " -f1)=${dnsmasq_port}
filter_node $node TCP > /dev/null 2>&1 & set_cache_var "ACL_${sid}_node" "$node"
filter_node $node UDP > /dev/null 2>&1 & set_cache_var "ACL_${sid}_redir_port" "$redir_port"
fi fi
set_cache_var "ACL_${sid}_node" "${node}"
} }
fi fi
set_cache_var "ACL_${sid}_redir_port" "${redir_port}"
} }
unset enabled sid remarks sources interface node direct_dns_query_strategy remote_dns_protocol remote_dns remote_dns_doh remote_dns_client_ip remote_dns_detour remote_fakedns remote_dns_query_strategy unset enabled sid remarks sources interface tcp_no_redir_ports udp_no_redir_ports node direct_dns_query_strategy write_ipset_direct remote_dns_protocol remote_dns remote_dns_doh remote_dns_client_ip remote_dns_detour remote_fakedns remote_dns_query_strategy
unset _ip _mac _iprange _ipset _ip_or_mac source_list config_file unset _ip _mac _iprange _ipset _ip_or_mac source_list config_file
done done
unset redir_port dns_port dnsmasq_port unset redir_port dns_port dnsmasq_port
@ -1272,9 +1312,9 @@ stop() {
} }
ENABLED=$(config_t_get global enabled 0) ENABLED=$(config_t_get global enabled 0)
NODE=$(config_t_get global node nil) NODE=$(config_t_get global node)
[ "$ENABLED" == 1 ] && { [ "$ENABLED" == 1 ] && {
[ "$NODE" != "nil" ] && [ "$(config_get_type $NODE nil)" != "nil" ] && ENABLED_DEFAULT_ACL=1 [ -n "$NODE" ] && [ "$(config_get_type $NODE)" == "nodes" ] && ENABLED_DEFAULT_ACL=1
} }
ENABLED_ACLS=$(config_t_get global acl_enable 0) ENABLED_ACLS=$(config_t_get global acl_enable 0)
[ "$ENABLED_ACLS" == 1 ] && { [ "$ENABLED_ACLS" == 1 ] && {

View File

@ -209,8 +209,8 @@ gen_shunt_list() {
[ "$default_node" = "_direct" ] && default_outbound="direct" [ "$default_node" = "_direct" ] && default_outbound="direct"
local shunt_ids=$(uci show $CONFIG | grep "=shunt_rules" | awk -F '.' '{print $2}' | awk -F '=' '{print $1}') local shunt_ids=$(uci show $CONFIG | grep "=shunt_rules" | awk -F '.' '{print $2}' | awk -F '=' '{print $1}')
for shunt_id in $shunt_ids; do for shunt_id in $shunt_ids; do
local shunt_node=$(config_n_get ${node} "${shunt_id}" nil) local shunt_node=$(config_n_get ${node} "${shunt_id}")
[ "$shunt_node" != "nil" ] && { [ -n "$shunt_node" ] && {
local ipset_v4="passwall2_${node}_${shunt_id}" local ipset_v4="passwall2_${node}_${shunt_id}"
local ipset_v6="passwall2_${node}_${shunt_id}6" local ipset_v6="passwall2_${node}_${shunt_id}6"
ipset -! create $ipset_v4 nethash maxelem 1048576 ipset -! create $ipset_v4 nethash maxelem 1048576
@ -244,7 +244,7 @@ gen_shunt_list() {
_SHUNT_LIST4="${_SHUNT_LIST4} ${_set_name4}:direct" _SHUNT_LIST4="${_SHUNT_LIST4} ${_set_name4}:direct"
_SHUNT_LIST6="${_SHUNT_LIST6} ${_set_name6}:direct" _SHUNT_LIST6="${_SHUNT_LIST6} ${_set_name6}:direct"
} }
[ "$default_node" != "nil" ] && { [ -n "$default_node" ] && {
local ipset_v4="passwall2_${node}_default" local ipset_v4="passwall2_${node}_default"
local ipset_v6="passwall2_${node}_default6" local ipset_v6="passwall2_${node}_default6"
ipset -! create $ipset_v4 nethash maxelem 1048576 ipset -! create $ipset_v4 nethash maxelem 1048576
@ -276,8 +276,8 @@ add_shunt_t_rule() {
load_acl() { load_acl() {
[ "$ENABLED_ACLS" == 1 ] && { [ "$ENABLED_ACLS" == 1 ] && {
acl_app
echolog "访问控制:" echolog "访问控制:"
acl_app
for sid in $(ls -F ${TMP_ACL_PATH} | grep '/$' | awk -F '/' '{print $1}' | grep -v 'default'); do for sid in $(ls -F ${TMP_ACL_PATH} | grep '/$' | awk -F '/' '{print $1}' | grep -v 'default'); do
eval $(uci -q show "${CONFIG}.${sid}" | cut -d'.' -sf 3-) eval $(uci -q show "${CONFIG}.${sid}" | cut -d'.' -sf 3-)
@ -285,24 +285,26 @@ load_acl() {
udp_no_redir_ports=${udp_no_redir_ports:-default} udp_no_redir_ports=${udp_no_redir_ports:-default}
tcp_proxy_mode="global" tcp_proxy_mode="global"
udp_proxy_mode="global" udp_proxy_mode="global"
tcp_redir_ports=${tcp_redir_ports:-default}
udp_redir_ports=${udp_redir_ports:-default}
node=${node:-default} node=${node:-default}
[ "$tcp_no_redir_ports" = "default" ] && tcp_no_redir_ports=$TCP_NO_REDIR_PORTS [ "$tcp_no_redir_ports" = "default" ] && tcp_no_redir_ports=$TCP_NO_REDIR_PORTS
[ "$udp_no_redir_ports" = "default" ] && udp_no_redir_ports=$UDP_NO_REDIR_PORTS [ "$udp_no_redir_ports" = "default" ] && udp_no_redir_ports=$UDP_NO_REDIR_PORTS
[ "$tcp_redir_ports" = "default" ] && tcp_redir_ports=$TCP_REDIR_PORTS [ "$tcp_redir_ports" = "default" ] && tcp_redir_ports=$TCP_REDIR_PORTS
[ "$udp_redir_ports" = "default" ] && udp_redir_ports=$UDP_REDIR_PORTS [ "$udp_redir_ports" = "default" ] && udp_redir_ports=$UDP_REDIR_PORTS
node_remark=$(config_n_get $NODE remarks)
[ -n "$(get_cache_var "ACL_${sid}_node")" ] && node=$(get_cache_var "ACL_${sid}_node") [ -n "$(get_cache_var "ACL_${sid}_node")" ] && node=$(get_cache_var "ACL_${sid}_node")
[ -n "$(get_cache_var "ACL_${sid}_redir_port")" ] && redir_port=$(get_cache_var "ACL_${sid}_redir_port") [ -n "$(get_cache_var "ACL_${sid}_redir_port")" ] && redir_port=$(get_cache_var "ACL_${sid}_redir_port")
[ -n "$(get_cache_var "ACL_${sid}_dns_port")" ] && dns_redirect_port=$(get_cache_var "ACL_${sid}_dns_port") [ -n "$(get_cache_var "ACL_${sid}_dns_port")" ] && dns_redirect_port=$(get_cache_var "ACL_${sid}_dns_port")
[ "$node" = "default" ] && dns_redirect_port=${DNS_REDIRECT_PORT} [ -n "$node" ] && node_remark=$(config_n_get $node remarks)
[ -n "$node" ] && [ "$node" != "default" ] && node_remark=$(config_n_get $node remarks)
write_ipset_direct=${write_ipset_direct:-1} write_ipset_direct=${write_ipset_direct:-1}
[ "${write_ipset_direct}" = "1" ] && { [ "${write_ipset_direct}" = "1" ] && {
if [ "$node" = "default" ]; then if [ -n "$(get_cache_var "ACL_${sid}_default")" ]; then
local ipset_whitelist=${ipset_global_whitelist} local ipset_whitelist=${ipset_global_whitelist}
local ipset_whitelist6=${ipset_global_whitelist6} local ipset_whitelist6=${ipset_global_whitelist6}
shunt_list4=${SHUNT_LIST4}
shunt_list6=${SHUNT_LIST6}
else else
local ipset_whitelist="passwall2_${sid}_whitelist" local ipset_whitelist="passwall2_${sid}_whitelist"
local ipset_whitelist6="passwall2_${sid}_whitelist6" local ipset_whitelist6="passwall2_${sid}_whitelist6"
@ -387,7 +389,7 @@ load_acl() {
fi fi
} }
if ([ "$tcp_proxy_mode" != "disable" ] || [ "$udp_proxy_mode" != "disable" ]) && [ -n "$redir_port" ]; then if ([ "$tcp_proxy_mode" != "disable" ] || [ "$udp_proxy_mode" != "disable" ]) && [ -n "$dns_redirect_port" ]; then
$ipt_n -A PSW2_DNS $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j REDIRECT --to-ports $dns_redirect_port $ipt_n -A PSW2_DNS $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j REDIRECT --to-ports $dns_redirect_port
$ip6t_n -A PSW2_DNS $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j REDIRECT --to-ports $dns_redirect_port 2>/dev/null $ip6t_n -A PSW2_DNS $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j REDIRECT --to-ports $dns_redirect_port 2>/dev/null
$ipt_n -A PSW2_DNS $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j REDIRECT --to-ports $dns_redirect_port $ipt_n -A PSW2_DNS $(comment "$remarks") -p tcp ${_ipt_source} --dport 53 -j REDIRECT --to-ports $dns_redirect_port
@ -490,7 +492,7 @@ load_acl() {
fi fi
} }
if ([ "$TCP_PROXY_MODE" != "disable" ] || [ "$UDP_PROXY_MODE" != "disable" ]) && [ "$NODE" != "nil" ]; then if ([ "$TCP_PROXY_MODE" != "disable" ] || [ "$UDP_PROXY_MODE" != "disable" ]) && [ -n "$NODE" ]; then
[ -n "$DNS_REDIRECT_PORT" ] && { [ -n "$DNS_REDIRECT_PORT" ] && {
$ipt_n -A PSW2_DNS $(comment "默认") -p udp --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT $ipt_n -A PSW2_DNS $(comment "默认") -p udp --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT
$ip6t_n -A PSW2_DNS $(comment "默认") -p udp --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT 2>/dev/null $ip6t_n -A PSW2_DNS $(comment "默认") -p udp --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT 2>/dev/null
@ -499,7 +501,7 @@ load_acl() {
} }
fi fi
if [ "$TCP_PROXY_MODE" != "disable" ] && [ "$NODE" != "nil" ]; then if [ "$TCP_PROXY_MODE" != "disable" ] && [ -n "$NODE" ]; then
msg2="${msg}使用 TCP 节点[$(config_n_get $NODE remarks)]" msg2="${msg}使用 TCP 节点[$(config_n_get $NODE remarks)]"
if [ -n "${is_tproxy}" ]; then if [ -n "${is_tproxy}" ]; then
msg2="${msg2}(TPROXY:${REDIR_PORT})" msg2="${msg2}(TPROXY:${REDIR_PORT})"
@ -536,7 +538,7 @@ load_acl() {
echolog "${msg2}" echolog "${msg2}"
fi fi
if [ "$UDP_PROXY_MODE" != "disable" ] && [ "$NODE" != "nil" ]; then if [ "$UDP_PROXY_MODE" != "disable" ] && [ -n "$NODE" ]; then
msg2="${msg}使用 UDP 节点[$(config_n_get $NODE remarks)](TPROXY:${REDIR_PORT})" msg2="${msg}使用 UDP 节点[$(config_n_get $NODE remarks)](TPROXY:${REDIR_PORT})"
$ipt_m -A PSW2 $(comment "默认") -p udp -d $FAKE_IP -j PSW2_RULE $ipt_m -A PSW2 $(comment "默认") -p udp -d $FAKE_IP -j PSW2_RULE
@ -595,7 +597,7 @@ filter_server_port() {
filter_node() { filter_node() {
local node=${1} local node=${1}
local stream=${2} local stream=${2}
if [ -n "$node" ] && [ "$node" != "nil" ]; then if [ -n "$node" ]; then
local address=$(config_n_get $node address) local address=$(config_n_get $node address)
local port=$(config_n_get $node port) local port=$(config_n_get $node port)
[ -z "$address" ] && [ -z "$port" ] && { [ -z "$address" ] && [ -z "$port" ] && {
@ -836,7 +838,7 @@ add_firewall_rule() {
fi fi
} }
if [ "$NODE" != "nil" ] && ([ "$TCP_LOCALHOST_PROXY" = "1" ] || [ "$UDP_LOCALHOST_PROXY" = "1" ]); then if [ -n "$NODE" ] && ([ "$TCP_LOCALHOST_PROXY" = "1" ] || [ "$UDP_LOCALHOST_PROXY" = "1" ]); then
[ -n "$DNS_REDIRECT_PORT" ] && { [ -n "$DNS_REDIRECT_PORT" ] && {
$ipt_n -A OUTPUT $(comment "PSW2") -p udp -o lo --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT $ipt_n -A OUTPUT $(comment "PSW2") -p udp -o lo --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT
$ip6t_n -A OUTPUT $(comment "PSW2") -p udp -o lo --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT 2>/dev/null $ip6t_n -A OUTPUT $(comment "PSW2") -p udp -o lo --dport 53 -j REDIRECT --to-ports $DNS_REDIRECT_PORT 2>/dev/null
@ -846,7 +848,7 @@ add_firewall_rule() {
fi fi
# 加载路由器自身代理 TCP # 加载路由器自身代理 TCP
if [ "$NODE" != "nil" ] && [ "$TCP_LOCALHOST_PROXY" = "1" ]; then if [ -n "$NODE" ] && [ "$TCP_LOCALHOST_PROXY" = "1" ]; then
[ "$accept_icmp" = "1" ] && { [ "$accept_icmp" = "1" ] && {
$ipt_n -A OUTPUT -p icmp -j PSW2_OUTPUT $ipt_n -A OUTPUT -p icmp -j PSW2_OUTPUT
$ipt_n -A PSW2_OUTPUT -p icmp -d $FAKE_IP $(REDIRECT) $ipt_n -A PSW2_OUTPUT -p icmp -d $FAKE_IP $(REDIRECT)
@ -895,7 +897,7 @@ add_firewall_rule() {
fi fi
# 加载路由器自身代理 UDP # 加载路由器自身代理 UDP
if [ "$NODE" != "nil" ] && [ "$UDP_LOCALHOST_PROXY" = "1" ]; then if [ -n "$NODE" ] && [ "$UDP_LOCALHOST_PROXY" = "1" ]; then
$ipt_m -A PSW2_OUTPUT -p udp -d $FAKE_IP -j PSW2_RULE $ipt_m -A PSW2_OUTPUT -p udp -d $FAKE_IP -j PSW2_RULE
add_shunt_t_rule "${SHUNT_LIST4}" "$ipt_m -A PSW2_OUTPUT -p udp $(factor $UDP_REDIR_PORTS "-m multiport --dport")" "-j PSW2_RULE" add_shunt_t_rule "${SHUNT_LIST4}" "$ipt_m -A PSW2_OUTPUT -p udp $(factor $UDP_REDIR_PORTS "-m multiport --dport")" "-j PSW2_RULE"
$ipt_m -A PSW2_OUTPUT -p udp $(factor $UDP_REDIR_PORTS "-m multiport --dport") -j PSW2_RULE $ipt_m -A PSW2_OUTPUT -p udp $(factor $UDP_REDIR_PORTS "-m multiport --dport") -j PSW2_RULE

View File

@ -263,8 +263,8 @@ gen_shunt_list() {
[ "$default_node" = "_direct" ] && default_outbound="direct" [ "$default_node" = "_direct" ] && default_outbound="direct"
local shunt_ids=$(uci show $CONFIG | grep "=shunt_rules" | awk -F '.' '{print $2}' | awk -F '=' '{print $1}') local shunt_ids=$(uci show $CONFIG | grep "=shunt_rules" | awk -F '.' '{print $2}' | awk -F '=' '{print $1}')
for shunt_id in $shunt_ids; do for shunt_id in $shunt_ids; do
local shunt_node=$(config_n_get ${node} "${shunt_id}" nil) local shunt_node=$(config_n_get ${node} "${shunt_id}")
[ "$shunt_node" != "nil" ] && { [ -n "$shunt_node" ] && {
local nftset_v4="passwall2_${node}_${shunt_id}" local nftset_v4="passwall2_${node}_${shunt_id}"
local nftset_v6="passwall2_${node}_${shunt_id}6" local nftset_v6="passwall2_${node}_${shunt_id}6"
gen_nftset $nftset_v4 ipv4_addr 0 0 gen_nftset $nftset_v4 ipv4_addr 0 0
@ -297,7 +297,7 @@ gen_shunt_list() {
_SHUNT_LIST4="${_SHUNT_LIST4} ${_set_name4}:direct" _SHUNT_LIST4="${_SHUNT_LIST4} ${_set_name4}:direct"
_SHUNT_LIST6="${_SHUNT_LIST6} ${_set_name6}:direct" _SHUNT_LIST6="${_SHUNT_LIST6} ${_set_name6}:direct"
} }
[ "$default_node" != "nil" ] && { [ -n "$default_node" ] && {
local nftset_v4="passwall2_${node}_default" local nftset_v4="passwall2_${node}_default"
local nftset_v6="passwall2_${node}_default6" local nftset_v6="passwall2_${node}_default6"
gen_nftset $nftset_v4 ipv4_addr 0 0 gen_nftset $nftset_v4 ipv4_addr 0 0
@ -331,8 +331,8 @@ add_shunt_t_rule() {
load_acl() { load_acl() {
[ "$ENABLED_ACLS" == 1 ] && { [ "$ENABLED_ACLS" == 1 ] && {
acl_app
echolog "访问控制:" echolog "访问控制:"
acl_app
for sid in $(ls -F ${TMP_ACL_PATH} | grep '/$' | awk -F '/' '{print $1}' | grep -v 'default'); do for sid in $(ls -F ${TMP_ACL_PATH} | grep '/$' | awk -F '/' '{print $1}' | grep -v 'default'); do
eval $(uci -q show "${CONFIG}.${sid}" | cut -d'.' -sf 3-) eval $(uci -q show "${CONFIG}.${sid}" | cut -d'.' -sf 3-)
@ -340,24 +340,26 @@ load_acl() {
udp_no_redir_ports=${udp_no_redir_ports:-default} udp_no_redir_ports=${udp_no_redir_ports:-default}
tcp_proxy_mode="global" tcp_proxy_mode="global"
udp_proxy_mode="global" udp_proxy_mode="global"
tcp_redir_ports=${tcp_redir_ports:-default}
udp_redir_ports=${udp_redir_ports:-default}
node=${node:-default} node=${node:-default}
[ "$tcp_no_redir_ports" = "default" ] && tcp_no_redir_ports=$TCP_NO_REDIR_PORTS [ "$tcp_no_redir_ports" = "default" ] && tcp_no_redir_ports=$TCP_NO_REDIR_PORTS
[ "$udp_no_redir_ports" = "default" ] && udp_no_redir_ports=$UDP_NO_REDIR_PORTS [ "$udp_no_redir_ports" = "default" ] && udp_no_redir_ports=$UDP_NO_REDIR_PORTS
[ "$tcp_redir_ports" = "default" ] && tcp_redir_ports=$TCP_REDIR_PORTS [ "$tcp_redir_ports" = "default" ] && tcp_redir_ports=$TCP_REDIR_PORTS
[ "$udp_redir_ports" = "default" ] && udp_redir_ports=$UDP_REDIR_PORTS [ "$udp_redir_ports" = "default" ] && udp_redir_ports=$UDP_REDIR_PORTS
node_remark=$(config_n_get $NODE remarks)
[ -n "$(get_cache_var "ACL_${sid}_node")" ] && node=$(get_cache_var "ACL_${sid}_node") [ -n "$(get_cache_var "ACL_${sid}_node")" ] && node=$(get_cache_var "ACL_${sid}_node")
[ -n "$(get_cache_var "ACL_${sid}_redir_port")" ] && redir_port=$(get_cache_var "ACL_${sid}_redir_port") [ -n "$(get_cache_var "ACL_${sid}_redir_port")" ] && redir_port=$(get_cache_var "ACL_${sid}_redir_port")
[ -n "$(get_cache_var "ACL_${sid}_dns_port")" ] && dns_redirect_port=$(get_cache_var "ACL_${sid}_dns_port") [ -n "$(get_cache_var "ACL_${sid}_dns_port")" ] && dns_redirect_port=$(get_cache_var "ACL_${sid}_dns_port")
[ "$node" = "default" ] && dns_redirect_port=${DNS_REDIRECT_PORT} [ -n "$node" ] && node_remark=$(config_n_get $node remarks)
[ -n "$node" ] && [ "$node" != "default" ] && node_remark=$(config_n_get $node remarks)
write_ipset_direct=${write_ipset_direct:-1} write_ipset_direct=${write_ipset_direct:-1}
[ "${write_ipset_direct}" = "1" ] && { [ "${write_ipset_direct}" = "1" ] && {
if [ "$node" = "default" ]; then if [ -n "$(get_cache_var "ACL_${sid}_default")" ]; then
local nftset_whitelist=${nftset_global_whitelist} local nftset_whitelist=${nftset_global_whitelist}
local nftset_whitelist6=${nftset_global_whitelist6} local nftset_whitelist6=${nftset_global_whitelist6}
shunt_list4=${SHUNT_LIST4}
shunt_list6=${SHUNT_LIST6}
else else
local nftset_whitelist="passwall2_${sid}_whitelist" local nftset_whitelist="passwall2_${sid}_whitelist"
local nftset_whitelist6="passwall2_${sid}_whitelist6" local nftset_whitelist6="passwall2_${sid}_whitelist6"
@ -432,7 +434,7 @@ load_acl() {
fi fi
} }
if ([ "$tcp_proxy_mode" != "disable" ] || [ "$udp_proxy_mode" != "disable" ]) && [ -n "$redir_port" ]; then if ([ "$tcp_proxy_mode" != "disable" ] || [ "$udp_proxy_mode" != "disable" ]) && [ -n "$dns_redirect_port" ]; then
[ -n "$dns_redirect_port" ] && { [ -n "$dns_redirect_port" ] && {
nft "add rule $NFTABLE_NAME PSW2_DNS ip protocol udp ${_ipt_source} udp dport 53 counter redirect to :$dns_redirect_port comment \"$remarks\"" nft "add rule $NFTABLE_NAME PSW2_DNS ip protocol udp ${_ipt_source} udp dport 53 counter redirect to :$dns_redirect_port comment \"$remarks\""
nft "add rule $NFTABLE_NAME PSW2_DNS ip protocol tcp ${_ipt_source} tcp dport 53 counter redirect to :$dns_redirect_port comment \"$remarks\"" nft "add rule $NFTABLE_NAME PSW2_DNS ip protocol tcp ${_ipt_source} tcp dport 53 counter redirect to :$dns_redirect_port comment \"$remarks\""
@ -539,7 +541,7 @@ load_acl() {
fi fi
} }
if ([ "$TCP_PROXY_MODE" != "disable" ] || [ "$UDP_PROXY_MODE" != "disable" ]) && [ "$NODE" != "nil" ]; then if ([ "$TCP_PROXY_MODE" != "disable" ] || [ "$UDP_PROXY_MODE" != "disable" ]) && [ -n "$NODE" ]; then
[ -n "$DNS_REDIRECT_PORT" ] && { [ -n "$DNS_REDIRECT_PORT" ] && {
nft "add rule $NFTABLE_NAME PSW2_DNS ip protocol udp udp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"默认\"" nft "add rule $NFTABLE_NAME PSW2_DNS ip protocol udp udp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"默认\""
nft "add rule $NFTABLE_NAME PSW2_DNS ip protocol tcp tcp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"默认\"" nft "add rule $NFTABLE_NAME PSW2_DNS ip protocol tcp tcp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"默认\""
@ -548,7 +550,7 @@ load_acl() {
} }
fi fi
if [ "$TCP_PROXY_MODE" != "disable" ] && [ "$NODE" != "nil" ]; then if [ "$TCP_PROXY_MODE" != "disable" ] && [ -n "$NODE" ]; then
msg2="${msg}使用 TCP 节点[$(config_n_get $NODE remarks)]" msg2="${msg}使用 TCP 节点[$(config_n_get $NODE remarks)]"
if [ -n "${is_tproxy}" ]; then if [ -n "${is_tproxy}" ]; then
msg2="${msg2}(TPROXY:${REDIR_PORT})" msg2="${msg2}(TPROXY:${REDIR_PORT})"
@ -589,7 +591,7 @@ load_acl() {
echolog "${msg2}" echolog "${msg2}"
fi fi
if [ "$UDP_PROXY_MODE" != "disable" ] && [ "$NODE" != "nil" ]; then if [ "$UDP_PROXY_MODE" != "disable" ] && [ -n "$NODE" ]; then
msg2="${msg}使用 UDP 节点[$(config_n_get $NODE remarks)](TPROXY:${REDIR_PORT})" msg2="${msg}使用 UDP 节点[$(config_n_get $NODE remarks)](TPROXY:${REDIR_PORT})"
nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol udp ip daddr $FAKE_IP counter jump PSW2_RULE comment \"默认\"" nft "add rule $NFTABLE_NAME PSW2_MANGLE ip protocol udp ip daddr $FAKE_IP counter jump PSW2_RULE comment \"默认\""
@ -656,7 +658,7 @@ filter_server_port() {
filter_node() { filter_node() {
local node=${1} local node=${1}
local stream=${2} local stream=${2}
if [ -n "$node" ] && [ "$node" != "nil" ]; then if [ -n "$node" ]; then
local address=$(config_n_get $node address) local address=$(config_n_get $node address)
local port=$(config_n_get $node port) local port=$(config_n_get $node port)
[ -z "$address" ] && [ -z "$port" ] && { [ -z "$address" ] && [ -z "$port" ] && {
@ -889,7 +891,7 @@ add_firewall_rule() {
fi fi
} }
if [ "$NODE" != "nil" ] && ([ "$TCP_LOCALHOST_PROXY" = "1" ] || [ "$UDP_LOCALHOST_PROXY" = "1" ]); then if [ -n "$NODE" ] && ([ "$TCP_LOCALHOST_PROXY" = "1" ] || [ "$UDP_LOCALHOST_PROXY" = "1" ]); then
[ -n "$DNS_REDIRECT_PORT" ] && { [ -n "$DNS_REDIRECT_PORT" ] && {
nft "add rule $NFTABLE_NAME nat_output ip protocol udp oif lo udp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"PSW2\"" nft "add rule $NFTABLE_NAME nat_output ip protocol udp oif lo udp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"PSW2\""
nft "add rule $NFTABLE_NAME nat_output ip protocol tcp oif lo tcp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"PSW2\"" nft "add rule $NFTABLE_NAME nat_output ip protocol tcp oif lo tcp dport 53 counter redirect to :$DNS_REDIRECT_PORT comment \"PSW2\""
@ -899,7 +901,7 @@ add_firewall_rule() {
fi fi
# 加载路由器自身代理 TCP # 加载路由器自身代理 TCP
if [ "$NODE" != "nil" ] && [ "$TCP_LOCALHOST_PROXY" = "1" ]; then if [ -n "$NODE" ] && [ "$TCP_LOCALHOST_PROXY" = "1" ]; then
[ "$accept_icmp" = "1" ] && { [ "$accept_icmp" = "1" ] && {
nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT oif lo ip protocol icmp ip daddr $FAKE_IP counter redirect" nft "add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT oif lo ip protocol icmp ip daddr $FAKE_IP counter redirect"
add_shunt_t_rule "${SHUNT_LIST4}" "nft add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT oif lo ip protocol icmp ip daddr" "counter redirect" add_shunt_t_rule "${SHUNT_LIST4}" "nft add rule $NFTABLE_NAME PSW2_ICMP_REDIRECT oif lo ip protocol icmp ip daddr" "counter redirect"
@ -949,7 +951,7 @@ add_firewall_rule() {
fi fi
# 加载路由器自身代理 UDP # 加载路由器自身代理 UDP
if [ "$NODE" != "nil" ] && [ "$UDP_LOCALHOST_PROXY" = "1" ]; then if [ -n "$NODE" ] && [ "$UDP_LOCALHOST_PROXY" = "1" ]; then
nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE ip protocol udp ip daddr $FAKE_IP counter jump PSW2_RULE" nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE ip protocol udp ip daddr $FAKE_IP counter jump PSW2_RULE"
add_shunt_t_rule "${SHUNT_LIST4}" "nft add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE ip protocol udp $(factor $UDP_REDIR_PORTS "udp dport") ip daddr" "counter jump PSW2_RULE" add_shunt_t_rule "${SHUNT_LIST4}" "nft add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE ip protocol udp $(factor $UDP_REDIR_PORTS "udp dport") ip daddr" "counter jump PSW2_RULE"
nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE ip protocol udp $(factor $UDP_REDIR_PORTS "udp dport") counter jump PSW2_RULE" nft "add rule $NFTABLE_NAME PSW2_OUTPUT_MANGLE ip protocol udp $(factor $UDP_REDIR_PORTS "udp dport") counter jump PSW2_RULE"

View File

@ -57,8 +57,8 @@ test_proxy() {
test_node() { test_node() {
local node_id=$1 local node_id=$1
local _type=$(echo $(config_n_get ${node_id} type nil) | tr 'A-Z' 'a-z') local _type=$(echo $(config_n_get ${node_id} type) | tr 'A-Z' 'a-z')
[ "${_type}" != "nil" ] && { [ -n "${_type}" ] && {
local _tmp_port=$(/usr/share/${CONFIG}/app.sh get_new_port 61080 tcp,udp) local _tmp_port=$(/usr/share/${CONFIG}/app.sh get_new_port 61080 tcp,udp)
/usr/share/${CONFIG}/app.sh run_socks flag="test_node_${node_id}" node=${node_id} bind=127.0.0.1 socks_port=${_tmp_port} config_file=test_node_${node_id}.json /usr/share/${CONFIG}/app.sh run_socks flag="test_node_${node_id}" node=${node_id} bind=127.0.0.1 socks_port=${_tmp_port} config_file=test_node_${node_id}.json
local curlx="socks5h://127.0.0.1:${_tmp_port}" local curlx="socks5h://127.0.0.1:${_tmp_port}"
@ -97,7 +97,7 @@ test_auto_switch() {
fi fi
#检测主节点是否能使用 #检测主节点是否能使用
if [ "$restore_switch" == "1" ] && [ "$main_node" != "nil" ] && [ "$now_node" != "$main_node" ]; then if [ "$restore_switch" == "1" ] && [ -n "$main_node" ] && [ "$now_node" != "$main_node" ]; then
test_node ${main_node} test_node ${main_node}
[ $? -eq 0 ] && { [ $? -eq 0 ] && {
#主节点正常,切换到主节点 #主节点正常,切换到主节点
@ -153,7 +153,7 @@ test_auto_switch() {
start() { start() {
id=$1 id=$1
LOCK_FILE=${LOCK_FILE_DIR}/${CONFIG}_socks_auto_switch_${id}.lock LOCK_FILE=${LOCK_FILE_DIR}/${CONFIG}_socks_auto_switch_${id}.lock
main_node=$(config_n_get $id node nil) main_node=$(config_n_get $id node)
socks_port=$(config_n_get $id port 0) socks_port=$(config_n_get $id port 0)
delay=$(config_n_get $id autoswitch_testing_time 30) delay=$(config_n_get $id autoswitch_testing_time 30)
sleep 5s sleep 5s
@ -161,8 +161,8 @@ start() {
retry_num=$(config_n_get $id autoswitch_retry_num 1) retry_num=$(config_n_get $id autoswitch_retry_num 1)
restore_switch=$(config_n_get $id autoswitch_restore_switch 0) restore_switch=$(config_n_get $id autoswitch_restore_switch 0)
probe_url=$(config_n_get $id autoswitch_probe_url "https://www.google.com/generate_204") probe_url=$(config_n_get $id autoswitch_probe_url "https://www.google.com/generate_204")
backup_node=$(config_n_get $id autoswitch_backup_node nil) backup_node=$(config_n_get $id autoswitch_backup_node)
while [ -n "$backup_node" -a "$backup_node" != "nil" ]; do while [ -n "$backup_node" ]; do
[ -f "$LOCK_FILE" ] && { [ -f "$LOCK_FILE" ] && {
sleep 6s sleep 6s
continue continue

View File

@ -248,7 +248,7 @@ do
currentNode = _node_id and uci:get_all(appname, _node_id) or nil, currentNode = _node_id and uci:get_all(appname, _node_id) or nil,
remarks = "分流" .. e.remarks .. "节点", remarks = "分流" .. e.remarks .. "节点",
set = function(o, server) set = function(o, server)
if not server then server = "nil" end if not server then server = "" end
uci:set(appname, node_id, e[".name"], server) uci:set(appname, node_id, e[".name"], server)
o.newNodeId = server o.newNodeId = server
end end
@ -1234,10 +1234,10 @@ local function truncate_nodes(add_from)
if config.currentNode and config.currentNode.add_mode == "2" then if config.currentNode and config.currentNode.add_mode == "2" then
if add_from then if add_from then
if config.currentNode.add_from and config.currentNode.add_from == add_from then if config.currentNode.add_from and config.currentNode.add_from == add_from then
config.set(config, "nil") config.set(config, "")
end end
else else
config.set(config, "nil") config.set(config, "")
end end
if config.id then if config.id then
uci:delete(appname, config.id) uci:delete(appname, config.id)
@ -1371,7 +1371,7 @@ local function select_node(nodes, config)
config.set(config, server) config.set(config, server)
end end
else else
config.set(config, "nil") config.set(config, "")
end end
end end

View File

@ -30,6 +30,33 @@ do
if [ "$CFG_UPDATE_INT" -ne 0 ]; then if [ "$CFG_UPDATE_INT" -ne 0 ]; then
stop_week_mode=$(config_t_get global_delay stop_week_mode)
stop_interval_mode=$(config_t_get global_delay stop_interval_mode)
stop_interval_mode=$(expr "$stop_interval_mode" \* 60)
if [ -n "$stop_week_mode" ]; then
[ "$stop_week_mode" = "8" ] && {
[ "$(expr "$CFG_UPDATE_INT" % "$stop_interval_mode")" -eq 0 ] && /etc/init.d/$CONFIG stop > /dev/null 2>&1 &
}
fi
start_week_mode=$(config_t_get global_delay start_week_mode)
start_interval_mode=$(config_t_get global_delay start_interval_mode)
start_interval_mode=$(expr "$start_interval_mode" \* 60)
if [ -n "$start_week_mode" ]; then
[ "$start_week_mode" = "8" ] && {
[ "$(expr "$CFG_UPDATE_INT" % "$start_interval_mode")" -eq 0 ] && /etc/init.d/$CONFIG start > /dev/null 2>&1 &
}
fi
restart_week_mode=$(config_t_get global_delay restart_week_mode)
restart_interval_mode=$(config_t_get global_delay restart_interval_mode)
restart_interval_mode=$(expr "$restart_interval_mode" \* 60)
if [ -n "$restart_week_mode" ]; then
[ "$restart_week_mode" = "8" ] && {
[ "$(expr "$CFG_UPDATE_INT" % "$restart_interval_mode")" -eq 0 ] && /etc/init.d/$CONFIG restart > /dev/null 2>&1 &
}
fi
autoupdate=$(config_t_get global_rules auto_update) autoupdate=$(config_t_get global_rules auto_update)
weekupdate=$(config_t_get global_rules week_update) weekupdate=$(config_t_get global_rules week_update)
hourupdate=$(config_t_get global_rules interval_update) hourupdate=$(config_t_get global_rules interval_update)

View File

@ -63,8 +63,8 @@ test_proxy() {
url_test_node() { url_test_node() {
result=0 result=0
local node_id=$1 local node_id=$1
local _type=$(echo $(config_n_get ${node_id} type nil) | tr 'A-Z' 'a-z') local _type=$(echo $(config_n_get ${node_id} type) | tr 'A-Z' 'a-z')
[ "${_type}" != "nil" ] && { [ -n "${_type}" ] && {
local _tmp_port=$(/usr/share/${CONFIG}/app.sh get_new_port 61080 tcp,udp) local _tmp_port=$(/usr/share/${CONFIG}/app.sh get_new_port 61080 tcp,udp)
/usr/share/${CONFIG}/app.sh run_socks flag="url_test_${node_id}" node=${node_id} bind=127.0.0.1 socks_port=${_tmp_port} config_file=url_test_${node_id}.json /usr/share/${CONFIG}/app.sh run_socks flag="url_test_${node_id}" node=${node_id} bind=127.0.0.1 socks_port=${_tmp_port} config_file=url_test_${node_id}.json
local curlx="socks5h://127.0.0.1:${_tmp_port}" local curlx="socks5h://127.0.0.1:${_tmp_port}"
@ -78,8 +78,8 @@ url_test_node() {
test_node() { test_node() {
local node_id=$1 local node_id=$1
local _type=$(echo $(config_n_get ${node_id} type nil) | tr 'A-Z' 'a-z') local _type=$(echo $(config_n_get ${node_id} type) | tr 'A-Z' 'a-z')
[ "${_type}" != "nil" ] && { [ -n "${_type}" ] && {
local _tmp_port=$(/usr/share/${CONFIG}/app.sh get_new_port 61080 tcp,udp) local _tmp_port=$(/usr/share/${CONFIG}/app.sh get_new_port 61080 tcp,udp)
/usr/share/${CONFIG}/app.sh run_socks flag="test_node_${node_id}" node=${node_id} bind=127.0.0.1 socks_port=${_tmp_port} config_file=test_node_${node_id}.json /usr/share/${CONFIG}/app.sh run_socks flag="test_node_${node_id}" node=${node_id} bind=127.0.0.1 socks_port=${_tmp_port} config_file=test_node_${node_id}.json
local curlx="socks5h://127.0.0.1:${_tmp_port}" local curlx="socks5h://127.0.0.1:${_tmp_port}"