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

View File

@ -68,7 +68,7 @@ o.rmempty = false
---- Remarks
o = s:option(Value, "remarks", translate("Remarks"))
o.default = arg[1]
o.rmempty = true
o.rmempty = false
o = s:option(ListValue, "interface", translate("Source Interface"))
o:value("", translate("All"))
@ -165,9 +165,8 @@ sources.write = dynamicList_write
---- 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.default = "default"
o:value("", translate("Use global config") .. "(" .. TCP_NO_REDIR_PORTS .. ")")
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.validate = port_validate
@ -177,53 +176,74 @@ o = s:option(Value, "udp_no_redir_ports", translate("UDP No Redir Ports"),
"<font color='red'>" ..
translate("If you don't want to let the device in the list to go proxy, please choose all.") ..
"</font>")
o.default = "default"
o:value("", translate("Use global config") .. "(" .. UDP_NO_REDIR_PORTS .. ")")
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.validate = port_validate
node = s:option(ListValue, "node", "<a style='color: red'>" .. translate("Node") .. "</a>")
node.default = "default"
node:value("default", translate("Use global config"))
for k, v in pairs(nodes_table) do
node:value(v.id, v["remark"])
o = s:option(DummyValue, "_hide_node_option", "")
o.template = "passwall2/cbi/hidevalue"
o.value = "1"
o:depends({ tcp_no_redir_ports = "1:65535", udp_no_redir_ports = "1:65535" })
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
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
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.default = "default"
o:value("default", translate("Use global config") .. "(" .. TCP_REDIR_PORTS .. ")")
o:value("", translate("Use global config") .. "(" .. TCP_REDIR_PORTS .. ")")
o:value("1:65535", translate("All"))
o:value("22,25,53,143,465,587,853,993,995,80,443", translate("Common Use"))
o:value("80,443", "80,443")
o.validate = port_validate
o:depends({ _hide_node_option = "1", ['!reverse'] = true })
---- 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.default = "default"
o:value("default", translate("Use global config") .. "(" .. UDP_REDIR_PORTS .. ")")
o:value("", translate("Use global config") .. "(" .. UDP_REDIR_PORTS .. ")")
o:value("1:65535", translate("All"))
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.default = "UseIP"
o:value("UseIP")
o:value("UseIPv4")
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.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:value("tcp", "TCP")
o:value("doh", "DoH")
o:value("udp", "UDP")
o:depends({ node = "default", ['!reverse'] = true })
o:depends({ _hide_dns_option = "1", ['!reverse'] = true })
---- DNS Forward
o = s:option(Value, "remote_dns", translate("Remote DNS"))
@ -291,8 +311,8 @@ o.rows = 5
o.wrap = "off"
o:depends({ __hide = true })
o.remove = function(self, section)
local node_value = node:formvalue(arg[1])
if node_value ~= "nil" then
local node_value = s.fields["node"]:formvalue(arg[1])
if node_value then
local node_t = m:get(node_value) or {}
if node_t.type == "Xray" then
AbstractValue.remove(self, section)
@ -301,11 +321,14 @@ o.remove = function(self, section)
end
for k, v in pairs(nodes_table) do
s.fields["node"]:value(v.id, v["remark"])
if v.type == "Xray" then
s.fields["remote_dns_client_ip"]:depends({ node = v.id, remote_dns_protocol = "tcp" })
s.fields["remote_dns_client_ip"]:depends({ node = v.id, remote_dns_protocol = "doh" })
s.fields["dns_hosts"]:depends({ node = v.id })
s.fields["_xray_node"]:depends({ node = v.id })
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

View File

