parent
38a728258f
commit
a89e62e998
@ -6,7 +6,7 @@ include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=luci-app-passwall2
|
||||
PKG_VERSION:=24.11.17
|
||||
PKG_RELEASE:=1
|
||||
PKG_RELEASE:=2
|
||||
|
||||
PKG_CONFIG_DEPENDS:= \
|
||||
CONFIG_PACKAGE_$(PKG_NAME)_Iptables_Transparent_Proxy \
|
||||
|
@ -147,6 +147,7 @@ if has_xray then
|
||||
o = s_xray:option(ListValue, "fragment_packets", translate("Fragment Packets"), translate(" \"1-3\" is for segmentation at TCP layer, applying to the beginning 1 to 3 data writes by the client. \"tlshello\" is for TLS client hello packet fragmentation."))
|
||||
o.default = "tlshello"
|
||||
o:value("tlshello", "tlshello")
|
||||
o:value("1-1", "1-1")
|
||||
o:value("1-2", "1-2")
|
||||
o:value("1-3", "1-3")
|
||||
o:value("1-5", "1-5")
|
||||
|
@ -334,9 +334,10 @@ o:depends({ [option_name("protocol")] = "shadowsocks" })
|
||||
|
||||
o = s:option(Flag, option_name("reality"), translate("REALITY"))
|
||||
o.default = 0
|
||||
o:depends({ [option_name("tls")] = true, [option_name("transport")] = "tcp" })
|
||||
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 = s:option(ListValue, option_name("alpn"), translate("alpn"))
|
||||
o.default = "default"
|
||||
@ -392,7 +393,7 @@ o:depends({ [option_name("tls")] = true, [option_name("utls")] = true })
|
||||
o:depends({ [option_name("tls")] = true, [option_name("reality")] = true })
|
||||
|
||||
o = s:option(ListValue, option_name("transport"), translate("Transport"))
|
||||
o:value("tcp", "TCP")
|
||||
o:value("raw", "RAW")
|
||||
o:value("mkcp", "mKCP")
|
||||
o:value("ws", "WebSocket")
|
||||
o:value("h2", "HTTP/2")
|
||||
@ -400,7 +401,7 @@ o:value("ds", "DomainSocket")
|
||||
o:value("quic", "QUIC")
|
||||
o:value("grpc", "gRPC")
|
||||
o:value("httpupgrade", "HttpUpgrade")
|
||||
o:value("splithttp", "SplitHTTP")
|
||||
o:value("xhttp", "XHTTP")
|
||||
o:depends({ [option_name("protocol")] = "vmess" })
|
||||
o:depends({ [option_name("protocol")] = "vless" })
|
||||
o:depends({ [option_name("protocol")] = "socks" })
|
||||
@ -432,13 +433,13 @@ o = s:option(Value, option_name("wireguard_keepAlive"), translate("Keep Alive"))
|
||||
o.default = "0"
|
||||
o:depends({ [option_name("protocol")] = "wireguard" })
|
||||
|
||||
-- [[ TCP部分 ]]--
|
||||
-- [[ RAW部分 ]]--
|
||||
|
||||
-- TCP伪装
|
||||
o = s:option(ListValue, option_name("tcp_guise"), translate("Camouflage Type"))
|
||||
o:value("none", "none")
|
||||
o:value("http", "http")
|
||||
o:depends({ [option_name("transport")] = "tcp" })
|
||||
o:depends({ [option_name("transport")] = "raw" })
|
||||
|
||||
-- HTTP域名
|
||||
o = s:option(DynamicList, option_name("tcp_guise_http_host"), translate("HTTP Host"))
|
||||
@ -566,16 +567,115 @@ o = s:option(Value, option_name("httpupgrade_path"), translate("HttpUpgrade Path
|
||||
o.placeholder = "/"
|
||||
o:depends({ [option_name("transport")] = "httpupgrade" })
|
||||
|
||||
-- [[ SplitHTTP部分 ]]--
|
||||
o = s:option(Value, option_name("splithttp_host"), translate("SplitHTTP Host"))
|
||||
o:depends({ [option_name("transport")] = "splithttp" })
|
||||
-- [[ XHTTP部分 ]]--
|
||||
o = s:option(Value, option_name("xhttp_host"), translate("XHTTP Host"))
|
||||
o:depends({ [option_name("transport")] = "xhttp" })
|
||||
|
||||
o = s:option(Value, option_name("splithttp_path"), translate("SplitHTTP Path"))
|
||||
o = s:option(Value, option_name("xhttp_path"), translate("XHTTP Path"))
|
||||
o.placeholder = "/"
|
||||
o:depends({ [option_name("transport")] = "splithttp" })
|
||||
o:depends({ [option_name("transport")] = "xhttp" })
|
||||
|
||||
-- [[ Mux ]]--
|
||||
o = s:option(Flag, option_name("mux"), translate("Mux"))
|
||||
-- XHTTP XMUX
|
||||
o = s:option(Flag, option_name("xhttp_xmux"), "XMUX", translate("Enable XHTTP XMUX. It's not recommended to enable Mux.Cool at the same time."))
|
||||
o:depends({ [option_name("transport")] = "xhttp" })
|
||||
|
||||
o = s:option(Value, option_name("maxConcurrency"), translate("XMUX Max Concurrency"))
|
||||
o:depends({ [option_name("xhttp_xmux")] = true })
|
||||
|
||||
o = s:option(Value, option_name("maxConnections"), translate("XMUX Max Connections"))
|
||||
o:depends({ [option_name("xhttp_xmux")] = true })
|
||||
|
||||
o = s:option(Value, option_name("cMaxReuseTimes"), translate("XMUX Connection Max Reuse Times"))
|
||||
o:depends({ [option_name("xhttp_xmux")] = true })
|
||||
|
||||
o = s:option(Value, option_name("cMaxLifetimeMs"), translate("XMUX Connection Max Lifetime (ms)"))
|
||||
o:depends({ [option_name("xhttp_xmux")] = true })
|
||||
|
||||
-- XHTTP 下行
|
||||
o = s:option(Flag, option_name("xhttp_download"), string.format('<a style="color:red">%s</a>', translate("XHTTP download splitting")))
|
||||
o:depends({ [option_name("transport")] = "xhttp" })
|
||||
|
||||
o = s:option(Value, option_name("xhttp_download_address"), string.format('<a style="color:red">%s</a>', translate("Address")))
|
||||
o:depends({ [option_name("xhttp_download")] = true })
|
||||
|
||||
o = s:option(Value, option_name("xhttp_download_port"), string.format('<a style="color:red">%s</a>', translate("Port")))
|
||||
o:depends({ [option_name("xhttp_download")] = true })
|
||||
|
||||
o = s:option(Value, option_name("xhttp_download_host"), string.format('<a style="color:red">%s</a>', "XHTTP Host"))
|
||||
o:depends({ [option_name("xhttp_download")] = true })
|
||||
|
||||
o = s:option(Value, option_name("xhttp_download_path"), string.format('<a style="color:red">%s</a>', "XHTTP Path"), translate("Must be the same as upload path."))
|
||||
o.placeholder = "/"
|
||||
o:depends({ [option_name("xhttp_download")] = true })
|
||||
|
||||
o = s:option(Flag, option_name("xhttp_download_tls"), string.format('<a style="color:red">%s</a>', "TLS"))
|
||||
o:depends({ [option_name("xhttp_download")] = true })
|
||||
o.default = 0
|
||||
|
||||
o = s:option(Flag, option_name("xhttp_download_reality"), string.format('<a style="color:red">%s</a>', "REALITY"))
|
||||
o.default = 0
|
||||
o:depends({ [option_name("xhttp_download_tls")] = true })
|
||||
|
||||
o = s:option(ListValue, option_name("xhttp_download_alpn"), string.format('<a style="color:red">%s</a>', "alpn"))
|
||||
o.default = "default"
|
||||
o:value("default", translate("Default"))
|
||||
o:value("h3")
|
||||
o:value("h2")
|
||||
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("xhttp_download_tls")] = true, [option_name("xhttp_download_reality")] = false })
|
||||
|
||||
o = s:option(Value, option_name("xhttp_download_tls_serverName"), string.format('<a style="color:red">%s</a>', translate("Domain")))
|
||||
o:depends({ [option_name("xhttp_download_tls")] = true })
|
||||
|
||||
o = s:option(Value, option_name("xhttp_download_reality_publicKey"), string.format('<a style="color:red">%s</a>', translate("Public Key")))
|
||||
o:depends({ [option_name("xhttp_download_tls")] = true, [option_name("xhttp_download_reality")] = true })
|
||||
|
||||
o = s:option(Value, option_name("xhttp_download_reality_shortId"), string.format('<a style="color:red">%s</a>', translate("Short Id")))
|
||||
o:depends({ [option_name("xhttp_download_tls")] = true, [option_name("xhttp_download_reality")] = true })
|
||||
|
||||
o = s:option(Value, option_name("xhttp_download_reality_spiderX"), string.format('<a style="color:red">%s</a>', "Spider X"))
|
||||
o.placeholder = "/"
|
||||
o:depends({ [option_name("xhttp_download_tls")] = true, [option_name("xhttp_download_reality")] = true })
|
||||
|
||||
o = s:option(Flag, option_name("xhttp_download_utls"), string.format('<a style="color:red">%s</a>', "uTLS"))
|
||||
o.default = "0"
|
||||
o:depends({ [option_name("xhttp_download_tls")] = true, [option_name("xhttp_download_reality")] = false })
|
||||
|
||||
o = s:option(ListValue, option_name("xhttp_download_fingerprint"), string.format('<a style="color:red">%s</a>', translate("Finger Print")))
|
||||
o:value("chrome")
|
||||
o:value("firefox")
|
||||
o:value("edge")
|
||||
o:value("safari")
|
||||
o:value("360")
|
||||
o:value("qq")
|
||||
o:value("ios")
|
||||
o:value("android")
|
||||
o:value("random")
|
||||
o:value("randomized")
|
||||
o.default = "chrome"
|
||||
o:depends({ [option_name("xhttp_download_tls")] = true, [option_name("xhttp_download_utls")] = true })
|
||||
o:depends({ [option_name("xhttp_download_tls")] = true, [option_name("xhttp_download_reality")] = true })
|
||||
|
||||
o = s:option(Flag, option_name("xhttp_download_xmux"), string.format('<a style="color:red">%s</a>', "XMUX"), translate("Enable XHTTP XMUX. It's not recommended to enable Mux.Cool at the same time."))
|
||||
o:depends({ [option_name("xhttp_download")] = true })
|
||||
|
||||
o = s:option(Value, option_name("download_maxConcurrency"), string.format('<a style="color:red">%s</a>', translate("XMUX Max Concurrency")))
|
||||
o:depends({ [option_name("xhttp_download_xmux")] = true })
|
||||
|
||||
o = s:option(Value, option_name("download_maxConnections"), string.format('<a style="color:red">%s</a>', translate("XMUX Max Connections")))
|
||||
o:depends({ [option_name("xhttp_download_xmux")] = true })
|
||||
|
||||
o = s:option(Value, option_name("download_cMaxReuseTimes"), string.format('<a style="color:red">%s</a>', translate("XMUX Connection Max Reuse Times")))
|
||||
o:depends({ [option_name("xhttp_download_xmux")] = true })
|
||||
|
||||
o = s:option(Value, option_name("download_cMaxLifetimeMs"), string.format('<a style="color:red">%s</a>', translate("XMUX Connection Max Lifetime (ms)")))
|
||||
o:depends({ [option_name("xhttp_download_xmux")] = true })
|
||||
|
||||
-- [[ 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" })
|
||||
@ -588,7 +688,7 @@ o.default = 8
|
||||
o:depends({ [option_name("mux")] = true })
|
||||
|
||||
-- [[ XUDP Mux ]]--
|
||||
o = s:option(Flag, option_name("xmux"), translate("xMux"))
|
||||
o = s:option(Flag, option_name("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" })
|
||||
|
@ -110,6 +110,15 @@ function gen_outbound(flag, node, tag, proxy_table)
|
||||
end
|
||||
end
|
||||
|
||||
if node.type == "Xray" and node.transport == "xhttp" then
|
||||
if node.xhttp_download_tls and node.xhttp_download_tls == "1" then
|
||||
node.xhttp_download_stream_security = "tls"
|
||||
if node.xhttp_download_reality and node.xhttp_download_reality == "1" then
|
||||
node.xhttp_download_stream_security = "reality"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if node.protocol == "wireguard" and node.wireguard_reserved then
|
||||
local bytes = {}
|
||||
if not node.wireguard_reserved:match("[^%d,]+") then
|
||||
@ -159,7 +168,7 @@ function gen_outbound(flag, node, tag, proxy_table)
|
||||
spiderX = node.reality_spiderX or "/",
|
||||
fingerprint = (node.type == "Xray" and node.fingerprint and node.fingerprint ~= "") and node.fingerprint or "chrome"
|
||||
} or nil,
|
||||
tcpSettings = (node.transport == "tcp" and node.protocol ~= "socks") and {
|
||||
rawSettings = ((node.transport == "raw" or node.transport == "tcp") and node.protocol ~= "socks") and {
|
||||
header = {
|
||||
type = node.tcp_guise or "none",
|
||||
request = (node.tcp_guise == "http") and {
|
||||
@ -213,9 +222,35 @@ function gen_outbound(flag, node, tag, proxy_table)
|
||||
path = node.httpupgrade_path or "/",
|
||||
host = node.httpupgrade_host
|
||||
} or nil,
|
||||
splithttpSettings = (node.transport == "splithttp") and {
|
||||
path = node.splithttp_path or "/",
|
||||
host = node.splithttp_host
|
||||
xhttpSettings = (node.transport == "xhttp" or node.transport == "splithttp") and {
|
||||
path = node.xhttp_path or node.splithttp_path or "/",
|
||||
host = node.xhttp_host or node.splithttp_host,
|
||||
downloadSettings = (node.xhttp_download == "1") and {
|
||||
address = node.xhttp_download_address,
|
||||
port = tonumber(node.xhttp_download_port),
|
||||
network = "xhttp",
|
||||
xhttpSettings = {
|
||||
path = node.xhttp_download_path,
|
||||
host = node.xhttp_download_host,
|
||||
},
|
||||
security = node.xhttp_download_stream_security,
|
||||
tlsSettings = (node.xhttp_download_stream_security == "tls") and {
|
||||
serverName = node.xhttp_download_tls_serverName,
|
||||
allowInsecure = false,
|
||||
fingerprint = (node.xhttp_download_utls == "1" and
|
||||
node.xhttp_download_fingerprint and
|
||||
node.xhttp_download_fingerprint ~= "") and node.xhttp_download_fingerprint or nil
|
||||
} or nil,
|
||||
realitySettings = (node.xhttp_download_stream_security == "reality") and {
|
||||
serverName = node.xhttp_download_tls_serverName,
|
||||
publicKey = node.xhttp_download_reality_publicKey,
|
||||
shortId = node.xhttp_download_reality_shortId or "",
|
||||
spiderX = node.xhttp_download_reality_spiderX or "/",
|
||||
fingerprint = (
|
||||
node.xhttp_download_fingerprint and
|
||||
node.xhttp_download_fingerprint ~= "") and node.xhttp_download_fingerprint or nil
|
||||
} or nil,
|
||||
} or nil
|
||||
} or nil,
|
||||
} or nil,
|
||||
settings = {
|
||||
@ -280,6 +315,41 @@ function gen_outbound(flag, node, tag, proxy_table)
|
||||
result.streamSettings.tlsSettings.alpn = alpn
|
||||
end
|
||||
end
|
||||
|
||||
local alpn_download = {}
|
||||
if node.xhttp_download_alpn and node.xhttp_download_alpn ~= "default" then
|
||||
string.gsub(node.xhttp_download_alpn, '[^' .. "," .. ']+', function(w)
|
||||
table.insert(alpn_download, w)
|
||||
end)
|
||||
end
|
||||
if alpn_download and #alpn_download > 0 then
|
||||
if result.streamSettings.xhttpSettings.downloadSettings.tlsSettings then
|
||||
result.streamSettings.xhttpSettings.downloadSettings.tlsSettings.alpn = alpn_download
|
||||
end
|
||||
end
|
||||
|
||||
local xmux = {}
|
||||
if (node.xhttp_xmux == "1") then
|
||||
xmux.maxConcurrency = node.maxConcurrency and (string.find(node.maxConcurrency, "-") and node.maxConcurrency or tonumber(node.maxConcurrency)) or 0
|
||||
xmux.maxConnections = node.maxConnections and (string.find(node.maxConnections, "-") and node.maxConnections or tonumber(node.maxConnections)) or 0
|
||||
xmux.cMaxReuseTimes = node.cMaxReuseTimes and (string.find(node.cMaxReuseTimes, "-") and node.cMaxReuseTimes or tonumber(node.cMaxReuseTimes)) or 0
|
||||
xmux.cMaxLifetimeMs = node.cMaxLifetimeMs and (string.find(node.cMaxLifetimeMs, "-") and node.cMaxLifetimeMs or tonumber(node.cMaxLifetimeMs)) or 0
|
||||
if result.streamSettings.xhttpSettings then
|
||||
result.streamSettings.xhttpSettings.xmux = xmux
|
||||
end
|
||||
end
|
||||
|
||||
local xmux_download = {}
|
||||
if (node.xhttp_download_xmux == "1") then
|
||||
xmux_download.maxConcurrency = node.download_maxConcurrency and (string.find(node.download_maxConcurrency, "-") and node.download_maxConcurrency or tonumber(node.download_maxConcurrency)) or 0
|
||||
xmux_download.maxConnections = node.download_maxConnections and (string.find(node.download_maxConnections, "-") and node.download_maxConnections or tonumber(node.download_maxConnections)) or 0
|
||||
xmux_download.cMaxReuseTimes = node.download_cMaxReuseTimes and (string.find(node.download_cMaxReuseTimes, "-") and node.download_cMaxReuseTimes or tonumber(node.download_cMaxReuseTimes)) or 0
|
||||
xmux_download.cMaxLifetimeMs = node.download_cMaxLifetimeMs and (string.find(node.download_cMaxLifetimeMs, "-") and node.download_cMaxLifetimeMs or tonumber(node.download_cMaxLifetimeMs)) or 0
|
||||
if result.streamSettings.xhttpSettings.downloadSettings.xhttpSettings then
|
||||
result.streamSettings.xhttpSettings.downloadSettings.xhttpSettings.xmux = xmux_download
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
return result
|
||||
end
|
||||
@ -447,7 +517,7 @@ function gen_config_server(node)
|
||||
}
|
||||
}
|
||||
} or nil,
|
||||
tcpSettings = (node.transport == "tcp") and {
|
||||
rawSettings = (node.transport == "raw" or node.transport == "tcp") and {
|
||||
header = {
|
||||
type = node.tcp_guise,
|
||||
request = (node.tcp_guise == "http") and {
|
||||
@ -672,9 +742,20 @@ function gen_config(var)
|
||||
return inboundTag
|
||||
end
|
||||
|
||||
local function gen_balancer(_node, loopbackTag)
|
||||
local function gen_balancer(_node, loopback_tag)
|
||||
local balancer_id = _node[".name"]
|
||||
local balancer_tag = "balancer-" .. balancer_id
|
||||
local loopback_dst = balancer_id -- route destination for the loopback outbound
|
||||
if not loopback_tag or loopback_tag == "" then loopback_tag = balancer_id end
|
||||
-- existing balancer
|
||||
for _, v in ipairs(balancers) do
|
||||
if v.tag == balancer_tag then
|
||||
gen_loopback(loopback_tag, loopback_dst)
|
||||
return balancer_tag
|
||||
end
|
||||
end
|
||||
-- new balancer
|
||||
local blc_nodes = _node.balancing_node
|
||||
local fallback_node_id = _node.fallback_node
|
||||
local length = #blc_nodes
|
||||
local valid_nodes = {}
|
||||
for i = 1, length do
|
||||
@ -698,6 +779,10 @@ function gen_config(var)
|
||||
end
|
||||
end
|
||||
end
|
||||
if #valid_nodes == 0 then return nil end
|
||||
|
||||
-- fallback node
|
||||
local fallback_node_id = _node.fallback_node
|
||||
if fallback_node_id == "" then fallback_node_id = nil end
|
||||
if fallback_node_id then
|
||||
local is_new_node = true
|
||||
@ -718,19 +803,14 @@ function gen_config(var)
|
||||
fallback_node_id = nil
|
||||
end
|
||||
else
|
||||
local valid = gen_balancer(fallback_node)
|
||||
if not valid then
|
||||
if not gen_balancer(fallback_node) then
|
||||
fallback_node_id = nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local valid = nil
|
||||
if #valid_nodes > 0 then
|
||||
local balancerTag = get_balancer_tag(_node[".name"])
|
||||
table.insert(balancers, {
|
||||
tag = balancerTag,
|
||||
tag = balancer_tag,
|
||||
selector = valid_nodes,
|
||||
fallbackTag = fallback_node_id,
|
||||
strategy = { type = _node.balancingStrategy or "random" }
|
||||
@ -745,12 +825,9 @@ function gen_config(var)
|
||||
}
|
||||
end
|
||||
end
|
||||
if loopbackTag == nil or loopbackTag =="" then loopbackTag = _node[".name"] end
|
||||
local inboundTag = gen_loopback(loopbackTag, _node[".name"])
|
||||
table.insert(rules, { inboundTag = { inboundTag }, balancerTag = balancerTag })
|
||||
valid = true
|
||||
end
|
||||
return valid
|
||||
local inbound_tag = gen_loopback(loopback_tag, loopback_dst)
|
||||
table.insert(rules, { inboundTag = { inbound_tag }, balancerTag = balancer_tag })
|
||||
return balancer_tag
|
||||
end
|
||||
|
||||
local function set_outbound_detour(node, outbound, outbounds_table, shunt_rule_name)
|
||||
@ -787,31 +864,25 @@ function gen_config(var)
|
||||
node.port = server_port
|
||||
end
|
||||
if node.protocol == "_shunt" then
|
||||
local preproxy_enabled = node.preproxy_enabled == "1"
|
||||
local preproxy_rule_name = "main"
|
||||
local preproxy_tag = "main"
|
||||
local preproxy_rule_name = node.preproxy_enabled == "1" and "main" or nil
|
||||
local preproxy_tag = preproxy_rule_name
|
||||
local preproxy_node_id = node["main_node"]
|
||||
local preproxy_node = preproxy_enabled and preproxy_node_id and uci:get_all(appname, preproxy_node_id) or nil
|
||||
if preproxy_node then
|
||||
preproxy_tag = preproxy_tag .. ":" .. preproxy_node.remarks
|
||||
end
|
||||
|
||||
local proxy_outboundTag, proxy_balancerTag
|
||||
local preproxy_outbound_tag, preproxy_balancer_tag
|
||||
local preproxy_nodes
|
||||
|
||||
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
|
||||
local rule_outboundTag
|
||||
local rule_balancerTag
|
||||
if _node_id == "_direct" then
|
||||
rule_outboundTag = "direct"
|
||||
return "direct", nil
|
||||
elseif _node_id == "_blackhole" then
|
||||
rule_outboundTag = "blackhole"
|
||||
return "blackhole", nil
|
||||
elseif _node_id == "_default" then
|
||||
rule_outboundTag = "default"
|
||||
return "default", nil
|
||||
elseif _node_id:find("Socks_") then
|
||||
local socks_id = _node_id:sub(1 + #"Socks_")
|
||||
local socks_node = uci:get_all(appname, socks_id) or nil
|
||||
local socks_tag
|
||||
if socks_node then
|
||||
local _node = {
|
||||
type = "Xray",
|
||||
@ -823,27 +894,25 @@ function gen_config(var)
|
||||
}
|
||||
local outbound = gen_outbound(flag, _node, rule_name)
|
||||
if outbound then
|
||||
if rule_name == "default" then
|
||||
table.insert(outbounds, 1, outbound)
|
||||
else
|
||||
table.insert(outbounds, outbound)
|
||||
rule_outboundTag = outbound.tag
|
||||
end
|
||||
socks_tag = outbound.tag
|
||||
end
|
||||
end
|
||||
return socks_tag, nil
|
||||
elseif _node_id ~= "nil" then
|
||||
local _node = uci:get_all(appname, _node_id)
|
||||
if not _node then return nil, nil end
|
||||
|
||||
if api.is_normal_node(_node) then
|
||||
local use_proxy = preproxy_node and node[rule_name .. "_proxy_tag"] == preproxy_rule_name and _node_id ~= preproxy_node_id
|
||||
if use_proxy and proxy_balancerTag then
|
||||
for _, blc_node_id in ipairs(preproxy_node.balancing_node) do
|
||||
if _node_id == blc_node_id then
|
||||
use_proxy = false
|
||||
break
|
||||
end
|
||||
end
|
||||
end
|
||||
local use_proxy = preproxy_tag and node[rule_name .. "_proxy_tag"] == preproxy_rule_name and _node_id ~= preproxy_node_id
|
||||
if use_proxy and preproxy_balancer_tag and preproxy_nodes[_node_id] then use_proxy = false end
|
||||
local copied_outbound
|
||||
for index, value in ipairs(outbounds) do
|
||||
if value["_id"] == _node_id and value["_flag_proxy_tag"] == preproxy_tag then
|
||||
if value["_id"] == _node_id and value["_flag_proxy_tag"] == (use_proxy and preproxy_tag or nil) then
|
||||
copied_outbound = api.clone(value)
|
||||
break
|
||||
end
|
||||
@ -851,7 +920,7 @@ function gen_config(var)
|
||||
if copied_outbound then
|
||||
copied_outbound.tag = rule_name .. ":" .. _node.remarks
|
||||
table.insert(outbounds, copied_outbound)
|
||||
rule_outboundTag = rule_name
|
||||
return copied_outbound.tag, nil
|
||||
else
|
||||
if use_proxy and (_node.type ~= "Xray" or _node.flow == "xtls-rprx-vision") then
|
||||
new_port = get_new_port()
|
||||
@ -869,8 +938,8 @@ function gen_config(var)
|
||||
_node.port = new_port
|
||||
table.insert(rules, 1, {
|
||||
inboundTag = {"proxy_" .. rule_name},
|
||||
outboundTag = proxy_outboundTag,
|
||||
balancerTag = proxy_balancerTag
|
||||
outboundTag = not preproxy_balancer_tag and preproxy_tag or nil,
|
||||
balancerTag = preproxy_balancer_tag
|
||||
})
|
||||
end
|
||||
local proxy_table = {
|
||||
@ -885,33 +954,22 @@ function gen_config(var)
|
||||
end
|
||||
end
|
||||
local outbound = gen_outbound(flag, _node, rule_name, proxy_table)
|
||||
local outbound_tag
|
||||
if outbound then
|
||||
outbound.tag = outbound.tag .. ":" .. _node.remarks
|
||||
rule_outboundTag = set_outbound_detour(_node, outbound, outbounds, rule_name)
|
||||
outbound_tag = set_outbound_detour(_node, outbound, outbounds, rule_name)
|
||||
if rule_name == "default" then
|
||||
table.insert(outbounds, 1, outbound)
|
||||
else
|
||||
table.insert(outbounds, outbound)
|
||||
end
|
||||
end
|
||||
return outbound_tag, nil
|
||||
end
|
||||
elseif _node.protocol == "_balancing" then
|
||||
local is_new_balancer = true
|
||||
rule_balancerTag = get_balancer_tag(_node_id)
|
||||
for _, v in ipairs(balancers) do
|
||||
if v.tag == rule_balancerTag then
|
||||
is_new_balancer = false
|
||||
gen_loopback(rule_name, _node_id)
|
||||
break
|
||||
end
|
||||
end
|
||||
if is_new_balancer then
|
||||
local valid = gen_balancer(_node, rule_name)
|
||||
if not valid then
|
||||
rule_balancerTag = nil
|
||||
end
|
||||
end
|
||||
return nil, gen_balancer(_node, rule_name)
|
||||
elseif _node.protocol == "_iface" then
|
||||
local outbound_tag
|
||||
if _node.iface then
|
||||
local outbound = {
|
||||
protocol = "freedom",
|
||||
@ -923,26 +981,40 @@ function gen_config(var)
|
||||
}
|
||||
}
|
||||
}
|
||||
outbound_tag = outbound.tag
|
||||
table.insert(outbounds, outbound)
|
||||
rule_outboundTag = rule_name
|
||||
sys.call("touch /tmp/etc/passwall2/iface/" .. _node.iface)
|
||||
end
|
||||
return outbound_tag, nil
|
||||
end
|
||||
end
|
||||
return rule_outboundTag, rule_balancerTag
|
||||
end
|
||||
|
||||
if preproxy_node then
|
||||
proxy_outboundTag, proxy_balancerTag = gen_shunt_node(preproxy_rule_name, preproxy_node_id)
|
||||
if not proxy_outboundTag and not proxy_balancerTag then
|
||||
preproxy_node = nil
|
||||
if preproxy_tag and preproxy_node_id then
|
||||
preproxy_outbound_tag, preproxy_balancer_tag = gen_shunt_node(preproxy_rule_name, preproxy_node_id)
|
||||
if preproxy_balancer_tag then
|
||||
local _node_id = preproxy_node_id
|
||||
preproxy_nodes = {}
|
||||
while _node_id do
|
||||
_node = uci:get_all(appname, _node_id)
|
||||
if not _node then break end
|
||||
if _node.protocol ~= "_balancing" then
|
||||
preproxy_nodes[_node_id] = true
|
||||
break
|
||||
end
|
||||
local _blc_nodes = _node.balancing_node
|
||||
for i = 1, #_blc_nodes do preproxy_nodes[_blc_nodes[i]] = true end
|
||||
_node_id = _node.fallback_node
|
||||
end
|
||||
elseif preproxy_outbound_tag then
|
||||
preproxy_tag = preproxy_outbound_tag
|
||||
end
|
||||
end
|
||||
--default_node
|
||||
local default_node_id = node.default_node or "_direct"
|
||||
local default_outboundTag, default_balancerTag = gen_shunt_node("default", default_node_id)
|
||||
COMMON.default_outbound_tag = default_outbound_tag
|
||||
COMMON.default_balancer_tag = default_balancer_tag
|
||||
COMMON.default_outbound_tag = default_outboundTag
|
||||
COMMON.default_balancer_tag = default_balancerTag
|
||||
--shunt rule
|
||||
uci:foreach(appname, "shunt_rules", function(e)
|
||||
local outboundTag, balancerTag = gen_shunt_node(e[".name"])
|
||||
@ -1053,15 +1125,15 @@ function gen_config(var)
|
||||
}
|
||||
elseif node.protocol == "_balancing" then
|
||||
if node.balancing_node then
|
||||
local valid = gen_balancer(node)
|
||||
if valid then
|
||||
table.insert(rules, { network = "tcp,udp", balancerTag = get_balancer_tag(node_id) })
|
||||
local balancer_tag = gen_balancer(node)
|
||||
if balancer_tag then
|
||||
table.insert(rules, { network = "tcp,udp", balancerTag = balancer_tag })
|
||||
end
|
||||
routing = {
|
||||
balancers = balancers,
|
||||
rules = rules
|
||||
}
|
||||
COMMON.default_balancer_tag = get_balancer_tag(node_id)
|
||||
COMMON.default_balancer_tag = balancer_tag
|
||||
end
|
||||
elseif node.protocol == "_iface" then
|
||||
if node.iface then
|
||||
@ -1358,7 +1430,7 @@ function gen_config(var)
|
||||
|
||||
local default_rule_index = #routing.rules > 0 and #routing.rules or 1
|
||||
for index, value in ipairs(routing.rules) do
|
||||
if value["_flag"] == "default" then
|
||||
if value.ruleTag == "default" then
|
||||
default_rule_index = index
|
||||
break
|
||||
end
|
||||
@ -1461,7 +1533,7 @@ function gen_config(var)
|
||||
})
|
||||
end
|
||||
|
||||
table.insert(outbounds, {
|
||||
local direct_outbound = {
|
||||
protocol = "freedom",
|
||||
tag = "direct",
|
||||
settings = {
|
||||
@ -1472,11 +1544,23 @@ function gen_config(var)
|
||||
mark = 255
|
||||
}
|
||||
}
|
||||
})
|
||||
table.insert(outbounds, {
|
||||
}
|
||||
if COMMON.default_outbound_tag == "direct" then
|
||||
table.insert(outbounds, 1, direct_outbound)
|
||||
else
|
||||
table.insert(outbounds, direct_outbound)
|
||||
end
|
||||
|
||||
local blackhole_outbound = {
|
||||
protocol = "blackhole",
|
||||
tag = "blackhole"
|
||||
})
|
||||
}
|
||||
if COMMON.default_outbound_tag == "blackhole" then
|
||||
table.insert(outbounds, 1, blackhole_outbound)
|
||||
else
|
||||
table.insert(outbounds, blackhole_outbound)
|
||||
end
|
||||
|
||||
for index, value in ipairs(config.outbounds) do
|
||||
for k, v in pairs(config.outbounds[index]) do
|
||||
if k:find("_") == 1 then
|
||||
|
@ -368,6 +368,10 @@ local api = require "luci.passwall2.api"
|
||||
v_transport = "splithttp";
|
||||
params += opt.query("host", dom_prefix + "splithttp_host");
|
||||
params += opt.query("path", dom_prefix + "splithttp_path");
|
||||
} else if (v_transport === "xhttp") {
|
||||
v_transport = "xhttp";
|
||||
params += opt.query("host", dom_prefix + "xhttp_host");
|
||||
params += opt.query("path", dom_prefix + "xhttp_path");
|
||||
}
|
||||
params += "&type=" + v_transport;
|
||||
|
||||
@ -1135,6 +1139,9 @@ local api = require "luci.passwall2.api"
|
||||
} else if (queryParam.type === "splithttp") {
|
||||
opt.set(dom_prefix + 'splithttp_host', queryParam.host || "");
|
||||
opt.set(dom_prefix + 'splithttp_path', queryParam.path || "");
|
||||
} else if (queryParam.type === "xhttp") {
|
||||
opt.set(dom_prefix + 'xhttp_host', queryParam.host || "");
|
||||
opt.set(dom_prefix + 'xhttp_path', queryParam.path || "");
|
||||
}
|
||||
|
||||
if (m.hash) {
|
||||
|
@ -1378,6 +1378,30 @@ msgstr "客户端文件不适合当前设备。"
|
||||
msgid "Can't move new file to path: %s"
|
||||
msgstr "无法移动新文件到:%s"
|
||||
|
||||
msgid "XHTTP download splitting"
|
||||
msgstr "XHTTP 下行分离"
|
||||
|
||||
msgid "Must be the same as upload path."
|
||||
msgstr "必须与上行 path 相同。"
|
||||
|
||||
msgid "Enable XHTTP XMUX. It's not recommended to enable Mux.Cool at the same time."
|
||||
msgstr "启用 XHTTP XMUX。不建议与 Mux.Cool 同时启用。"
|
||||
|
||||
msgid "XMUX Max Concurrency"
|
||||
msgstr "XMUX 连接最大复用流数"
|
||||
|
||||
msgid "XMUX Max Connections"
|
||||
msgstr "XMUX 最大连接数"
|
||||
|
||||
msgid "XMUX Connection Max Reuse Times"
|
||||
msgstr "XMUX 连接最多复用次数"
|
||||
|
||||
msgid "XMUX Connection Max Lifetime (ms)"
|
||||
msgstr "XMUX 连接最大存活时间(ms)"
|
||||
|
||||
msgid "Enable Mux.Cool"
|
||||
msgstr "启用 Mux.Cool"
|
||||
|
||||
msgid "Mux concurrency"
|
||||
msgstr "最大并发连接数"
|
||||
|
||||
|
@ -223,10 +223,10 @@ load_acl() {
|
||||
}
|
||||
|
||||
_acl_list=${TMP_ACL_PATH}/${sid}/rule_list
|
||||
[ $use_interface = "1" ] && _acl_list=${TMP_ACL_PATH}/${sid}/interface_list
|
||||
[ "$use_interface" = "1" ] && _acl_list=${TMP_ACL_PATH}/${sid}/interface_list
|
||||
|
||||
for i in $(cat $_acl_list); do
|
||||
if [ $use_interface = "0" ]; then
|
||||
if [ "$use_interface" = "0" ]; then
|
||||
if [ -n "$(echo ${i} | grep '^iprange:')" ]; then
|
||||
_iprange=$(echo ${i} | sed 's#iprange:##g')
|
||||
_ipt_source=$(factor ${_iprange} "-m iprange --src-range")
|
||||
|
@ -277,10 +277,10 @@ load_acl() {
|
||||
}
|
||||
|
||||
_acl_list=${TMP_ACL_PATH}/${sid}/rule_list
|
||||
[ $use_interface = "1" ] && _acl_list=${TMP_ACL_PATH}/${sid}/interface_list
|
||||
[ "$use_interface" = "1" ] && _acl_list=${TMP_ACL_PATH}/${sid}/interface_list
|
||||
|
||||
for i in $(cat $_acl_list); do
|
||||
if [ $use_interface = "0" ]; then
|
||||
if [ "$use_interface" = "0" ]; then
|
||||
if [ -n "$(echo ${i} | grep '^iprange:')" ]; then
|
||||
_iprange=$(echo ${i} | sed 's#iprange:##g')
|
||||
_ipt_source=$(factor ${_iprange} "ip saddr")
|
||||
|
Loading…
Reference in New Issue
Block a user