@ -79,14 +79,14 @@ o = s:taboption("Main", Flag, "enabled", translate("Main switch"))
o.rmempty = false
---- Node
node = s:taboption("Main", ListValue, "node", "<a style='color: red'>" .. translate("Node") .. "</a>")
node:value("nil", translate("Close"))
o = s:taboption("Main", ListValue, "node", "<a style='color: red'>" .. translate("Node") .. "</a>")
o:value("", translate("Close"))
-- 分流
if (has_singbox or has_xray) and #nodes_table > 0 then
local function get_cfgvalue(shunt_node_id, option)
return function(self, section)
return m:get(shunt_node_id, option) or "nil"
return m:get(shunt_node_id, option)
end
end
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
type:depends("node", v.id)
else
type:depends("node", "hide") --不存在的依赖,即始终隐藏
type:depends({ __hide = true }) --不存在的依赖,即始终隐藏
end
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.write = get_write(v.id, id)
o:depends("node", v.id)
o.default = "nil"
o:value("nil", translate("Close"))
o.default = ""
o:value("", translate("Close"))
o:value("_default", translate("Default"))
o:value("_direct", translate("Direct Connection"))
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")))
pt.cfgvalue = get_cfgvalue(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.default = "nil"
for k1, v1 in pairs(socks_list) do
o:value(v1.id, v1.remark)
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.cfgvalue = get_cfgvalue(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"))
for k1, v1 in pairs(normal_list) do
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)
return string.format('<a style="color: red">%s</a>', translate("There are no available nodes, please add or subscribe nodes first."))
end
tips:depends({ node = "nil", ["!reverse"] = true })
tips:depends({ node = "", ["!reverse"] = true })
for k, v in pairs(shunt_list) do
tips:depends("node", v.id)
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.default = "1"
node_socks_bind_local:depends({ node = "nil", ["!reverse"] = true })
node_socks_bind_local:depends({ node = "", ["!reverse"] = true })
s:tab("DNS", translate("DNS"))
@ -316,8 +316,8 @@ o.rows = 5
o.wrap = "off"
o:depends({ __hide = true })
o.remove = function(self, section)
local node_value = node:formvalue(global_cfgid)
if node_value ~= "nil" then
local node_value = s.fields["node"]:formvalue(global_cfgid)
if node_value then
local node_t = m:get(node_value) or {}
if node_t.type == "Xray" then
AbstractValue.remove(self, section)
@ -336,13 +336,14 @@ function o.write(e, e)
luci.http.redirect(api.url("log"))
end
for k, v in pairs(nodes_table) do
if v.type == "Xray" then
s.fields["remote_dns_client_ip"]:depends({ node = v.id, remote_dns_protocol = "tcp" })
s.fields["remote_dns_client_ip"]:depends({ node = v.id, remote_dns_protocol = "doh" })
s.fields["dns_hosts"]:depends({ node = v.id })
end
end
o = s:taboption("DNS", DummyValue, "_xray_node", "")
o.template = "passwall2/cbi/hidevalue"
o.value = "1"
o:depends({ __hide = true })
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" })
s:tab("log", translate("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.rmempty = false
s = m:section(TypedSection, "socks", translate("Socks Config"))
s.template = "cbi/tblsection"
s.anonymous = true
s.addremove = true
s.extedit = api.url("socks_config", "%s")
function s.create(e, t)
s2 = m:section(TypedSection, "socks", translate("Socks Config"))
s2.template = "cbi/tblsection"
s2.anonymous = true
s2.addremove = true
s2.extedit = api.url("socks_config", "%s")
function s2.create(e, t)
local uuid = api.gen_short_uuid()
t = uuid
TypedSection.create(e, t)
luci.http.redirect(e.extedit:format(t))
end
o = s:option(DummyValue, "status", translate("Status"))
o = s2:option(DummyValue, "status", translate("Status"))
o.rawhtml = true
o.cfgvalue = function(t, n)
return string.format('<div class="_status" socks_id="%s"></div>', n)
end
---- Enable
o = s:option(Flag, "enabled", translate("Enable"))
o = s2:option(Flag, "enabled", translate("Enable"))
o.default = 1
o.rmempty = false
socks_node = s:option(ListValue, "node", translate("Socks Node"))
o = s2:option(ListValue, "node", translate("Socks Node"))
local n = 1
uci:foreach(appname, "socks", function(s)
@ -398,25 +399,22 @@ uci:foreach(appname, "socks", function(s)
n = n + 1
end)
o = s:option(Value, "port", "Socks " .. translate("Listen Port"))
o = s2:option(Value, "port", "Socks " .. translate("Listen Port"))
o.default = n + 1080
o.datatype = "port"
o.rmempty = false
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.datatype = "port"
end
for k, v in pairs(nodes_table) do
node:value(v.id, v["remark"])
if v.type == "Socks" then
if has_singbox or has_xray then
socks_node:value(v.id, v["remark"])
end
else
socks_node:value(v.id, v["remark"])
s.fields["node"]:value(v.id, v["remark"])
s2.fields["node"]:value(v.id, v["remark"])
if v.type == "Xray" then
s.fields["_xray_node"]:depends({ node = v.id })
end
end

View File

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

View File

@ -19,43 +19,46 @@ s = m:section(TypedSection, "global_delay", translate("Delay Settings"))
s.anonymous = true
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
o = s:option(Flag, "start_daemon", translate("Open and close Daemon"))
o.default = 1
o.rmempty = false
--[[
---- Open and close automatically
o = s:option(Flag, "auto_on", translate("Open and close automatically"))
o.default = 0
o.rmempty = false
---- Delay Start
o = s:option(Value, "start_delay", translate("Delay Start"), translate("Units:seconds"))
o.default = "1"
o.rmempty = true
---- Automatically turn off time
o = s:option(ListValue, "time_off", translate("Automatically turn off time"))
o.default = nil
o:depends("auto_on", true)
o:value(nil, translate("Disable"))
for e = 0, 23 do o:value(e, e .. translate("oclock")) end
for index, value in ipairs({"stop", "start", "restart"}) do
o = s:option(ListValue, value .. "_week_mode", translate(value .. " automatically mode"))
o:value("", translate("Disable"))
o:value(8, translate("Loop Mode"))
o:value(7, translate("Every day"))
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, "time_on", translate("Automatically turn on time"))
o.default = nil
o:depends("auto_on", true)
o:value(nil, translate("Disable"))
for e = 0, 23 do o:value(e, e .. translate("oclock")) end
o = s:option(ListValue, value .. "_time_mode", translate(value .. " Time(Every day)"))
for t = 0, 23 do o:value(t, t .. ":00") end
o.default = 0
o:depends(value .. "_week_mode", "0")
o:depends(value .. "_week_mode", "1")
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, "time_restart", translate("Automatically restart time"))
o.default = nil
o:depends("auto_on", true)
o:value(nil, translate("Disable"))
for e = 0, 23 do o:value(e, e .. translate("oclock")) end
--]]
o = s:option(ListValue, value .. "_interval_mode", translate(value .. " Interval(Hour)"))
for t = 1, 24 do o:value(t, t .. " " .. translate("Hour")) end
o.default = 2
o:depends(value .. "_week_mode", "8")
end
-- [[ 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 function option_name(name)
local function _n(name)
return option_prefix .. name
end
@ -18,58 +18,58 @@ end
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 = 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 = 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 = s:option(Value, option_name("obfs"), translate("Obfs Password"))
o = s:option(Value, _n("obfs"), translate("Obfs Password"))
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.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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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 = 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.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.rewrite_option = o.option

View File

@ -10,7 +10,7 @@ local type_name = "Naiveproxy"
local option_prefix = "naive_"
local function option_name(name)
local function _n(name)
return option_prefix .. name
end
@ -18,18 +18,18 @@ end
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("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 = 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
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 function option_name(name)
local function _n(name)
return option_prefix .. name
end
@ -33,7 +33,7 @@ local xray_version = api.get_app_version("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("vless", translate("VLESS"))
o:value("http", translate("HTTP"))
@ -45,9 +45,9 @@ o:value("_balancing", translate("Balancing"))
o:value("_shunt", translate("Shunt"))
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:depends({ [option_name("protocol")] = "_iface" })
o:depends({ [_n("protocol")] = "_iface" })
local nodes_table = {}
local balancers_table = {}
@ -96,12 +96,12 @@ uci:foreach(appname, "socks", function(s)
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>"))
o:depends({ [option_name("protocol")] = "_balancing" })
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({ [_n("protocol")] = "_balancing" })
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"))
o:depends({ [option_name("protocol")] = "_balancing" })
local o = s:option(ListValue, _n("balancingStrategy"), translate("Balancing Strategy"))
o:depends({ [_n("protocol")] = "_balancing" })
o:value("random")
o:value("roundRobin")
o:value("leastPing")
@ -109,11 +109,11 @@ o.default = "leastPing"
-- Fallback Node
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
o:depends({ [option_name("protocol")] = "_balancing" })
o:depends({ [_n("protocol")] = "_balancing" })
else
o:depends({ [option_name("balancingStrategy")] = "leastPing" })
o:depends({ [_n("balancingStrategy")] = "leastPing" })
end
local function check_fallback_chain(fb)
for k, v in pairs(fallback_table) do
@ -132,11 +132,11 @@ if api.compare_versions(xray_version, ">=", "1.8.10") then
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."))
ucpu:depends({ [option_name("balancingStrategy")] = "leastPing" })
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({ [_n("balancingStrategy")] = "leastPing" })
local pu = s:option(Value, option_name("probeUrl"), translate("Probe URL"))
pu:depends({ [option_name("useCustomProbeUrl")] = true })
local pu = s:option(Value, _n("probeUrl"), translate("Probe URL"))
pu:depends({ [_n("useCustomProbeUrl")] = true })
pu:value("https://cp.cloudflare.com/", "Cloudflare")
pu:value("https://www.gstatic.com/generate_204", "Gstatic")
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.")
-- 探测间隔
local pi = s:option(Value, option_name("probeInterval"), translate("Probe Interval"))
pi:depends({ [option_name("balancingStrategy")] = "leastPing" })
local pi = s:option(Value, _n("probeInterval"), translate("Probe Interval"))
pi:depends({ [_n("balancingStrategy")] = "leastPing" })
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.")
if api.compare_versions(xray_version, ">=", "1.8.12") then
ucpu:depends({ [option_name("protocol")] = "_balancing" })
pi:depends({ [option_name("protocol")] = "_balancing" })
ucpu:depends({ [_n("protocol")] = "_balancing" })
pi:depends({ [_n("protocol")] = "_balancing" })
else
ucpu:depends({ [option_name("balancingStrategy")] = "leastPing" })
pi:depends({ [option_name("balancingStrategy")] = "leastPing" })
ucpu:depends({ [_n("balancingStrategy")] = "leastPing" })
pi:depends({ [_n("balancingStrategy")] = "leastPing" })
end
-- [[ 分流模块 ]]
if #nodes_table > 0 then
o = s:option(Flag, option_name("preproxy_enabled"), translate("Preproxy"))
o:depends({ [option_name("protocol")] = "_shunt" })
o = s:option(Flag, _n("preproxy_enabled"), translate("Preproxy"))
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:depends({ [option_name("protocol")] = "_shunt", [option_name("preproxy_enabled")] = true })
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({ [_n("protocol")] = "_shunt", [_n("preproxy_enabled")] = true })
for k, v in pairs(socks_list) do
o:value(v.id, v.remark)
end
@ -180,16 +180,18 @@ if #nodes_table > 0 then
for k, v in pairs(nodes_table) do
o:value(v.id, v.remark)
end
o.default = "nil"
if #o.keylist > 0 then
o.default = o.keylist[1]
end
end
uci:foreach(appname, "shunt_rules", function(e)
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:value("nil", translate("Close"))
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("", translate("Close"))
o:value("_default", translate("Default"))
o:value("_direct", translate("Direct Connection"))
o:value("_blackhole", translate("Blackhole"))
o:depends({ [option_name("protocol")] = "_shunt" })
o:depends({ [_n("protocol")] = "_shunt" })
if #nodes_table > 0 then
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
o:value(v.id, v.remark)
end
local pt = s:option(ListValue, option_name(e[".name"] .. "_proxy_tag"), string.format('* <a style="color:red">%s</a>', e.remarks .. " " .. translate("Preproxy")))
pt:value("nil", translate("Close"))
local pt = s:option(ListValue, _n(e[".name"] .. "_proxy_tag"), string.format('* <a style="color:red">%s</a>', e.remarks .. " " .. translate("Preproxy")))
pt:value("", translate("Close"))
pt:value("main", translate("Preproxy Node"))
pt.default = "nil"
for k, v in pairs(nodes_table) do
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)
o = s:option(DummyValue, option_name("shunt_tips"), " ")
o = s:option(DummyValue, _n("shunt_tips"), " ")
o.not_rewrite = true
o.rawhtml = true
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."))
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")))
o:depends({ [option_name("protocol")] = "_shunt" })
local o = s:option(ListValue, _n("default_node"), string.format('* <a style="color:red">%s</a>', translate("Default")))
o:depends({ [_n("protocol")] = "_shunt" })
o:value("_direct", translate("Direct Connection"))
o:value("_blackhole", translate("Blackhole"))
@ -236,17 +237,16 @@ if #nodes_table > 0 then
for k, v in pairs(iface_table) do
o:value(v.id, v.remark)
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."))
dpt:value("nil", translate("Close"))
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("", translate("Close"))
dpt:value("main", translate("Preproxy Node"))
dpt.default = "nil"
for k, v in pairs(nodes_table) do
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
o = s:option(ListValue, option_name("domainStrategy"), translate("Domain Strategy"))
o = s:option(ListValue, _n("domainStrategy"), translate("Domain Strategy"))
o:value("AsIs")
o:value("IPIfNonMatch")
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("'IPOnDemand': As long as there is a IP-based rule, resolves the domain into IP immediately.")
.. "</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("linear")
o:depends({ [option_name("protocol")] = "_shunt" })
o:depends({ [_n("protocol")] = "_shunt" })
-- [[ 分流模块 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"
local protocols = s.fields[option_name("protocol")].keylist
local protocols = s.fields[_n("protocol")].keylist
if #protocols > 0 then
for index, value in ipairs(protocols) do
if not value:find("_") then
s.fields[option_name("address")]:depends({ [option_name("protocol")] = value })
s.fields[option_name("port")]:depends({ [option_name("protocol")] = value })
s.fields[_n("address")]:depends({ [_n("protocol")] = value })
s.fields[_n("port")]:depends({ [_n("protocol")] = value })
end
end
end
o = s:option(Value, option_name("username"), translate("Username"))
o:depends({ [option_name("protocol")] = "http" })
o:depends({ [option_name("protocol")] = "socks" })
o = s:option(Value, _n("username"), translate("Username"))
o:depends({ [_n("protocol")] = "http" })
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:depends({ [option_name("protocol")] = "http" })
o:depends({ [option_name("protocol")] = "socks" })
o:depends({ [option_name("protocol")] = "shadowsocks" })
o:depends({ [option_name("protocol")] = "trojan" })
o:depends({ [_n("protocol")] = "http" })
o:depends({ [_n("protocol")] = "socks" })
o:depends({ [_n("protocol")] = "shadowsocks" })
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
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: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"
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:depends({ [option_name("protocol")] = "shadowsocks", [option_name("ss_method")] = "aes-128-gcm" })
o:depends({ [option_name("protocol")] = "shadowsocks", [option_name("ss_method")] = "aes-256-gcm" })
o:depends({ [option_name("protocol")] = "shadowsocks", [option_name("ss_method")] = "chacha20-poly1305" })
o:depends({ [option_name("protocol")] = "shadowsocks", [option_name("ss_method")] = "xchacha20-poly1305" })
o = s:option(Flag, _n("iv_check"), translate("IV Check"))
o:depends({ [_n("protocol")] = "shadowsocks", [_n("ss_method")] = "aes-128-gcm" })
o:depends({ [_n("protocol")] = "shadowsocks", [_n("ss_method")] = "aes-256-gcm" })
o:depends({ [_n("protocol")] = "shadowsocks", [_n("ss_method")] = "chacha20-poly1305" })
o:depends({ [_n("protocol")] = "shadowsocks", [_n("ss_method")] = "xchacha20-poly1305" })
o = s:option(Flag, option_name("uot"), translate("UDP over TCP"))
o:depends({ [option_name("protocol")] = "shadowsocks" })
o = s:option(Flag, _n("uot"), translate("UDP over TCP"))
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:depends({ [option_name("protocol")] = "vmess" })
o:depends({ [option_name("protocol")] = "vless" })
o:depends({ [_n("protocol")] = "vmess" })
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:value("", translate("Disable"))
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:depends({ [option_name("protocol")] = "vmess" })
o:depends({ [option_name("protocol")] = "vless" })
o:depends({ [option_name("protocol")] = "http" })
o:depends({ [option_name("protocol")] = "socks" })
o:depends({ [option_name("protocol")] = "trojan" })
o:depends({ [option_name("protocol")] = "shadowsocks" })
o:depends({ [_n("protocol")] = "vmess" })
o:depends({ [_n("protocol")] = "vless" })
o:depends({ [_n("protocol")] = "http" })
o:depends({ [_n("protocol")] = "socks" })
o:depends({ [_n("protocol")] = "trojan" })
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:depends({ [option_name("tls")] = true, [option_name("transport")] = "raw" })
o:depends({ [option_name("tls")] = true, [option_name("transport")] = "h2" })
o:depends({ [option_name("tls")] = true, [option_name("transport")] = "grpc" })
o:depends({ [option_name("tls")] = true, [option_name("transport")] = "xhttp" })
o:depends({ [_n("tls")] = true, [_n("transport")] = "raw" })
o:depends({ [_n("tls")] = true, [_n("transport")] = "h2" })
o:depends({ [_n("tls")] = true, [_n("transport")] = "grpc" })
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:value("default", translate("Default"))
o:value("h3")
@ -349,36 +349,36 @@ o:value("h3,h2")
o:value("http/1.1")
o:value("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: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:depends({ [option_name("tls")] = true })
o = s:option(Value, _n("tls_serverName"), translate("Domain"))
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:depends({ [option_name("tls")] = true, [option_name("reality")] = false })
o:depends({ [_n("tls")] = true, [_n("reality")] = false })
-- [[ REALITY部分 ]] --
o = s:option(Value, option_name("reality_publicKey"), translate("Public Key"))
o:depends({ [option_name("tls")] = true, [option_name("reality")] = true })
o = s:option(Value, _n("reality_publicKey"), translate("Public Key"))
o:depends({ [_n("tls")] = true, [_n("reality")] = true })
o = s:option(Value, option_name("reality_shortId"), translate("Short Id"))
o:depends({ [option_name("tls")] = true, [option_name("reality")] = true })
o = s:option(Value, _n("reality_shortId"), translate("Short Id"))
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: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: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("firefox")
o:value("edge")
@ -390,10 +390,10 @@ o:value("android")
o:value("random")
o:value("randomized")
o.default = "chrome"
o:depends({ [option_name("tls")] = true, [option_name("utls")] = true })
o:depends({ [option_name("tls")] = true, [option_name("reality")] = true })
o:depends({ [_n("tls")] = true, [_n("utls")] = 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("mkcp", "mKCP")
o:value("ws", "WebSocket")
@ -403,193 +403,193 @@ o:value("quic", "QUIC")
o:value("grpc", "gRPC")
o:value("httpupgrade", "HttpUpgrade")
o:value("xhttp", "XHTTP (SplitHTTP)")
o:depends({ [option_name("protocol")] = "vmess" })
o:depends({ [option_name("protocol")] = "vless" })
o:depends({ [option_name("protocol")] = "socks" })
o:depends({ [option_name("protocol")] = "shadowsocks" })
o:depends({ [option_name("protocol")] = "trojan" })
o:depends({ [_n("protocol")] = "vmess" })
o:depends({ [_n("protocol")] = "vless" })
o:depends({ [_n("protocol")] = "socks" })
o:depends({ [_n("protocol")] = "shadowsocks" })
o:depends({ [_n("protocol")] = "trojan" })
o = s:option(Value, option_name("wireguard_public_key"), translate("Public Key"))
o:depends({ [option_name("protocol")] = "wireguard" })
o = s:option(Value, _n("wireguard_public_key"), translate("Public Key"))
o:depends({ [_n("protocol")] = "wireguard" })
o = s:option(Value, option_name("wireguard_secret_key"), translate("Private Key"))
o:depends({ [option_name("protocol")] = "wireguard" })
o = s:option(Value, _n("wireguard_secret_key"), translate("Private Key"))
o:depends({ [_n("protocol")] = "wireguard" })
o = s:option(Value, option_name("wireguard_preSharedKey"), translate("Pre shared key"))
o:depends({ [option_name("protocol")] = "wireguard" })
o = s:option(Value, _n("wireguard_preSharedKey"), translate("Pre shared key"))
o:depends({ [_n("protocol")] = "wireguard" })
o = s:option(DynamicList, option_name("wireguard_local_address"), translate("Local Address"))
o:depends({ [option_name("protocol")] = "wireguard" })
o = s:option(DynamicList, _n("wireguard_local_address"), translate("Local Address"))
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:depends({ [option_name("protocol")] = "wireguard" })
o:depends({ [_n("protocol")] = "wireguard" })
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:depends({ [option_name("protocol")] = "wireguard" })
o = s:option(Value, _n("wireguard_reserved"), translate("Reserved"), translate("Decimal numbers separated by \",\" or Base64-encoded strings."))
o:depends({ [_n("protocol")] = "wireguard" })
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:depends({ [option_name("protocol")] = "wireguard" })
o:depends({ [_n("protocol")] = "wireguard" })
-- [[ RAW部分 ]]--
-- 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("http", "http")
o:depends({ [option_name("transport")] = "raw" })
o:depends({ [_n("transport")] = "raw" })
-- HTTP域名
o = s:option(DynamicList, option_name("tcp_guise_http_host"), translate("HTTP Host"))
o:depends({ [option_name("tcp_guise")] = "http" })
o = s:option(DynamicList, _n("tcp_guise_http_host"), translate("HTTP Host"))
o:depends({ [_n("tcp_guise")] = "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:depends({ [option_name("tcp_guise")] = "http" })
o:depends({ [_n("tcp_guise")] = "http" })
-- [[ 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
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: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: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: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:depends({ [option_name("transport")] = "mkcp" })
o:depends({ [_n("transport")] = "mkcp" })
o = s:option(Flag, option_name("mkcp_congestion"), translate("KCP Congestion"))
o:depends({ [option_name("transport")] = "mkcp" })
o = s:option(Flag, _n("mkcp_congestion"), translate("KCP Congestion"))
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: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:depends({ [option_name("transport")] = "mkcp" })
o:depends({ [_n("transport")] = "mkcp" })
o = s:option(Value, option_name("mkcp_seed"), translate("KCP Seed"))
o:depends({ [option_name("transport")] = "mkcp" })
o = s:option(Value, _n("mkcp_seed"), translate("KCP Seed"))
o:depends({ [_n("transport")] = "mkcp" })
-- [[ WebSocket部分 ]]--
o = s:option(Value, option_name("ws_host"), translate("WebSocket Host"))
o:depends({ [option_name("transport")] = "ws" })
o = s:option(Value, _n("ws_host"), translate("WebSocket Host"))
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: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:depends({ [option_name("transport")] = "ws" })
o:depends({ [_n("transport")] = "ws" })
-- [[ HTTP/2部分 ]]--
o = s:option(Value, option_name("h2_host"), translate("HTTP/2 Host"))
o:depends({ [option_name("transport")] = "h2" })
o = s:option(Value, _n("h2_host"), translate("HTTP/2 Host"))
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:depends({ [option_name("transport")] = "h2" })
o:depends({ [_n("transport")] = "h2" })
o = s:option(Flag, option_name("h2_health_check"), translate("Health check"))
o:depends({ [option_name("transport")] = "h2" })
o = s:option(Flag, _n("h2_health_check"), translate("Health check"))
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: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:depends({ [option_name("h2_health_check")] = true })
o:depends({ [_n("h2_health_check")] = true })
-- [[ DomainSocket部分 ]]--
o = s:option(Value, option_name("ds_path"), "Path", translate("A legal file path. This file must not exist before running."))
o:depends({ [option_name("transport")] = "ds" })
o = s:option(Value, _n("ds_path"), "Path", translate("A legal file path. This file must not exist before running."))
o:depends({ [_n("transport")] = "ds" })
-- [[ 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("aes-128-gcm")
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:depends({ [option_name("transport")] = "quic" })
o = s:option(Value, _n("quic_key"), translate("Encrypt Method") .. translate("Key"))
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
o:depends({ [option_name("transport")] = "quic" })
o:depends({ [_n("transport")] = "quic" })
-- [[ gRPC部分 ]]--
o = s:option(Value, option_name("grpc_serviceName"), "ServiceName")
o:depends({ [option_name("transport")] = "grpc" })
o = s:option(Value, _n("grpc_serviceName"), "ServiceName")
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("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:depends({ [option_name("transport")] = "grpc" })
o = s:option(Flag, _n("grpc_health_check"), translate("Health check"))
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: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: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: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:depends({ [option_name("transport")] = "grpc" })
o:depends({ [_n("transport")] = "grpc" })
-- [[ HttpUpgrade部分 ]]--
o = s:option(Value, option_name("httpupgrade_host"), translate("HttpUpgrade Host"))
o:depends({ [option_name("transport")] = "httpupgrade" })
o = s:option(Value, _n("httpupgrade_host"), translate("HttpUpgrade Host"))
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:depends({ [option_name("transport")] = "httpupgrade" })
o:depends({ [_n("transport")] = "httpupgrade" })
-- [[ XHTTP部分 ]]--
o = s:option(ListValue, option_name("xhttp_mode"), "XHTTP " .. translate("Mode"))
o:depends({ [option_name("transport")] = "xhttp" })
o = s:option(ListValue, _n("xhttp_mode"), "XHTTP " .. translate("Mode"))
o:depends({ [_n("transport")] = "xhttp" })
o.default = "auto"
o:value("auto")
o:value("packet-up")
o:value("stream-up")
o:value("stream-one")
o = s:option(Value, option_name("xhttp_host"), translate("XHTTP Host"))
o:depends({ [option_name("transport")] = "xhttp" })
o = s:option(Value, _n("xhttp_host"), translate("XHTTP Host"))
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: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:depends({ [option_name("transport")] = "xhttp" })
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({ [_n("transport")] = "xhttp" })
o.rows = 15
o.wrap = "off"
o.custom_write = function(self, section, value)
@ -618,63 +618,63 @@ o.validate = function(self, value)
end
-- [[ Mux.Cool ]]--
o = s:option(Flag, option_name("mux"), "Mux", translate("Enable Mux.Cool"))
o:depends({ [option_name("protocol")] = "vmess" })
o:depends({ [option_name("protocol")] = "vless", [option_name("flow")] = "" })
o:depends({ [option_name("protocol")] = "http" })
o:depends({ [option_name("protocol")] = "socks" })
o:depends({ [option_name("protocol")] = "shadowsocks" })
o:depends({ [option_name("protocol")] = "trojan" })
o = s:option(Flag, _n("mux"), "Mux", translate("Enable Mux.Cool"))
o:depends({ [_n("protocol")] = "vmess" })
o:depends({ [_n("protocol")] = "vless", [_n("flow")] = "" })
o:depends({ [_n("protocol")] = "http" })
o:depends({ [_n("protocol")] = "socks" })
o:depends({ [_n("protocol")] = "shadowsocks" })
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:depends({ [option_name("mux")] = true })
o:depends({ [_n("mux")] = true })
-- [[ XUDP Mux ]]--
o = s:option(Flag, option_name("xmux"), "XUDP Mux")
o = s:option(Flag, _n("xmux"), "XUDP Mux")
o.default = 1
o:depends({ [option_name("protocol")] = "vless", [option_name("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" })
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:depends({ [option_name("xmux")] = true })
o:depends({ [_n("xmux")] = true })
--[[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 = s:option(Flag, option_name("tcpNoDelay"), "tcpNoDelay")
o = s:option(Flag, _n("tcpNoDelay"), "tcpNoDelay")
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("1", translate("Preproxy 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
o:depends({ [option_name("protocol")] = v })
o:depends({ [_n("protocol")] = v })
end
end
o = s:option(ListValue, option_name("preproxy_node"), translate("Preproxy Node"), translate("Only support a layer of proxy."))
o:depends({ [option_name("chain_proxy")] = "1" })
o = s:option(ListValue, _n("preproxy_node"), translate("Preproxy Node"), translate("Only support a layer of proxy."))
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:depends({ [option_name("chain_proxy")] = "2" })
o = s:option(ListValue, _n("to_node"), translate("Landing Node"), translate("Only support a layer of proxy."))
o:depends({ [_n("chain_proxy")] = "2" })
for k, v in pairs(nodes_table) do
if v.type == "Xray" and v.id ~= arg[1] then
s.fields[option_name("preproxy_node")]:value(v.id, v.remark)
s.fields[option_name("to_node")]:value(v.id, v.remark)
s.fields[_n("preproxy_node")]:value(v.id, v.remark)
s.fields[_n("to_node")]:value(v.id, v.remark)
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
s.fields[option_name("tcpMptcp")]:depends({ [option_name("protocol")] = v })
s.fields[option_name("tcpNoDelay")]:depends({ [option_name("protocol")] = v })
s.fields[option_name("chain_proxy")]:depends({ [option_name("protocol")] = v })
s.fields[_n("tcpMptcp")]:depends({ [_n("protocol")] = v })
s.fields[_n("tcpNoDelay")]:depends({ [_n("protocol")] = v })
s.fields[_n("chain_proxy")]:depends({ [_n("protocol")] = v })
end
end

View File

@ -17,7 +17,7 @@ local type_name = "sing-box"
local option_prefix = "singbox_"
local function option_name(name)
local function _n(name)
return option_prefix .. name
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"))
o = s:option(ListValue, option_name("protocol"), translate("Protocol"))
o = s:option(ListValue, _n("protocol"), translate("Protocol"))
o:value("socks", "Socks")
o:value("http", "HTTP")
o:value("shadowsocks", "Shadowsocks")
@ -60,9 +60,9 @@ end
o:value("_shunt", translate("Shunt"))
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:depends({ [option_name("protocol")] = "_iface" })
o:depends({ [_n("protocol")] = "_iface" })
local nodes_table = {}
local iface_table = {}
@ -94,11 +94,11 @@ end)
-- [[ 分流模块 ]]
if #nodes_table > 0 then
o = s:option(Flag, option_name("preproxy_enabled"), translate("Preproxy"))
o:depends({ [option_name("protocol")] = "_shunt" })
o = s:option(Flag, _n("preproxy_enabled"), translate("Preproxy"))
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:depends({ [option_name("protocol")] = "_shunt", [option_name("preproxy_enabled")] = true })
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({ [_n("protocol")] = "_shunt", [_n("preproxy_enabled")] = true })
for k, v in pairs(socks_list) do
o:value(v.id, v.remark)
end
@ -108,16 +108,18 @@ if #nodes_table > 0 then
for k, v in pairs(nodes_table) do
o:value(v.id, v.remark)
end
o.default = "nil"
if #o.keylist > 0 then
o.default = o.keylist[1]
end
end
uci:foreach(appname, "shunt_rules", function(e)
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:value("nil", translate("Close"))
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("", translate("Close"))
o:value("_default", translate("Default"))
o:value("_direct", translate("Direct Connection"))
o:value("_blackhole", translate("Blackhole"))
o:depends({ [option_name("protocol")] = "_shunt" })
o:depends({ [_n("protocol")] = "_shunt" })
if #nodes_table > 0 then
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
o:value(v.id, v.remark)
end
local pt = s:option(ListValue, option_name(e[".name"] .. "_proxy_tag"), string.format('* <a style="color:red">%s</a>', e.remarks .. " " .. translate("Preproxy")))
pt:value("nil", translate("Close"))
local pt = s:option(ListValue, _n(e[".name"] .. "_proxy_tag"), string.format('* <a style="color:red">%s</a>', e.remarks .. " " .. translate("Preproxy")))
pt:value("", translate("Close"))
pt:value("main", translate("Preproxy Node"))
pt.default = "nil"
for k, v in pairs(nodes_table) do
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)
o = s:option(DummyValue, option_name("shunt_tips"), " ")
o = s:option(DummyValue, _n("shunt_tips"), " ")
o.not_rewrite = true
o.rawhtml = true
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."))
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")))
o:depends({ [option_name("protocol")] = "_shunt" })
local o = s:option(ListValue, _n("default_node"), string.format('* <a style="color:red">%s</a>', translate("Default")))
o:depends({ [_n("protocol")] = "_shunt" })
o:value("_direct", translate("Direct Connection"))
o:value("_blackhole", translate("Blackhole"))
@ -158,61 +159,60 @@ if #nodes_table > 0 then
for k, v in pairs(iface_table) do
o:value(v.id, v.remark)
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."))
dpt:value("nil", translate("Close"))
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("", translate("Close"))
dpt:value("main", translate("Preproxy Node"))
dpt.default = "nil"
for k, v in pairs(nodes_table) do
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 ]]
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"
local protocols = s.fields[option_name("protocol")].keylist
local protocols = s.fields[_n("protocol")].keylist
if #protocols > 0 then
for index, value in ipairs(protocols) do
if not value:find("_") then
s.fields[option_name("address")]:depends({ [option_name("protocol")] = value })
s.fields[option_name("port")]:depends({ [option_name("protocol")] = value })
s.fields[_n("address")]:depends({ [_n("protocol")] = value })
s.fields[_n("port")]:depends({ [_n("protocol")] = value })
end
end
end
o = s:option(Value, option_name("username"), translate("Username"))
o:depends({ [option_name("protocol")] = "http" })
o:depends({ [option_name("protocol")] = "socks" })
o = s:option(Value, _n("username"), translate("Username"))
o:depends({ [_n("protocol")] = "http" })
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:depends({ [option_name("protocol")] = "http" })
o:depends({ [option_name("protocol")] = "socks" })
o:depends({ [option_name("protocol")] = "shadowsocks" })
o:depends({ [option_name("protocol")] = "shadowsocksr" })
o:depends({ [option_name("protocol")] = "trojan" })
o:depends({ [option_name("protocol")] = "tuic" })
o:depends({ [_n("protocol")] = "http" })
o:depends({ [_n("protocol")] = "socks" })
o:depends({ [_n("protocol")] = "shadowsocks" })
o:depends({ [_n("protocol")] = "shadowsocksr" })
o:depends({ [_n("protocol")] = "trojan" })
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
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"
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
o:depends({ [option_name("protocol")] = "shadowsocks" })
o:depends({ [_n("protocol")] = "shadowsocks" })
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"
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 = {
"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"
}
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
o:depends({ [option_name("protocol")] = "shadowsocksr" })
o:depends({ [_n("protocol")] = "shadowsocksr" })
o = s:option(Value, option_name("ssr_protocol_param"), translate("Protocol_param"))
o:depends({ [option_name("protocol")] = "shadowsocksr" })
o = s:option(Value, _n("ssr_protocol_param"), translate("Protocol_param"))
o:depends({ [_n("protocol")] = "shadowsocksr" })
local ssr_obfs_list = {
"plain", "http_simple", "http_post", "random_head", "tls_simple",
"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
o:depends({ [option_name("protocol")] = "shadowsocksr" })
o:depends({ [_n("protocol")] = "shadowsocksr" })
o = s:option(Value, option_name("ssr_obfs_param"), translate("Obfs_param"))
o:depends({ [option_name("protocol")] = "shadowsocksr" })
o = s:option(Value, _n("ssr_obfs_param"), translate("Obfs_param"))
o:depends({ [_n("protocol")] = "shadowsocksr" })
end
o = s:option(Flag, option_name("uot"), translate("UDP over TCP"))
o:depends({ [option_name("protocol")] = "socks" })
o:depends({ [option_name("protocol")] = "shadowsocks" })
o = s:option(Flag, _n("uot"), translate("UDP over TCP"))
o:depends({ [_n("protocol")] = "socks" })
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:depends({ [option_name("protocol")] = "vmess" })
o:depends({ [option_name("protocol")] = "vless" })
o:depends({ [option_name("protocol")] = "tuic" })
o:depends({ [_n("protocol")] = "vmess" })
o:depends({ [_n("protocol")] = "vless" })
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.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: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: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:value("", translate("Disable"))
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
o = s:option(Value, option_name("hysteria_obfs"), translate("Obfs Password"))
o:depends({ [option_name("protocol")] = "hysteria" })
o = s:option(Value, _n("hysteria_obfs"), translate("Obfs Password"))
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("string", translate("STRING"))
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:depends({ [option_name("protocol")] = "hysteria", [option_name("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")] = "string"})
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: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: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:depends({ [option_name("protocol")] = "hysteria" })
o = s:option(Value, _n("hysteria_recv_window_conn"), translate("QUIC stream receive window"))
o:depends({ [_n("protocol")] = "hysteria" })
o = s:option(Value, option_name("hysteria_recv_window"), translate("QUIC connection receive window"))
o:depends({ [option_name("protocol")] = "hysteria" })
o = s:option(Value, _n("hysteria_recv_window"), translate("QUIC connection receive window"))
o:depends({ [_n("protocol")] = "hysteria" })
o = s:option(Flag, option_name("hysteria_disable_mtu_discovery"), translate("Disable MTU detection"))
o:depends({ [option_name("protocol")] = "hysteria" })
o = s:option(Flag, _n("hysteria_disable_mtu_discovery"), translate("Disable MTU detection"))
o:depends({ [_n("protocol")] = "hysteria" })
o = s:option(Value, option_name("hysteria_alpn"), translate("QUIC TLS ALPN"))
o:depends({ [option_name("protocol")] = "hysteria" })
o = s:option(Value, _n("hysteria_alpn"), translate("QUIC TLS ALPN"))
o:depends({ [_n("protocol")] = "hysteria" })
end
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:value("bbr", translate("BBR"))
o:value("cubic", translate("CUBIC"))
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:value("native", translate("native"))
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:depends({ [option_name("protocol")] = "tuic" })
o = s:option(Flag, _n("tuic_udp_over_stream"), translate("UDP over stream"))
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: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.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:value("default", translate("Default"))
o:value("h3")
@ -343,38 +343,38 @@ if singbox_tags:find("with_quic") then
o:value("http/1.1")
o:value("h2,http/1.1")
o:value("h3,h2,http/1.1")
o:depends({ [option_name("protocol")] = "tuic" })
o:depends({ [_n("protocol")] = "tuic" })
end
if singbox_tags:find("with_quic") then
o = s:option(Value, option_name("hysteria2_up_mbps"), translate("Max upload Mbps"))
o:depends({ [option_name("protocol")] = "hysteria2" })
o = s:option(Value, _n("hysteria2_up_mbps"), translate("Max upload Mbps"))
o:depends({ [_n("protocol")] = "hysteria2" })
o = s:option(Value, option_name("hysteria2_down_mbps"), translate("Max download Mbps"))
o:depends({ [option_name("protocol")] = "hysteria2" })
o = s:option(Value, _n("hysteria2_down_mbps"), translate("Max download Mbps"))
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("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:depends({ [option_name("protocol")] = "hysteria2" })
o = s:option(Value, _n("hysteria2_obfs_password"), translate("Obfs Password"))
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:depends({ [option_name("protocol")] = "hysteria2"})
o:depends({ [_n("protocol")] = "hysteria2"})
end
o = s:option(Flag, option_name("tls"), translate("TLS"))
o = s:option(Flag, _n("tls"), translate("TLS"))
o.default = 0
o:depends({ [option_name("protocol")] = "vmess" })
o:depends({ [option_name("protocol")] = "vless" })
o:depends({ [option_name("protocol")] = "http" })
o:depends({ [option_name("protocol")] = "trojan" })
o:depends({ [option_name("protocol")] = "shadowsocks" })
o:depends({ [_n("protocol")] = "vmess" })
o:depends({ [_n("protocol")] = "vless" })
o:depends({ [_n("protocol")] = "http" })
o:depends({ [_n("protocol")] = "trojan" })
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:value("default", translate("Default"))
o:value("h3")
@ -383,36 +383,36 @@ o:value("h3,h2")
o:value("http/1.1")
o:value("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:depends({ [option_name("tls")] = true })
o:depends({ [option_name("protocol")] = "hysteria"})
o:depends({ [option_name("protocol")] = "tuic" })
o:depends({ [option_name("protocol")] = "hysteria2" })
o:depends({ [option_name("protocol")] = "shadowsocks" })
o = s:option(Value, _n("tls_serverName"), translate("Domain"))
o:depends({ [_n("tls")] = true })
o:depends({ [_n("protocol")] = "hysteria"})
o:depends({ [_n("protocol")] = "tuic" })
o:depends({ [_n("protocol")] = "hysteria2" })
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:depends({ [option_name("tls")] = true })
o:depends({ [option_name("protocol")] = "hysteria"})
o:depends({ [option_name("protocol")] = "tuic" })
o:depends({ [option_name("protocol")] = "hysteria2" })
o:depends({ [option_name("protocol")] = "shadowsocks" })
o:depends({ [_n("tls")] = true })
o:depends({ [_n("protocol")] = "hysteria"})
o:depends({ [_n("protocol")] = "tuic" })
o:depends({ [_n("protocol")] = "hysteria2" })
o:depends({ [_n("protocol")] = "shadowsocks" })
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:depends({ [option_name("tls")] = true, [option_name("flow")] = "", [option_name("reality")] = false })
o:depends({ [option_name("protocol")] = "tuic" })
o:depends({ [option_name("protocol")] = "hysteria" })
o:depends({ [option_name("protocol")] = "hysteria2" })
o:depends({ [_n("tls")] = true, [_n("flow")] = "", [_n("reality")] = false })
o:depends({ [_n("protocol")] = "tuic" })
o:depends({ [_n("protocol")] = "hysteria" })
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.rows = 5
o.wrap = "off"
o:depends({ [option_name("ech")] = true })
o:depends({ [_n("ech")] = true })
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*\n", "")
@ -422,21 +422,21 @@ if singbox_tags:find("with_ech") then
return value
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: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:depends({ [option_name("ech")] = true })
o:depends({ [_n("ech")] = true })
end
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: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("firefox")
o:value("edge")
@ -448,25 +448,25 @@ if singbox_tags:find("with_utls") then
o:value("random")
-- o:value("randomized")
o.default = "chrome"
o:depends({ [option_name("tls")] = true, [option_name("utls")] = true })
o:depends({ [_n("tls")] = true, [_n("utls")] = true })
-- [[ REALITY部分 ]] --
o = s:option(Flag, option_name("reality"), translate("REALITY"))
o = s:option(Flag, _n("reality"), translate("REALITY"))
o.default = 0
o:depends({ [option_name("protocol")] = "vless", [option_name("utls")] = true })
o:depends({ [option_name("protocol")] = "vmess", [option_name("utls")] = true })
o:depends({ [option_name("protocol")] = "shadowsocks", [option_name("utls")] = true })
o:depends({ [option_name("protocol")] = "socks", [option_name("utls")] = true })
o:depends({ [option_name("protocol")] = "trojan", [option_name("utls")] = true })
o:depends({ [_n("protocol")] = "vless", [_n("utls")] = true })
o:depends({ [_n("protocol")] = "vmess", [_n("utls")] = true })
o:depends({ [_n("protocol")] = "shadowsocks", [_n("utls")] = true })
o:depends({ [_n("protocol")] = "socks", [_n("utls")] = true })
o:depends({ [_n("protocol")] = "trojan", [_n("utls")] = true })
o = s:option(Value, option_name("reality_publicKey"), translate("Public Key"))
o:depends({ [option_name("utls")] = true, [option_name("reality")] = true })
o = s:option(Value, _n("reality_publicKey"), translate("Public Key"))
o:depends({ [_n("utls")] = true, [_n("reality")] = true })
o = s:option(Value, option_name("reality_shortId"), translate("Short Id"))
o:depends({ [option_name("utls")] = true, [option_name("reality")] = true })
o = s:option(Value, _n("reality_shortId"), translate("Short Id"))
o:depends({ [_n("utls")] = true, [_n("reality")] = true })
end
o = s:option(ListValue, option_name("transport"), translate("Transport"))
o = s:option(ListValue, _n("transport"), translate("Transport"))
o:value("tcp", "TCP")
o:value("http", "HTTP")
o:value("ws", "WebSocket")
@ -478,165 +478,165 @@ if singbox_tags:find("with_grpc") then
o:value("grpc", "gRPC")
else o:value("grpc", "gRPC-lite")
end
o:depends({ [option_name("protocol")] = "vmess" })
o:depends({ [option_name("protocol")] = "vless" })
o:depends({ [option_name("protocol")] = "socks" })
o:depends({ [option_name("protocol")] = "shadowsocks" })
o:depends({ [option_name("protocol")] = "trojan" })
o:depends({ [_n("protocol")] = "vmess" })
o:depends({ [_n("protocol")] = "vless" })
o:depends({ [_n("protocol")] = "socks" })
o:depends({ [_n("protocol")] = "shadowsocks" })
o:depends({ [_n("protocol")] = "trojan" })
if singbox_tags:find("with_wireguard") then
o = s:option(Value, option_name("wireguard_public_key"), translate("Public Key"))
o:depends({ [option_name("protocol")] = "wireguard" })
o = s:option(Value, _n("wireguard_public_key"), translate("Public Key"))
o:depends({ [_n("protocol")] = "wireguard" })
o = s:option(Value, option_name("wireguard_secret_key"), translate("Private Key"))
o:depends({ [option_name("protocol")] = "wireguard" })
o = s:option(Value, _n("wireguard_secret_key"), translate("Private Key"))
o:depends({ [_n("protocol")] = "wireguard" })
o = s:option(Value, option_name("wireguard_preSharedKey"), translate("Pre shared key"))
o:depends({ [option_name("protocol")] = "wireguard" })
o = s:option(Value, _n("wireguard_preSharedKey"), translate("Pre shared key"))
o:depends({ [_n("protocol")] = "wireguard" })
o = s:option(DynamicList, option_name("wireguard_local_address"), translate("Local Address"))
o:depends({ [option_name("protocol")] = "wireguard" })
o = s:option(DynamicList, _n("wireguard_local_address"), translate("Local Address"))
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: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:depends({ [option_name("protocol")] = "wireguard" })
o:depends({ [_n("protocol")] = "wireguard" })
o = s:option(Value, option_name("wireguard_interface_name"), translate("System interface name"))
o:depends({ [option_name("protocol")] = "wireguard" })
o = s:option(Value, _n("wireguard_interface_name"), translate("System interface name"))
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:depends({ [option_name("protocol")] = "wireguard" })
o = s:option(Value, _n("wireguard_reserved"), translate("Reserved"), translate("Decimal numbers separated by \",\" or Base64-encoded strings."))
o:depends({ [_n("protocol")] = "wireguard" })
end
-- [[ HTTP部分 ]]--
o = s:option(Value, option_name("http_host"), translate("HTTP Host"))
o:depends({ [option_name("transport")] = "http" })
o = s:option(Value, _n("http_host"), translate("HTTP Host"))
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:depends({ [option_name("transport")] = "http" })
o:depends({ [_n("transport")] = "http" })
o = s:option(Flag, option_name("http_h2_health_check"), translate("Health check"))
o:depends({ [option_name("tls")] = true, [option_name("transport")] = "http" })
o = s:option(Flag, _n("http_h2_health_check"), translate("Health check"))
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: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: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部分 ]]--
o = s:option(Value, option_name("ws_host"), translate("WebSocket Host"))
o:depends({ [option_name("transport")] = "ws" })
o = s:option(Value, _n("ws_host"), translate("WebSocket Host"))
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:depends({ [option_name("transport")] = "ws" })
o:depends({ [_n("transport")] = "ws" })
o = s:option(Flag, option_name("ws_enableEarlyData"), translate("Enable early data"))
o:depends({ [option_name("transport")] = "ws" })
o = s:option(Flag, _n("ws_enableEarlyData"), translate("Enable early data"))
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: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:depends({ [option_name("ws_enableEarlyData")] = true })
o = s:option(Value, _n("ws_earlyDataHeaderName"), translate("Early data header name"), translate("Recommended value: Sec-WebSocket-Protocol"))
o:depends({ [_n("ws_enableEarlyData")] = true })
-- [[ HTTPUpgrade部分 ]]--
o = s:option(Value, option_name("httpupgrade_host"), translate("HTTPUpgrade Host"))
o:depends({ [option_name("transport")] = "httpupgrade" })
o = s:option(Value, _n("httpupgrade_host"), translate("HTTPUpgrade Host"))
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:depends({ [option_name("transport")] = "httpupgrade" })
o:depends({ [_n("transport")] = "httpupgrade" })
-- [[ gRPC部分 ]]--
o = s:option(Value, option_name("grpc_serviceName"), "ServiceName")
o:depends({ [option_name("transport")] = "grpc" })
o = s:option(Value, _n("grpc_serviceName"), "ServiceName")
o:depends({ [_n("transport")] = "grpc" })
o = s:option(Flag, option_name("grpc_health_check"), translate("Health check"))
o:depends({ [option_name("transport")] = "grpc" })
o = s:option(Flag, _n("grpc_health_check"), translate("Health check"))
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: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: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:depends({ [option_name("grpc_health_check")] = true })
o:depends({ [_n("grpc_health_check")] = true })
-- [[ Mux ]]--
o = s:option(Flag, option_name("mux"), translate("Mux"))
o = s:option(Flag, _n("mux"), translate("Mux"))
o.rmempty = false
o:depends({ [option_name("protocol")] = "vmess" })
o:depends({ [option_name("protocol")] = "vless", [option_name("flow")] = "" })
o:depends({ [option_name("protocol")] = "shadowsocks", [option_name("uot")] = "" })
o:depends({ [option_name("protocol")] = "trojan" })
o:depends({ [_n("protocol")] = "vmess" })
o:depends({ [_n("protocol")] = "vless", [_n("flow")] = "" })
o:depends({ [_n("protocol")] = "shadowsocks", [_n("uot")] = "" })
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("yamux")
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: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:depends({ [option_name("mux")] = true })
o:depends({ [_n("mux")] = true })
-- [[ 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: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: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: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:depends({ [option_name("protocol")] = "vmess", [option_name("tls")] = false })
o:depends({ [option_name("protocol")] = "shadowsocks", [option_name("tls")] = false })
o:depends({ [_n("protocol")] = "vmess", [_n("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:value("1", "ShadowTLS v1")
o:value("2", "ShadowTLS v2")
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:depends({ [option_name("shadowtls")] = true, [option_name("shadowtls_version")] = "2" })
o:depends({ [option_name("shadowtls")] = true, [option_name("shadowtls_version")] = "3" })
o:depends({ [_n("shadowtls")] = true, [_n("shadowtls_version")] = "2" })
o:depends({ [_n("shadowtls")] = true, [_n("shadowtls_version")] = "3" })
o = s:option(Value, option_name("shadowtls_serverName"), "ShadowTLS " .. translate("Domain"))
o:depends({ [option_name("shadowtls")] = true })
o = s:option(Value, _n("shadowtls_serverName"), "ShadowTLS " .. translate("Domain"))
o:depends({ [_n("shadowtls")] = true })
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: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("firefox")
o:value("edge")
@ -648,62 +648,62 @@ if singbox_tags:find("with_utls") then
o:value("random")
-- o:value("randomized")
o.default = "chrome"
o:depends({ [option_name("shadowtls")] = true, [option_name("shadowtls_utls")] = true })
o:depends({ [_n("shadowtls")] = true, [_n("shadowtls_utls")] = true })
end
-- [[ 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: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:depends({ [option_name("plugin_enabled")] = true })
o:depends({ [_n("plugin_enabled")] = true })
o:value("obfs-local")
o:value("v2ray-plugin")
o = s:option(Value, option_name("plugin_opts"), translate("opts"))
o:depends({ [option_name("plugin_enabled")] = true })
o = s:option(Value, _n("plugin_opts"), translate("opts"))
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:value("", translate("Auto"))
o:value("prefer_ipv4", translate("Prefer IPv4"))
o:value("prefer_ipv6", translate("Prefer IPv6"))
o:value("ipv4_only", translate("IPv4 Only"))
o:value("ipv6_only", translate("IPv6 Only"))
o:depends({ [option_name("protocol")] = "socks" })
o:depends({ [option_name("protocol")] = "http" })
o:depends({ [option_name("protocol")] = "shadowsocks" })
o:depends({ [option_name("protocol")] = "shadowsocksr" })
o:depends({ [option_name("protocol")] = "vmess" })
o:depends({ [option_name("protocol")] = "trojan" })
o:depends({ [option_name("protocol")] = "wireguard" })
o:depends({ [option_name("protocol")] = "hysteria" })
o:depends({ [option_name("protocol")] = "vless" })
o:depends({ [option_name("protocol")] = "tuic" })
o:depends({ [option_name("protocol")] = "hysteria2" })
o:depends({ [_n("protocol")] = "socks" })
o:depends({ [_n("protocol")] = "http" })
o:depends({ [_n("protocol")] = "shadowsocks" })
o:depends({ [_n("protocol")] = "shadowsocksr" })
o:depends({ [_n("protocol")] = "vmess" })
o:depends({ [_n("protocol")] = "trojan" })
o:depends({ [_n("protocol")] = "wireguard" })
o:depends({ [_n("protocol")] = "hysteria" })
o:depends({ [_n("protocol")] = "vless" })
o:depends({ [_n("protocol")] = "tuic" })
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("1", translate("Preproxy 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
o:depends({ [option_name("protocol")] = v })
o:depends({ [_n("protocol")] = v })
end
end
o = s:option(ListValue, option_name("preproxy_node"), translate("Preproxy Node"), translate("Only support a layer of proxy."))
o:depends({ [option_name("chain_proxy")] = "1" })
o = s:option(ListValue, _n("preproxy_node"), translate("Preproxy Node"), translate("Only support a layer of proxy."))
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:depends({ [option_name("chain_proxy")] = "2" })
o = s:option(ListValue, _n("to_node"), translate("Landing Node"), translate("Only support a layer of proxy."))
o:depends({ [_n("chain_proxy")] = "2" })
for k, v in pairs(nodes_table) do
if v.type == "sing-box" and v.id ~= arg[1] then
s.fields[option_name("preproxy_node")]:value(v.id, v.remark)
s.fields[option_name("to_node")]:value(v.id, v.remark)
s.fields[_n("preproxy_node")]:value(v.id, v.remark)
s.fields[_n("to_node")]:value(v.id, v.remark)
end
end

View File

@ -10,7 +10,7 @@ local type_name = "SS-Rust"
local option_prefix = "ssrust_"
local function option_name(name)
local function _n(name)
return option_prefix .. name
end
@ -24,34 +24,34 @@ local ssrust_encrypt_method_list = {
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 = s:option(Value, option_name("password"), translate("Password"))
o = s:option(Value, _n("password"), translate("Password"))
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
o = s:option(Value, option_name("timeout"), translate("Connection Timeout"))
o = s:option(Value, _n("timeout"), translate("Connection Timeout"))
o.datatype = "uinteger"
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("true")
o = s:option(ListValue, option_name("plugin"), translate("plugin"))
o = s:option(ListValue, _n("plugin"), translate("plugin"))
o:value("none", translate("none"))
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("obfs-local") then o:value("obfs-local") end
o = s:option(Value, option_name("plugin_opts"), translate("opts"))
o:depends({ [option_name("plugin")] = "xray-plugin"})
o:depends({ [option_name("plugin")] = "v2ray-plugin"})
o:depends({ [option_name("plugin")] = "obfs-local"})
o = s:option(Value, _n("plugin_opts"), translate("opts"))
o:depends({ [_n("plugin")] = "xray-plugin"})
o:depends({ [_n("plugin")] = "v2ray-plugin"})
o:depends({ [_n("plugin")] = "obfs-local"})
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 function option_name(name)
local function _n(name)
return option_prefix .. name
end
@ -25,34 +25,34 @@ local ss_encrypt_method_list = {
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 = s:option(Value, option_name("password"), translate("Password"))
o = s:option(Value, _n("password"), translate("Password"))
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
o = s:option(Value, option_name("timeout"), translate("Connection Timeout"))
o = s:option(Value, _n("timeout"), translate("Connection Timeout"))
o.datatype = "uinteger"
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("true")
o = s:option(ListValue, option_name("plugin"), translate("plugin"))
o = s:option(ListValue, _n("plugin"), translate("plugin"))
o:value("none", translate("none"))
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("obfs-local") then o:value("obfs-local") end
o = s:option(Value, option_name("plugin_opts"), translate("opts"))
o:depends({ [option_name("plugin")] = "xray-plugin"})
o:depends({ [option_name("plugin")] = "v2ray-plugin"})
o:depends({ [option_name("plugin")] = "obfs-local"})
o = s:option(Value, _n("plugin_opts"), translate("opts"))
o:depends({ [_n("plugin")] = "xray-plugin"})
o:depends({ [_n("plugin")] = "v2ray-plugin"})
o:depends({ [_n("plugin")] = "obfs-local"})
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 function option_name(name)
local function _n(name)
return option_prefix .. name
end
@ -37,32 +37,32 @@ local ssr_obfs_list = {
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 = s:option(Value, option_name("password"), translate("Password"))
o = s:option(Value, _n("password"), translate("Password"))
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
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
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
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.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("true")

View File

@ -10,7 +10,7 @@ local type_name = "TUIC"
local option_prefix = "tuic_"
local function option_name(name)
local function _n(name)
return option_prefix .. name
end
@ -18,16 +18,16 @@ end
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 = s:option(Value, option_name("uuid"), translate("ID"))
o = s:option(Value, _n("uuid"), translate("ID"))
o.password = true
-- 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.rmempty = true
o.default = ""
@ -35,32 +35,32 @@ o.rewrite_option = o.option
--[[
-- 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.default = ""
o.rewrite_option = o.option
-- 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.rmempty = true
o.default = ""
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.rmempty = true
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("quic", translate("QUIC"))
o.default = "native"
o.rmempty = true
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("cubic", translate("CUBIC"))
o:value("new_reno", translate("New Reno"))
@ -68,65 +68,65 @@ o.default = "cubic"
o.rmempty = true
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.default = "3"
o.rmempty = true
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.default = "8"
o.rmempty = true
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.default = "3"
o.rmempty = true
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.default = "15"
o.rmempty = true
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.default = 20971520
o.rmempty = true
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.default = 10485760
o.rmempty = true
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.default = 1500
o.rmempty = true
o.rewrite_option = o.option
--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.rmempty = true
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.rmempty = true
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.rmempty = true
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.rewrite_option = o.option

View File

@ -10,7 +10,7 @@ local type_name = "Hysteria2"
local option_prefix = "hysteria2_"
local function option_name(name)
local function _n(name)
return option_prefix .. name
end
@ -18,31 +18,31 @@ end
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 = s:option(Value, option_name("obfs"), translate("Obfs Password"))
o = s:option(Value, _n("obfs"), translate("Obfs Password"))
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.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.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 = 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 = s:option(Flag, option_name("ignoreClientBandwidth"), translate("ignoreClientBandwidth"))
o = s:option(Flag, _n("ignoreClientBandwidth"), translate("ignoreClientBandwidth"))
o.default = "0"
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.validate = function(self, value, t)
if value and value ~= "" then
@ -55,7 +55,7 @@ o.validate = function(self, value, t)
return nil
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.validate = function(self, value, t)
if value and value ~= "" then
@ -68,7 +68,7 @@ o.validate = function(self, value, t)
return nil
end
o = s:option(Flag, option_name("log"), translate("Log"))
o = s:option(Flag, _n("log"), translate("Log"))
o.default = "1"
o.rmempty = false

View File

@ -10,7 +10,7 @@ local type_name = "Xray"
local option_prefix = "xray_"
local function option_name(name)
local function _n(name)
return option_prefix .. name
end
@ -26,7 +26,7 @@ local header_type_list = {
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("vless", "VLESS")
o:value("http", "HTTP")
@ -35,91 +35,91 @@ o:value("shadowsocks", "Shadowsocks")
o:value("trojan", "Trojan")
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 = s:option(Flag, option_name("auth"), translate("Auth"))
o = s:option(Flag, _n("auth"), translate("Auth"))
o.validate = function(self, value, t)
if value and value == "1" then
local user_v = s.fields[option_name("username")] and s.fields[option_name("username")]:formvalue(t) or ""
local pass_v = s.fields[option_name("password")] and s.fields[option_name("password")]:formvalue(t) or ""
local user_v = s.fields[_n("username")] and s.fields[_n("username")]: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
return nil, translate("Username and Password must be used together!")
end
end
return value
end
o:depends({ [option_name("protocol")] = "socks" })
o:depends({ [option_name("protocol")] = "http" })
o:depends({ [_n("protocol")] = "socks" })
o:depends({ [_n("protocol")] = "http" })
o = s:option(Value, option_name("username"), translate("Username"))
o:depends({ [option_name("auth")] = true })
o = s:option(Value, _n("username"), translate("Username"))
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:depends({ [option_name("auth")] = true })
o:depends({ [option_name("protocol")] = "shadowsocks" })
o:depends({ [_n("auth")] = true })
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("udp", "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:depends({ [option_name("protocol")] = "dokodemo-door" })
o = s:option(Value, _n("d_address"), translate("Destination address"))
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: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: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"
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:depends({ [option_name("protocol")] = "shadowsocks" })
o = s:option(Flag, _n("iv_check"), translate("IV Check"))
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:value("tcp", "TCP")
o:value("udp", "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.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
o:value(api.gen_uuid(1))
end
o:depends({ [option_name("protocol")] = "vmess" })
o:depends({ [option_name("protocol")] = "vless" })
o:depends({ [option_name("protocol")] = "trojan" })
o:depends({ [_n("protocol")] = "vmess" })
o:depends({ [_n("protocol")] = "vless" })
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:value("", translate("Disable"))
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.validate = function(self, value, t)
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 value == "1" then
local ca = s.fields[option_name("tls_certificateFile")] and s.fields[option_name("tls_certificateFile")]:formvalue(t) or ""
local key = s.fields[option_name("tls_keyFile")] and s.fields[option_name("tls_keyFile")]:formvalue(t) or ""
local ca = s.fields[_n("tls_certificateFile")] and s.fields[_n("tls_certificateFile")]:formvalue(t) or ""
local key = s.fields[_n("tls_keyFile")] and s.fields[_n("tls_keyFile")]:formvalue(t) or ""
if ca == "" or key == "" then
return nil, translate("Public key and Private key path can not be empty!")
end
@ -127,32 +127,32 @@ o.validate = function(self, value, t)
return value
end
end
o:depends({ [option_name("protocol")] = "vmess" })
o:depends({ [option_name("protocol")] = "vless" })
o:depends({ [option_name("protocol")] = "http" })
o:depends({ [option_name("protocol")] = "socks" })
o:depends({ [option_name("protocol")] = "shadowsocks" })
o:depends({ [option_name("protocol")] = "trojan" })
o:depends({ [_n("protocol")] = "vmess" })
o:depends({ [_n("protocol")] = "vless" })
o:depends({ [_n("protocol")] = "http" })
o:depends({ [_n("protocol")] = "socks" })
o:depends({ [_n("protocol")] = "shadowsocks" })
o:depends({ [_n("protocol")] = "trojan" })
-- [[ REALITY部分 ]] --
o = s:option(Flag, option_name("reality"), translate("REALITY"))
o = s:option(Flag, _n("reality"), translate("REALITY"))
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:depends({ [option_name("reality")] = true })
o = s:option(Value, _n("reality_private_key"), translate("Private Key"))
o:depends({ [_n("reality")] = true })
o = s:option(DynamicList, option_name("reality_shortId"), translate("Short Id"))
o:depends({ [option_name("reality")] = true })
o = s:option(DynamicList, _n("reality_shortId"), translate("Short Id"))
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:depends({ [option_name("reality")] = true })
o:depends({ [_n("reality")] = true })
o = s:option(Value, option_name("reality_serverNames"), translate("serverNames"))
o:depends({ [option_name("reality")] = true })
o = s:option(Value, _n("reality_serverNames"), translate("serverNames"))
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:value("h3,h2,http/1.1")
o:value("h3,h2")
@ -160,17 +160,17 @@ o:value("h2,http/1.1")
o:value("h3")
o:value("h2")
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:value("1.3")
--o:depends({ [option_name("tls")] = true })
--o:depends({ [_n("tls")] = true })
-- [[ 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:depends({ [option_name("tls")] = true, [option_name("reality")] = false })
o:depends({ [_n("tls")] = true, [_n("reality")] = false })
o.validate = function(self, value, t)
if value and value ~= "" then
if not nixio.fs.access(value) then
@ -182,9 +182,9 @@ o.validate = function(self, value, t)
return nil
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:depends({ [option_name("tls")] = true, [option_name("reality")] = false })
o:depends({ [_n("tls")] = true, [_n("reality")] = false })
o.validate = function(self, value, t)
if value and value ~= "" then
if not nixio.fs.access(value) then
@ -196,7 +196,7 @@ o.validate = function(self, value, t)
return nil
end
o = s:option(ListValue, option_name("transport"), translate("Transport"))
o = s:option(ListValue, _n("transport"), translate("Transport"))
o:value("raw", "RAW")
o:value("mkcp", "mKCP")
o:value("ws", "WebSocket")
@ -206,161 +206,161 @@ o:value("quic", "QUIC")
o:value("grpc", "gRPC")
o:value("httpupgrade", "HttpUpgrade")
o:value("xhttp", "XHTTP")
o:depends({ [option_name("protocol")] = "vmess" })
o:depends({ [option_name("protocol")] = "vless" })
o:depends({ [option_name("protocol")] = "socks" })
o:depends({ [option_name("protocol")] = "shadowsocks" })
o:depends({ [option_name("protocol")] = "trojan" })
o:depends({ [_n("protocol")] = "vmess" })
o:depends({ [_n("protocol")] = "vless" })
o:depends({ [_n("protocol")] = "socks" })
o:depends({ [_n("protocol")] = "shadowsocks" })
o:depends({ [_n("protocol")] = "trojan" })
-- [[ WebSocket部分 ]]--
o = s:option(Value, option_name("ws_host"), translate("WebSocket Host"))
o:depends({ [option_name("transport")] = "ws" })
o = s:option(Value, _n("ws_host"), translate("WebSocket Host"))
o:depends({ [_n("transport")] = "ws" })
o = s:option(Value, option_name("ws_path"), translate("WebSocket Path"))
o:depends({ [option_name("transport")] = "ws" })
o = s:option(Value, _n("ws_path"), translate("WebSocket Path"))
o:depends({ [_n("transport")] = "ws" })
-- [[ HttpUpgrade部分 ]]--
o = s:option(Value, option_name("httpupgrade_host"), translate("HttpUpgrade Host"))
o:depends({ [option_name("transport")] = "httpupgrade" })
o = s:option(Value, _n("httpupgrade_host"), translate("HttpUpgrade Host"))
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:depends({ [option_name("transport")] = "httpupgrade" })
o:depends({ [_n("transport")] = "httpupgrade" })
-- [[ HTTP/2部分 ]]--
o = s:option(Value, option_name("h2_host"), translate("HTTP/2 Host"))
o:depends({ [option_name("transport")] = "h2" })
o = s:option(Value, _n("h2_host"), translate("HTTP/2 Host"))
o:depends({ [_n("transport")] = "h2" })
o = s:option(Value, option_name("h2_path"), translate("HTTP/2 Path"))
o:depends({ [option_name("transport")] = "h2" })
o = s:option(Value, _n("h2_path"), translate("HTTP/2 Path"))
o:depends({ [_n("transport")] = "h2" })
-- [[ SplitHTTP部分 ]]--
o = s:option(Value, option_name("xhttp_host"), translate("XHTTP Host"))
o:depends({ [option_name("transport")] = "xhttp" })
o = s:option(Value, _n("xhttp_host"), translate("XHTTP Host"))
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: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: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: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: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:depends({ [option_name("transport")] = "splithttp" })
o:depends({ [_n("transport")] = "splithttp" })
-- [[ 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("http", "http")
o:depends({ [option_name("transport")] = "raw" })
o:depends({ [_n("transport")] = "raw" })
-- HTTP域名
o = s:option(DynamicList, option_name("tcp_guise_http_host"), translate("HTTP Host"))
o:depends({ [option_name("tcp_guise")] = "http" })
o = s:option(DynamicList, _n("tcp_guise_http_host"), translate("HTTP Host"))
o:depends({ [_n("tcp_guise")] = "http" })
-- HTTP路径
o = s:option(DynamicList, option_name("tcp_guise_http_path"), translate("HTTP Path"))
o:depends({ [option_name("tcp_guise")] = "http" })
o = s:option(DynamicList, _n("tcp_guise_http_path"), translate("HTTP Path"))
o:depends({ [_n("tcp_guise")] = "http" })
-- [[ 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
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: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: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: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:depends({ [option_name("transport")] = "mkcp" })
o:depends({ [_n("transport")] = "mkcp" })
o = s:option(Flag, option_name("mkcp_congestion"), translate("KCP Congestion"))
o:depends({ [option_name("transport")] = "mkcp" })
o = s:option(Flag, _n("mkcp_congestion"), translate("KCP Congestion"))
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: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:depends({ [option_name("transport")] = "mkcp" })
o:depends({ [_n("transport")] = "mkcp" })
o = s:option(Value, option_name("mkcp_seed"), translate("KCP Seed"))
o:depends({ [option_name("transport")] = "mkcp" })
o = s:option(Value, _n("mkcp_seed"), translate("KCP Seed"))
o:depends({ [_n("transport")] = "mkcp" })
-- [[ DomainSocket部分 ]]--
o = s:option(Value, option_name("ds_path"), "Path", translate("A legal file path. This file must not exist before running."))
o:depends({ [option_name("transport")] = "ds" })
o = s:option(Value, _n("ds_path"), "Path", translate("A legal file path. This file must not exist before running."))
o:depends({ [_n("transport")] = "ds" })
-- [[ 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("aes-128-gcm")
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:depends({ [option_name("transport")] = "quic" })
o = s:option(Value, _n("quic_key"), translate("Encrypt Method") .. translate("Key"))
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
o:depends({ [option_name("transport")] = "quic" })
o:depends({ [_n("transport")] = "quic" })
-- [[ gRPC部分 ]]--
o = s:option(Value, option_name("grpc_serviceName"), "ServiceName")
o:depends({ [option_name("transport")] = "grpc" })
o = s:option(Value, _n("grpc_serviceName"), "ServiceName")
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"
-- [[ Fallback部分 ]]--
o = s:option(Flag, option_name("fallback"), translate("Fallback"))
o:depends({ [option_name("protocol")] = "vless", [option_name("transport")] = "raw" })
o:depends({ [option_name("protocol")] = "trojan", [option_name("transport")] = "raw" })
o = s:option(Flag, _n("fallback"), translate("Fallback"))
o:depends({ [_n("protocol")] = "vless", [_n("transport")] = "raw" })
o:depends({ [_n("protocol")] = "trojan", [_n("transport")] = "raw" })
--[[
o = s:option(Value, option_name("fallback_alpn"), "Fallback alpn")
o:depends({ [option_name("fallback")] = true })
o = s:option(Value, _n("fallback_alpn"), "Fallback alpn")
o:depends({ [_n("fallback")] = true })
o = s:option(Value, option_name("fallback_path"), "Fallback path")
o:depends({ [option_name("fallback")] = true })
o = s:option(Value, _n("fallback_path"), "Fallback path")
o:depends({ [_n("fallback")] = true })
o = s:option(Value, option_name("fallback_dest"), "Fallback dest")
o:depends({ [option_name("fallback")] = true })
o = s:option(Value, _n("fallback_dest"), "Fallback dest")
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:depends({ [option_name("fallback")] = true })
o:depends({ [_n("fallback")] = true })
]]--
o = s:option(DynamicList, option_name("fallback_list"), "Fallback", translate("dest,path"))
o:depends({ [option_name("fallback")] = true })
o = s:option(DynamicList, _n("fallback_list"), "Fallback", translate("dest,path"))
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 = 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"
local nodes_table = {}
@ -373,46 +373,45 @@ for k, e in ipairs(api.get_valid_nodes()) do
end
end
o = s:option(ListValue, option_name("outbound_node"), translate("outbound node"))
o:value("nil", translate("Close"))
o = s:option(ListValue, _n("outbound_node"), translate("outbound node"))
o:value("", translate("Close"))
o:value("_socks", translate("Custom Socks"))
o:value("_http", translate("Custom HTTP"))
o:value("_iface", translate("Custom Interface"))
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:depends({ [option_name("outbound_node")] = "_socks"})
o:depends({ [option_name("outbound_node")] = "_http"})
o = s:option(Value, _n("outbound_node_address"), translate("Address (Support Domain Name)"))
o:depends({ [_n("outbound_node")] = "_socks"})
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:depends({ [option_name("outbound_node")] = "_socks"})
o:depends({ [option_name("outbound_node")] = "_http"})
o:depends({ [_n("outbound_node")] = "_socks"})
o:depends({ [_n("outbound_node")] = "_http"})
o = s:option(Value, option_name("outbound_node_username"), translate("Username"))
o:depends({ [option_name("outbound_node")] = "_socks"})
o:depends({ [option_name("outbound_node")] = "_http"})
o = s:option(Value, _n("outbound_node_username"), translate("Username"))
o:depends({ [_n("outbound_node")] = "_socks"})
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:depends({ [option_name("outbound_node")] = "_socks"})
o:depends({ [option_name("outbound_node")] = "_http"})
o:depends({ [_n("outbound_node")] = "_socks"})
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: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.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:value("debug")
o:value("info")
o:value("warning")
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)

View File

@ -14,7 +14,7 @@ local type_name = "sing-box"
local option_prefix = "singbox_"
local function option_name(name)
local function _n(name)
return option_prefix .. name
end
@ -27,7 +27,7 @@ local ss_method_list = {
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("socks", "Socks")
o:value("http", "HTTP")
@ -47,166 +47,166 @@ if singbox_tags:find("with_quic") then
end
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 = s:option(Flag, option_name("auth"), translate("Auth"))
o = s:option(Flag, _n("auth"), translate("Auth"))
o.validate = function(self, value, t)
if value and value == "1" then
local user_v = s.fields[option_name("username")] and s.fields[option_name("username")]:formvalue(t) or ""
local pass_v = s.fields[option_name("password")] and s.fields[option_name("password")]:formvalue(t) or ""
local user_v = s.fields[_n("username")] and s.fields[_n("username")]: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
return nil, translate("Username and Password must be used together!")
end
end
return value
end
o:depends({ [option_name("protocol")] = "mixed" })
o:depends({ [option_name("protocol")] = "socks" })
o:depends({ [option_name("protocol")] = "http" })
o:depends({ [_n("protocol")] = "mixed" })
o:depends({ [_n("protocol")] = "socks" })
o:depends({ [_n("protocol")] = "http" })
o = s:option(Value, option_name("username"), translate("Username"))
o:depends({ [option_name("auth")] = true })
o:depends({ [option_name("protocol")] = "naive" })
o = s:option(Value, _n("username"), translate("Username"))
o:depends({ [_n("auth")] = true })
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:depends({ [option_name("auth")] = true })
o:depends({ [option_name("protocol")] = "shadowsocks" })
o:depends({ [option_name("protocol")] = "naive" })
o:depends({ [option_name("protocol")] = "tuic" })
o:depends({ [_n("auth")] = true })
o:depends({ [_n("protocol")] = "shadowsocks" })
o:depends({ [_n("protocol")] = "naive" })
o:depends({ [_n("protocol")] = "tuic" })
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: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:depends({ [option_name("protocol")] = "hysteria" })
o:depends({ [_n("protocol")] = "hysteria" })
o = s:option(Value, option_name("hysteria_obfs"), translate("Obfs Password"))
o:depends({ [option_name("protocol")] = "hysteria" })
o = s:option(Value, _n("hysteria_obfs"), translate("Obfs Password"))
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("string", translate("STRING"))
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:depends({ [option_name("protocol")] = "hysteria", [option_name("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")] = "string"})
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:depends({ [option_name("protocol")] = "hysteria" })
o = s:option(Value, _n("hysteria_recv_window_conn"), translate("QUIC stream receive window"))
o:depends({ [_n("protocol")] = "hysteria" })
o = s:option(Value, option_name("hysteria_recv_window_client"), translate("QUIC connection receive window"))
o:depends({ [option_name("protocol")] = "hysteria" })
o = s:option(Value, _n("hysteria_recv_window_client"), translate("QUIC connection receive window"))
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: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:depends({ [option_name("protocol")] = "hysteria" })
o = s:option(Flag, _n("hysteria_disable_mtu_discovery"), translate("Disable MTU detection"))
o:depends({ [_n("protocol")] = "hysteria" })
o = s:option(Value, option_name("hysteria_alpn"), translate("QUIC TLS ALPN"))
o:depends({ [option_name("protocol")] = "hysteria" })
o = s:option(Value, _n("hysteria_alpn"), translate("QUIC TLS ALPN"))
o:depends({ [_n("protocol")] = "hysteria" })
end
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:value("bbr", translate("BBR"))
o:value("cubic", translate("CUBIC"))
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: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.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:depends({ [option_name("protocol")] = "tuic" })
o = s:option(Value, _n("tuic_alpn"), translate("QUIC TLS ALPN"))
o:depends({ [_n("protocol")] = "tuic" })
end
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:depends({ [option_name("protocol")] = "hysteria2" })
o:depends({ [_n("protocol")] = "hysteria2" })
o = s:option(Value, option_name("hysteria2_up_mbps"), translate("Max upload Mbps"))
o:depends({ [option_name("protocol")] = "hysteria2", [option_name("hysteria2_ignore_client_bandwidth")] = false })
o = s:option(Value, _n("hysteria2_up_mbps"), translate("Max upload Mbps"))
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:depends({ [option_name("protocol")] = "hysteria2", [option_name("hysteria2_ignore_client_bandwidth")] = false })
o = s:option(Value, _n("hysteria2_down_mbps"), translate("Max download Mbps"))
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("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:depends({ [option_name("protocol")] = "hysteria2" })
o = s:option(Value, _n("hysteria2_obfs_password"), translate("Obfs Password"))
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:depends({ [option_name("protocol")] = "hysteria2"})
o:depends({ [_n("protocol")] = "hysteria2"})
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("udp", "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:depends({ [option_name("protocol")] = "direct" })
o = s:option(Value, _n("d_address"), translate("Destination address"))
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: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: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"
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
o:value(api.gen_uuid(1))
end
o:depends({ [option_name("protocol")] = "vmess" })
o:depends({ [option_name("protocol")] = "vless" })
o:depends({ [option_name("protocol")] = "trojan" })
o:depends({ [option_name("protocol")] = "tuic" })
o:depends({ [_n("protocol")] = "vmess" })
o:depends({ [_n("protocol")] = "vless" })
o:depends({ [_n("protocol")] = "trojan" })
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:value("", translate("Disable"))
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.validate = function(self, value, t)
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 value == "1" then
local ca = s.fields[option_name("tls_certificateFile")] and s.fields[option_name("tls_certificateFile")]:formvalue(t) or ""
local key = s.fields[option_name("tls_keyFile")] and s.fields[option_name("tls_keyFile")]:formvalue(t) or ""
local ca = s.fields[_n("tls_certificateFile")] and s.fields[_n("tls_certificateFile")]:formvalue(t) or ""
local key = s.fields[_n("tls_keyFile")] and s.fields[_n("tls_keyFile")]:formvalue(t) or ""
if ca == "" or key == "" then
return nil, translate("Public key and Private key path can not be empty!")
end
@ -214,45 +214,45 @@ o.validate = function(self, value, t)
return value
end
end
o:depends({ [option_name("protocol")] = "http" })
o:depends({ [option_name("protocol")] = "vmess" })
o:depends({ [option_name("protocol")] = "vless" })
o:depends({ [option_name("protocol")] = "trojan" })
o:depends({ [_n("protocol")] = "http" })
o:depends({ [_n("protocol")] = "vmess" })
o:depends({ [_n("protocol")] = "vless" })
o:depends({ [_n("protocol")] = "trojan" })
if singbox_tags:find("with_reality_server") then
-- [[ REALITY部分 ]] --
o = s:option(Flag, option_name("reality"), translate("REALITY"))
o = s:option(Flag, _n("reality"), translate("REALITY"))
o.default = 0
o:depends({ [option_name("protocol")] = "http", [option_name("tls")] = true })
o:depends({ [option_name("protocol")] = "vmess", [option_name("tls")] = true })
o:depends({ [option_name("protocol")] = "vless", [option_name("tls")] = true })
o:depends({ [option_name("protocol")] = "trojan", [option_name("tls")] = true })
o:depends({ [_n("protocol")] = "http", [_n("tls")] = true })
o:depends({ [_n("protocol")] = "vmess", [_n("tls")] = true })
o:depends({ [_n("protocol")] = "vless", [_n("tls")] = true })
o:depends({ [_n("protocol")] = "trojan", [_n("tls")] = true })
o = s:option(Value, option_name("reality_private_key"), translate("Private Key"))
o:depends({ [option_name("reality")] = true })
o = s:option(Value, _n("reality_private_key"), translate("Private Key"))
o:depends({ [_n("reality")] = true })
o = s:option(Value, option_name("reality_shortId"), translate("Short Id"))
o:depends({ [option_name("reality")] = true })
o = s:option(Value, _n("reality_shortId"), translate("Short Id"))
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: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.default = "443"
o:depends({ [option_name("reality")] = true })
o:depends({ [_n("reality")] = true })
end
-- [[ 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:depends({ [option_name("tls")] = true, [option_name("reality")] = false })
o:depends({ [option_name("protocol")] = "naive" })
o:depends({ [option_name("protocol")] = "hysteria" })
o:depends({ [option_name("protocol")] = "tuic" })
o:depends({ [option_name("protocol")] = "hysteria2" })
o:depends({ [_n("tls")] = true, [_n("reality")] = false })
o:depends({ [_n("protocol")] = "naive" })
o:depends({ [_n("protocol")] = "hysteria" })
o:depends({ [_n("protocol")] = "tuic" })
o:depends({ [_n("protocol")] = "hysteria2" })
o.validate = function(self, value, t)
if value and value ~= "" then
if not nixio.fs.access(value) then
@ -264,13 +264,13 @@ o.validate = function(self, value, t)
return nil
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:depends({ [option_name("tls")] = true, [option_name("reality")] = false })
o:depends({ [option_name("protocol")] = "naive" })
o:depends({ [option_name("protocol")] = "hysteria" })
o:depends({ [option_name("protocol")] = "tuic" })
o:depends({ [option_name("protocol")] = "hysteria2" })
o:depends({ [_n("tls")] = true, [_n("reality")] = false })
o:depends({ [_n("protocol")] = "naive" })
o:depends({ [_n("protocol")] = "hysteria" })
o:depends({ [_n("protocol")] = "tuic" })
o:depends({ [_n("protocol")] = "hysteria2" })
o.validate = function(self, value, t)
if value and value ~= "" then
if not nixio.fs.access(value) then
@ -283,19 +283,19 @@ o.validate = function(self, value, t)
end
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:depends({ [option_name("tls")] = true, [option_name("flow")] = "", [option_name("reality")] = false })
o:depends({ [option_name("protocol")] = "naive" })
o:depends({ [option_name("protocol")] = "hysteria" })
o:depends({ [option_name("protocol")] = "tuic" })
o:depends({ [option_name("protocol")] = "hysteria2" })
o:depends({ [_n("tls")] = true, [_n("flow")] = "", [_n("reality")] = false })
o:depends({ [_n("protocol")] = "naive" })
o:depends({ [_n("protocol")] = "hysteria" })
o:depends({ [_n("protocol")] = "tuic" })
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.rows = 5
o.wrap = "off"
o:depends({ [option_name("ech")] = true })
o:depends({ [_n("ech")] = true })
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*\n", "")
@ -305,80 +305,80 @@ if singbox_tags:find("with_ech") then
return value
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: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:depends({ [option_name("ech")] = true })
o:depends({ [_n("ech")] = true })
end
o = s:option(ListValue, option_name("transport"), translate("Transport"))
o = s:option(ListValue, _n("transport"), translate("Transport"))
o:value("tcp", "TCP")
o:value("http", "HTTP")
o:value("ws", "WebSocket")
o:value("httpupgrade", "HTTPUpgrade")
o:value("quic", "QUIC")
o:value("grpc", "gRPC")
o:depends({ [option_name("protocol")] = "shadowsocks" })
o:depends({ [option_name("protocol")] = "vmess" })
o:depends({ [option_name("protocol")] = "vless" })
o:depends({ [option_name("protocol")] = "trojan" })
o:depends({ [_n("protocol")] = "shadowsocks" })
o:depends({ [_n("protocol")] = "vmess" })
o:depends({ [_n("protocol")] = "vless" })
o:depends({ [_n("protocol")] = "trojan" })
-- [[ HTTP部分 ]]--
o = s:option(Value, option_name("http_host"), translate("HTTP Host"))
o:depends({ [option_name("transport")] = "http" })
o = s:option(Value, _n("http_host"), translate("HTTP Host"))
o:depends({ [_n("transport")] = "http" })
o = s:option(Value, option_name("http_path"), translate("HTTP Path"))
o:depends({ [option_name("transport")] = "http" })
o = s:option(Value, _n("http_path"), translate("HTTP Path"))
o:depends({ [_n("transport")] = "http" })
-- [[ WebSocket部分 ]]--
o = s:option(Value, option_name("ws_host"), translate("WebSocket Host"))
o:depends({ [option_name("transport")] = "ws" })
o = s:option(Value, _n("ws_host"), translate("WebSocket Host"))
o:depends({ [_n("transport")] = "ws" })
o = s:option(Value, option_name("ws_path"), translate("WebSocket Path"))
o:depends({ [option_name("transport")] = "ws" })
o = s:option(Value, _n("ws_path"), translate("WebSocket Path"))
o:depends({ [_n("transport")] = "ws" })
-- [[ HTTPUpgrade部分 ]]--
o = s:option(Value, option_name("httpupgrade_host"), translate("HTTPUpgrade Host"))
o:depends({ [option_name("transport")] = "httpupgrade" })
o = s:option(Value, _n("httpupgrade_host"), translate("HTTPUpgrade Host"))
o:depends({ [_n("transport")] = "httpupgrade" })
o = s:option(Value, option_name("httpupgrade_path"), translate("HTTPUpgrade Path"))
o:depends({ [option_name("transport")] = "httpupgrade" })
o = s:option(Value, _n("httpupgrade_path"), translate("HTTPUpgrade Path"))
o:depends({ [_n("transport")] = "httpupgrade" })
-- [[ gRPC部分 ]]--
o = s:option(Value, option_name("grpc_serviceName"), "ServiceName")
o:depends({ [option_name("transport")] = "grpc" })
o = s:option(Value, _n("grpc_serviceName"), "ServiceName")
o:depends({ [_n("transport")] = "grpc" })
-- [[ Mux ]]--
o = s:option(Flag, option_name("mux"), translate("Mux"))
o = s:option(Flag, _n("mux"), translate("Mux"))
o.rmempty = false
o:depends({ [option_name("protocol")] = "vmess" })
o:depends({ [option_name("protocol")] = "vless", [option_name("flow")] = "" })
o:depends({ [option_name("protocol")] = "shadowsocks" })
o:depends({ [option_name("protocol")] = "trojan" })
o:depends({ [_n("protocol")] = "vmess" })
o:depends({ [_n("protocol")] = "vless", [_n("flow")] = "" })
o:depends({ [_n("protocol")] = "shadowsocks" })
o:depends({ [_n("protocol")] = "trojan" })
-- [[ 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: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: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: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 = 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"
local nodes_table = {}
@ -391,46 +391,45 @@ for k, e in ipairs(api.get_valid_nodes()) do
end
end
o = s:option(ListValue, option_name("outbound_node"), translate("outbound node"))
o:value("nil", translate("Close"))
o = s:option(ListValue, _n("outbound_node"), translate("outbound node"))
o:value("", translate("Close"))
o:value("_socks", translate("Custom Socks"))
o:value("_http", translate("Custom HTTP"))
o:value("_iface", translate("Custom Interface"))
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:depends({ [option_name("outbound_node")] = "_socks" })
o:depends({ [option_name("outbound_node")] = "_http" })
o = s:option(Value, _n("outbound_node_address"), translate("Address (Support Domain Name)"))
o:depends({ [_n("outbound_node")] = "_socks" })
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:depends({ [option_name("outbound_node")] = "_socks" })
o:depends({ [option_name("outbound_node")] = "_http" })
o:depends({ [_n("outbound_node")] = "_socks" })
o:depends({ [_n("outbound_node")] = "_http" })
o = s:option(Value, option_name("outbound_node_username"), translate("Username"))
o:depends({ [option_name("outbound_node")] = "_socks" })
o:depends({ [option_name("outbound_node")] = "_http" })
o = s:option(Value, _n("outbound_node_username"), translate("Username"))
o:depends({ [_n("outbound_node")] = "_socks" })
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:depends({ [option_name("outbound_node")] = "_socks" })
o:depends({ [option_name("outbound_node")] = "_http" })
o:depends({ [_n("outbound_node")] = "_socks" })
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: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.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:value("debug")
o:value("info")
o:value("warn")
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)

View File

@ -10,7 +10,7 @@ local type_name = "SS-Rust"
local option_prefix = "ssrust_"
local function option_name(name)
local function _n(name)
return option_prefix .. name
end
@ -24,23 +24,23 @@ local ssrust_encrypt_method_list = {
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 = s:option(Value, option_name("password"), translate("Password"))
o = s:option(Value, _n("password"), translate("Password"))
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
o = s:option(Value, option_name("timeout"), translate("Connection Timeout"))
o = s:option(Value, _n("timeout"), translate("Connection Timeout"))
o.datatype = "uinteger"
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 = s:option(Flag, option_name("log"), translate("Log"))
o = s:option(Flag, _n("log"), translate("Log"))
o.default = "1"
o.rmempty = false

View File

@ -10,7 +10,7 @@ local type_name = "SS"
local option_prefix = "ss_"
local function option_name(name)
local function _n(name)
return option_prefix .. name
end
@ -27,23 +27,23 @@ local ss_encrypt_method_list = {
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 = s:option(Value, option_name("password"), translate("Password"))
o = s:option(Value, _n("password"), translate("Password"))
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
o = s:option(Value, option_name("timeout"), translate("Connection Timeout"))
o = s:option(Value, _n("timeout"), translate("Connection Timeout"))
o.datatype = "uinteger"
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 = s:option(Flag, option_name("log"), translate("Log"))
o = s:option(Flag, _n("log"), translate("Log"))
o.default = "1"
o.rmempty = false

View File

@ -10,7 +10,7 @@ local type_name = "SSR"
local option_prefix = "ssr_"
local function option_name(name)
local function _n(name)
return option_prefix .. name
end
@ -37,37 +37,37 @@ local ssr_obfs_list = {
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 = s:option(Value, option_name("password"), translate("Password"))
o = s:option(Value, _n("password"), translate("Password"))
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
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
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
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.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 = s:option(Flag, option_name("udp_forward"), translate("UDP Forward"))
o = s:option(Flag, _n("udp_forward"), translate("UDP Forward"))
o.default = "1"
o.rmempty = false
o = s:option(Flag, option_name("log"), translate("Log"))
o = s:option(Flag, _n("log"), translate("Log"))
o.default = "1"
o.rmempty = false

View File

@ -347,6 +347,26 @@ function get_domain_from_url(url)
return url
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()
local show_node_info = uci_get_type("global_other", "show_node_info") or "0"
local nodes = {}

View File

@ -21,7 +21,7 @@ end
function gen_outbound(flag, node, tag, proxy_table)
local result = nil
if node and node ~= "nil" then
if node then
local node_id = node[".name"]
if tag == nil then
tag = node_id
@ -47,7 +47,7 @@ function gen_outbound(flag, node, tag, proxy_table)
"127.0.0.1", --bind
new_port, --socks port
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
}
else
if proxy_tag and proxy_tag ~= "nil" then
if proxy_tag then
node.detour = proxy_tag
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
if node.outbound_node == "_iface" and node.outbound_node_iface then
outbound = {
@ -896,7 +896,7 @@ function gen_config(var)
end
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
else
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)
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
if _node_id == "_direct" then
rule_outboundTag = "direct"
@ -967,7 +967,7 @@ function gen_config(var)
rule_outboundTag = _outbound.tag
end
end
elseif _node_id ~= "nil" then
elseif _node_id then
local _node = uci:get_all(appname, _node_id)
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.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))
end
end
@ -1468,7 +1468,7 @@ function gen_config(var)
tag = "block"
})
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"))
end
for k, v in pairs(config.outbounds[index]) do

View File

@ -49,7 +49,7 @@ end
function gen_outbound(flag, node, tag, proxy_table)
local result = nil
if node and node ~= "nil" then
if node then
local node_id = node[".name"]
if tag == nil then
tag = node_id
@ -79,7 +79,7 @@ function gen_outbound(flag, node, tag, proxy_table)
"127.0.0.1", --bind
new_port, --socks port
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
if node.flow == "xtls-rprx-vision" then
else
if proxy_tag and proxy_tag ~= "nil" then
if proxy_tag then
node.proxySettings = {
tag = proxy_tag,
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
if node.outbound_node == "_iface" and node.outbound_node_iface then
outbound = {
@ -735,7 +735,7 @@ function gen_config(var)
-- fallback node
local fallback_node_tag = nil
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
local is_new_node = true
for _, outbound in ipairs(outbounds) do
@ -784,7 +784,7 @@ function gen_config(var)
local last_insert_outbound
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
else
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)
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
return "direct", nil
elseif _node_id == "_blackhole" then
@ -872,7 +872,7 @@ function gen_config(var)
end
end
return socks_tag, nil
elseif _node_id ~= "nil" then
elseif _node_id then
local _node = uci:get_all(appname, _node_id)
if not _node then return nil, nil end
@ -1031,7 +1031,7 @@ function gen_config(var)
table.insert(domains, w)
table.insert(domain_table.domain, w)
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))
end
if #domains == 0 then domains = nil end
@ -1549,7 +1549,7 @@ function gen_config(var)
end
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"))
end
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 node_select = document.getElementsByName(dom_id)[0];
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") {
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 node_select = document.getElementsByName(dom_id)[0];
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);
if (v) {
node_select.title = v.text;

View File

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

View File

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

View File

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

View File

@ -278,7 +278,7 @@ ln_run() {
lua_api() {
local func=${1}
[ -z "${func}" ] && {
echo "nil"
echo ""
return
}
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
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() {
@ -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
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() {
@ -701,11 +705,10 @@ socks_node_switch() {
}
run_global() {
[ "$NODE" = "nil" ] && return 1
TYPE=$(echo $(config_n_get $NODE type nil) | tr 'A-Z' 'a-z')
[ "$TYPE" = "nil" ] && return 1
[ -z "$NODE" ] && return 1
TYPE=$(echo $(config_n_get $NODE type) | tr 'A-Z' 'a-z')
[ -z "$TYPE" ] && return 1
mkdir -p $TMP_ACL_PATH/default
set_cache_var "GLOBAL_node" "$NODE"
if [ $PROXY_IPV6 == "1" ]; then
echolog "开启实验性IPv6透明代理(TProxy)请确认您的节点及类型支持IPv6"
@ -774,6 +777,9 @@ run_global() {
GLOBAL_DNSMASQ_PORT=$(get_new_port 11400)
run_copy_dnsmasq flag="default" listen_port=$GLOBAL_DNSMASQ_PORT tun_dns="${TUN_DNS}"
DNS_REDIRECT_PORT=${GLOBAL_DNSMASQ_PORT}
set_cache_var "ACL_GLOBAL_node" "$NODE"
set_cache_var "ACL_GLOBAL_redir_port" "$REDIR_PORT"
}
start_socks() {
@ -784,8 +790,8 @@ start_socks() {
for id in $ids; do
local enabled=$(config_n_get $id enabled 0)
[ "$enabled" == "0" ] && continue
local node=$(config_n_get $id node nil)
[ "$node" == "nil" ] && continue
local node=$(config_n_get $id node)
[ -z "$node" ] && continue
local bind_local=$(config_n_get $id bind_local 0)
local bind="0.0.0.0"
[ "$bind_local" = "1" ] && bind="127.0.0.1"
@ -846,23 +852,43 @@ start_crontab() {
return
}
auto_on=$(config_t_get global_delay auto_on 0)
if [ "$auto_on" = "1" ]; then
time_off=$(config_t_get global_delay time_off)
time_on=$(config_t_get global_delay time_on)
time_restart=$(config_t_get global_delay time_restart)
[ -z "$time_off" -o "$time_off" != "nil" ] && {
echo "0 $time_off * * * /etc/init.d/$CONFIG stop" >>/etc/crontabs/root
echolog "配置定时任务:每天 $time_off 点关闭服务。"
}
[ -z "$time_on" -o "$time_on" != "nil" ] && {
echo "0 $time_on * * * /etc/init.d/$CONFIG start" >>/etc/crontabs/root
echolog "配置定时任务:每天 $time_on 点开启服务。"
}
[ -z "$time_restart" -o "$time_restart" != "nil" ] && {
echo "0 $time_restart * * * /etc/init.d/$CONFIG restart" >>/etc/crontabs/root
echolog "配置定时任务:每天 $time_restart 点重启服务。"
}
stop_week_mode=$(config_t_get global_delay stop_week_mode)
stop_time_mode=$(config_t_get global_delay stop_time_mode)
if [ -n "$stop_week_mode" ]; then
local t="0 $stop_time_mode * * $stop_week_mode"
[ "$stop_week_mode" = "7" ] && t="0 $stop_time_mode * * *"
if [ "$stop_week_mode" = "8" ]; then
update_loop=1
else
echo "$t /etc/init.d/$CONFIG stop > /dev/null 2>&1 &" >>/etc/crontabs/root
fi
echolog "配置定时任务:自动关闭服务。"
fi
start_week_mode=$(config_t_get global_delay start_week_mode)
start_time_mode=$(config_t_get global_delay start_time_mode)
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
autoupdate=$(config_t_get global_rules auto_update)
@ -1098,7 +1124,7 @@ acl_app() {
dnsmasq_port=${GLOBAL_DNSMASQ_PORT:-11400}
for item in $items; do
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
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-)
@ -1127,30 +1153,46 @@ acl_app() {
mkdir -p $TMP_ACL_PATH/$sid
[ ! -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}
direct_dns_query_strategy=${direct_dns_query_strategy:-UseIP}
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}
tcp_no_redir_ports=${tcp_no_redir_ports:-default}
udp_no_redir_ports=${udp_no_redir_ports:-default}
[ "$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
[ "$tcp_no_redir_ports" == "1:65535" ] && [ "$udp_no_redir_ports" == "1:65535" ] && unset node
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
node=$NODE
redir_port=$REDIR_PORT
if [ -n "${GLOBAL_node}" ]; then
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
[ "$(config_get_type $node nil)" = "nodes" ] && {
if [ "$node" = "$NODE" ]; then
redir_port=$REDIR_PORT
[ "$(config_get_type $node)" = "nodes" ] && {
if [ -n "${GLOBAL_node}" ] && [ "$node" = "${GLOBAL_node}" ]; then
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
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')
if [ -n "${type}" ]; then
@ -1169,16 +1211,14 @@ acl_app() {
fi
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}"
eval node_${node}_$(echo -n "${tcp_proxy_mode}${remote_dns}" | md5sum | cut -d " " -f1)=${dnsmasq_port}
filter_node $node TCP > /dev/null 2>&1 &
filter_node $node UDP > /dev/null 2>&1 &
set_cache_var "ACL_${sid}_node" "$node"
set_cache_var "ACL_${sid}_redir_port" "$redir_port"
fi
set_cache_var "ACL_${sid}_node" "${node}"
}
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
done
unset redir_port dns_port dnsmasq_port
@ -1272,9 +1312,9 @@ stop() {
}
ENABLED=$(config_t_get global enabled 0)
NODE=$(config_t_get global node nil)
NODE=$(config_t_get global node)
[ "$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" == 1 ] && {

View File

@ -209,8 +209,8 @@ gen_shunt_list() {
[ "$default_node" = "_direct" ] && default_outbound="direct"
local shunt_ids=$(uci show $CONFIG | grep "=shunt_rules" | awk -F '.' '{print $2}' | awk -F '=' '{print $1}')
for shunt_id in $shunt_ids; do
local shunt_node=$(config_n_get ${node} "${shunt_id}" nil)
[ "$shunt_node" != "nil" ] && {
local shunt_node=$(config_n_get ${node} "${shunt_id}")
[ -n "$shunt_node" ] && {
local ipset_v4="passwall2_${node}_${shunt_id}"
local ipset_v6="passwall2_${node}_${shunt_id}6"
ipset -! create $ipset_v4 nethash maxelem 1048576
@ -244,7 +244,7 @@ gen_shunt_list() {
_SHUNT_LIST4="${_SHUNT_LIST4} ${_set_name4}:direct"
_SHUNT_LIST6="${_SHUNT_LIST6} ${_set_name6}:direct"
}
[ "$default_node" != "nil" ] && {
[ -n "$default_node" ] && {
local ipset_v4="passwall2_${node}_default"
local ipset_v6="passwall2_${node}_default6"
ipset -! create $ipset_v4 nethash maxelem 1048576
@ -276,8 +276,8 @@ add_shunt_t_rule() {
load_acl() {
[ "$ENABLED_ACLS" == 1 ] && {
acl_app
echolog "访问控制:"
acl_app
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-)
@ -285,24 +285,26 @@ load_acl() {
udp_no_redir_ports=${udp_no_redir_ports:-default}
tcp_proxy_mode="global"
udp_proxy_mode="global"
tcp_redir_ports=${tcp_redir_ports:-default}
udp_redir_ports=${udp_redir_ports:-default}
node=${node:-default}
[ "$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
[ "$tcp_redir_ports" = "default" ] && tcp_redir_ports=$TCP_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}_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")
[ "$node" = "default" ] && dns_redirect_port=${DNS_REDIRECT_PORT}
[ -n "$node" ] && [ "$node" != "default" ] && node_remark=$(config_n_get $node remarks)
[ -n "$node" ] && node_remark=$(config_n_get $node remarks)
write_ipset_direct=${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_whitelist6=${ipset_global_whitelist6}
shunt_list4=${SHUNT_LIST4}
shunt_list6=${SHUNT_LIST6}
else
local ipset_whitelist="passwall2_${sid}_whitelist"
local ipset_whitelist6="passwall2_${sid}_whitelist6"
@ -387,7 +389,7 @@ load_acl() {
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
$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
@ -490,7 +492,7 @@ load_acl() {
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" ] && {
$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
@ -499,7 +501,7 @@ load_acl() {
}
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)]"
if [ -n "${is_tproxy}" ]; then
msg2="${msg2}(TPROXY:${REDIR_PORT})"
@ -536,7 +538,7 @@ load_acl() {
echolog "${msg2}"
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})"
$ipt_m -A PSW2 $(comment "默认") -p udp -d $FAKE_IP -j PSW2_RULE
@ -595,7 +597,7 @@ filter_server_port() {
filter_node() {
local node=${1}
local stream=${2}
if [ -n "$node" ] && [ "$node" != "nil" ]; then
if [ -n "$node" ]; then
local address=$(config_n_get $node address)
local port=$(config_n_get $node port)
[ -z "$address" ] && [ -z "$port" ] && {
@ -836,7 +838,7 @@ add_firewall_rule() {
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" ] && {
$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
@ -846,7 +848,7 @@ add_firewall_rule() {
fi
# 加载路由器自身代理 TCP
if [ "$NODE" != "nil" ] && [ "$TCP_LOCALHOST_PROXY" = "1" ]; then
if [ -n "$NODE" ] && [ "$TCP_LOCALHOST_PROXY" = "1" ]; then
[ "$accept_icmp" = "1" ] && {
$ipt_n -A OUTPUT -p icmp -j PSW2_OUTPUT
$ipt_n -A PSW2_OUTPUT -p icmp -d $FAKE_IP $(REDIRECT)
@ -895,7 +897,7 @@ add_firewall_rule() {
fi
# 加载路由器自身代理 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
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

View File

@ -263,8 +263,8 @@ gen_shunt_list() {
[ "$default_node" = "_direct" ] && default_outbound="direct"
local shunt_ids=$(uci show $CONFIG | grep "=shunt_rules" | awk -F '.' '{print $2}' | awk -F '=' '{print $1}')
for shunt_id in $shunt_ids; do
local shunt_node=$(config_n_get ${node} "${shunt_id}" nil)
[ "$shunt_node" != "nil" ] && {
local shunt_node=$(config_n_get ${node} "${shunt_id}")
[ -n "$shunt_node" ] && {
local nftset_v4="passwall2_${node}_${shunt_id}"
local nftset_v6="passwall2_${node}_${shunt_id}6"
gen_nftset $nftset_v4 ipv4_addr 0 0
@ -297,7 +297,7 @@ gen_shunt_list() {
_SHUNT_LIST4="${_SHUNT_LIST4} ${_set_name4}:direct"
_SHUNT_LIST6="${_SHUNT_LIST6} ${_set_name6}:direct"
}
[ "$default_node" != "nil" ] && {
[ -n "$default_node" ] && {
local nftset_v4="passwall2_${node}_default"
local nftset_v6="passwall2_${node}_default6"
gen_nftset $nftset_v4 ipv4_addr 0 0
@ -331,8 +331,8 @@ add_shunt_t_rule() {
load_acl() {
[ "$ENABLED_ACLS" == 1 ] && {
acl_app
echolog "访问控制:"
acl_app
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-)
@ -340,24 +340,26 @@ load_acl() {
udp_no_redir_ports=${udp_no_redir_ports:-default}
tcp_proxy_mode="global"
udp_proxy_mode="global"
tcp_redir_ports=${tcp_redir_ports:-default}
udp_redir_ports=${udp_redir_ports:-default}
node=${node:-default}
[ "$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
[ "$tcp_redir_ports" = "default" ] && tcp_redir_ports=$TCP_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}_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")
[ "$node" = "default" ] && dns_redirect_port=${DNS_REDIRECT_PORT}
[ -n "$node" ] && [ "$node" != "default" ] && node_remark=$(config_n_get $node remarks)
[ -n "$node" ] && node_remark=$(config_n_get $node remarks)
write_ipset_direct=${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_whitelist6=${nftset_global_whitelist6}
shunt_list4=${SHUNT_LIST4}
shunt_list6=${SHUNT_LIST6}
else
local nftset_whitelist="passwall2_${sid}_whitelist"
local nftset_whitelist6="passwall2_${sid}_whitelist6"
@ -432,7 +434,7 @@ load_acl() {
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" ] && {
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\""
@ -539,7 +541,7 @@ load_acl() {
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" ] && {
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 \"默认\""
@ -548,7 +550,7 @@ load_acl() {
}
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)]"
if [ -n "${is_tproxy}" ]; then
msg2="${msg2}(TPROXY:${REDIR_PORT})"
@ -589,7 +591,7 @@ load_acl() {
echolog "${msg2}"
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})"
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() {
local node=${1}
local stream=${2}
if [ -n "$node" ] && [ "$node" != "nil" ]; then
if [ -n "$node" ]; then
local address=$(config_n_get $node address)
local port=$(config_n_get $node port)
[ -z "$address" ] && [ -z "$port" ] && {
@ -889,7 +891,7 @@ add_firewall_rule() {
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" ] && {
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\""
@ -899,7 +901,7 @@ add_firewall_rule() {
fi
# 加载路由器自身代理 TCP
if [ "$NODE" != "nil" ] && [ "$TCP_LOCALHOST_PROXY" = "1" ]; then
if [ -n "$NODE" ] && [ "$TCP_LOCALHOST_PROXY" = "1" ]; then
[ "$accept_icmp" = "1" ] && {
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"
@ -949,7 +951,7 @@ add_firewall_rule() {
fi
# 加载路由器自身代理 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"
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"

View File

@ -57,8 +57,8 @@ test_proxy() {
test_node() {
local node_id=$1
local _type=$(echo $(config_n_get ${node_id} type nil) | tr 'A-Z' 'a-z')
[ "${_type}" != "nil" ] && {
local _type=$(echo $(config_n_get ${node_id} type) | tr 'A-Z' 'a-z')
[ -n "${_type}" ] && {
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
local curlx="socks5h://127.0.0.1:${_tmp_port}"
@ -97,7 +97,7 @@ test_auto_switch() {
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}
[ $? -eq 0 ] && {
#主节点正常,切换到主节点
@ -153,7 +153,7 @@ test_auto_switch() {
start() {
id=$1
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)
delay=$(config_n_get $id autoswitch_testing_time 30)
sleep 5s
@ -161,8 +161,8 @@ start() {
retry_num=$(config_n_get $id autoswitch_retry_num 1)
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")
backup_node=$(config_n_get $id autoswitch_backup_node nil)
while [ -n "$backup_node" -a "$backup_node" != "nil" ]; do
backup_node=$(config_n_get $id autoswitch_backup_node)
while [ -n "$backup_node" ]; do
[ -f "$LOCK_FILE" ] && {
sleep 6s
continue

View File

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

View File

@ -30,6 +30,33 @@ do
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)
weekupdate=$(config_t_get global_rules week_update)
hourupdate=$(config_t_get global_rules interval_update)

View File

@ -63,8 +63,8 @@ test_proxy() {
url_test_node() {
result=0
local node_id=$1
local _type=$(echo $(config_n_get ${node_id} type nil) | tr 'A-Z' 'a-z')
[ "${_type}" != "nil" ] && {
local _type=$(echo $(config_n_get ${node_id} type) | tr 'A-Z' 'a-z')
[ -n "${_type}" ] && {
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
local curlx="socks5h://127.0.0.1:${_tmp_port}"
@ -78,8 +78,8 @@ url_test_node() {
test_node() {
local node_id=$1
local _type=$(echo $(config_n_get ${node_id} type nil) | tr 'A-Z' 'a-z')
[ "${_type}" != "nil" ] && {
local _type=$(echo $(config_n_get ${node_id} type) | tr 'A-Z' 'a-z')
[ -n "${_type}" ] && {
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
local curlx="socks5h://127.0.0.1:${_tmp_port}"