luci: Xray outbound support network interface

This commit is contained in:
xiaorouji 2023-02-06 18:57:37 +08:00 committed by sbwml
parent 2a0b8a0b49
commit 08b4cda31b
8 changed files with 74 additions and 17 deletions

View File

@ -110,7 +110,7 @@ function strToTable(str)
end end
function is_normal_node(e) function is_normal_node(e)
if e and e.type and e.protocol and (e.protocol == "_balancing" or e.protocol == "_shunt") then if e and e.type and e.protocol and (e.protocol == "_balancing" or e.protocol == "_shunt" or e.protocol == "_iface") then
return false return false
end end
return true return true
@ -220,7 +220,7 @@ function get_valid_nodes()
uci:foreach(appname, "nodes", function(e) uci:foreach(appname, "nodes", function(e)
e.id = e[".name"] e.id = e[".name"]
if e.type and e.remarks then if e.type and e.remarks then
if e.protocol and (e.protocol == "_balancing" or e.protocol == "_shunt") then if e.protocol and (e.protocol == "_balancing" or e.protocol == "_shunt" or e.protocol == "_iface") then
e["remark"] = "%s[%s] " % {i18n.translatef(e.type .. e.protocol), e.remarks} e["remark"] = "%s[%s] " % {i18n.translatef(e.type .. e.protocol), e.remarks}
e["node_type"] = "special" e["node_type"] = "special"
nodes[#nodes + 1] = e nodes[#nodes + 1] = e
@ -257,7 +257,7 @@ end
function get_full_node_remarks(n) function get_full_node_remarks(n)
local remarks = "" local remarks = ""
if n then if n then
if n.protocol and (n.protocol == "_balancing" or n.protocol == "_shunt") then if n.protocol and (n.protocol == "_balancing" or n.protocol == "_shunt" or n.protocol == "_iface") then
remarks = "%s[%s] " % {i18n.translatef(n.type .. n.protocol), n.remarks} remarks = "%s[%s] " % {i18n.translatef(n.type .. n.protocol), n.remarks}
else else
local type2 = n.type local type2 = n.type

View File

@ -526,7 +526,22 @@ if node_id then
} }
end end
else else
local outbound = gen_outbound(node) local outbound = nil
if node.protocol == "_iface" then
if node.iface then
outbound = {
protocol = "freedom",
tag = "outbound",
streamSettings = {
sockopt = {
interface = node.iface
}
}
}
end
else
outbound = gen_outbound(node)
end
if outbound then table.insert(outbounds, outbound) end if outbound then table.insert(outbounds, outbound) end
routing = { routing = {
domainStrategy = "AsIs", domainStrategy = "AsIs",

View File

@ -123,9 +123,14 @@ protocol:value("trojan", translate("Trojan"))
protocol:value("wireguard", translate("WireGuard")) protocol:value("wireguard", translate("WireGuard"))
protocol:value("_balancing", translate("Balancing")) protocol:value("_balancing", translate("Balancing"))
protocol:value("_shunt", translate("Shunt")) protocol:value("_shunt", translate("Shunt"))
protocol:value("_iface", translate("Custom Interface") .. " (Only Support Xray)")
protocol:depends("type", "V2ray") protocol:depends("type", "V2ray")
protocol:depends("type", "Xray") protocol:depends("type", "Xray")
iface = s:option(Value, "iface", translate("Interface"))
iface.default = "eth1"
iface:depends("protocol", "_iface")
local nodes_table = {} local nodes_table = {}
for k, e in ipairs(api.get_valid_nodes()) do for k, e in ipairs(api.get_valid_nodes()) do
if e.node_type == "normal" then if e.node_type == "normal" then

View File

@ -117,19 +117,32 @@ function gen_config(user)
} }
if user.outbound_node and user.outbound_node ~= "nil" then if user.outbound_node and user.outbound_node ~= "nil" then
local outbound_node_t = uci:get_all("passwall", user.outbound_node) local outbound = nil
if user.outbound_node == "_socks" or user.outbound_node == "_http" then if user.outbound_node == "_iface" and user.outbound_node_iface then
outbound_node_t = { outbound = {
type = user.type, protocol = "freedom",
protocol = user.outbound_node:gsub("_", ""), tag = "outbound",
transport = "tcp", streamSettings = {
address = user.outbound_node_address, sockopt = {
port = user.outbound_node_port, interface = user.outbound_node_iface
username = (user.outbound_node_username and user.outbound_node_username ~= "") and user.outbound_node_username or nil, }
password = (user.outbound_node_password and user.outbound_node_password ~= "") and user.outbound_node_password or nil, }
} }
else
local outbound_node_t = uci:get_all("passwall", user.outbound_node)
if user.outbound_node == "_socks" or user.outbound_node == "_http" then
outbound_node_t = {
type = user.type,
protocol = user.outbound_node:gsub("_", ""),
transport = "tcp",
address = user.outbound_node_address,
port = user.outbound_node_port,
username = (user.outbound_node_username and user.outbound_node_username ~= "") and user.outbound_node_username or nil,
password = (user.outbound_node_password and user.outbound_node_password ~= "") and user.outbound_node_password or nil,
}
end
outbound = require("luci.model.cbi.passwall.api.gen_v2ray").gen_outbound(outbound_node_t, "outbound")
end end
local outbound = require("luci.model.cbi.passwall.api.gen_v2ray").gen_outbound(outbound_node_t, "outbound")
if outbound then if outbound then
table.insert(outbounds, 1, outbound) table.insert(outbounds, 1, outbound)
end end

View File

@ -685,6 +685,7 @@ outbound_node = s:option(ListValue, "outbound_node", translate("outbound node"))
outbound_node:value("nil", translate("Close")) outbound_node:value("nil", translate("Close"))
outbound_node:value("_socks", translate("Custom Socks")) outbound_node:value("_socks", translate("Custom Socks"))
outbound_node:value("_http", translate("Custom HTTP")) outbound_node:value("_http", translate("Custom HTTP"))
outbound_node:value("_iface", translate("Custom Interface") .. " (Only Support Xray)")
for k, v in pairs(nodes_table) do outbound_node:value(v.id, v.remarks) end for k, v in pairs(nodes_table) do outbound_node:value(v.id, v.remarks) end
outbound_node.default = "nil" outbound_node.default = "nil"
outbound_node:depends("type", "V2ray") outbound_node:depends("type", "V2ray")
@ -708,6 +709,10 @@ outbound_node_password.password = true
outbound_node_password:depends("outbound_node", "_socks") outbound_node_password:depends("outbound_node", "_socks")
outbound_node_password:depends("outbound_node", "_http") outbound_node_password:depends("outbound_node", "_http")
outbound_node_iface = s:option(Value, "outbound_node_iface", translate("Interface"))
outbound_node_iface.default = "eth1"
outbound_node_iface:depends("outbound_node", "_iface")
log = s:option(Flag, "log", translate("Log")) log = s:option(Flag, "log", translate("Log"))
log.default = "1" log.default = "1"
log.rmempty = false log.rmempty = false

View File

@ -1162,6 +1162,12 @@ msgstr "自定义 Socks"
msgid "Custom HTTP" msgid "Custom HTTP"
msgstr "自定义 HTTP" msgstr "自定义 HTTP"
msgid "Custom Interface"
msgstr "自定义接口"
msgid "Interface"
msgstr "接口"
msgid "Bind Local" msgid "Bind Local"
msgstr "本机监听" msgstr "本机监听"

View File

@ -24,6 +24,7 @@ DNS_PORT=15353
TUN_DNS="127.0.0.1#${DNS_PORT}" TUN_DNS="127.0.0.1#${DNS_PORT}"
LOCAL_DNS=119.29.29.29 LOCAL_DNS=119.29.29.29
DEFAULT_DNS= DEFAULT_DNS=
IFACES=
NO_PROXY=0 NO_PROXY=0
PROXY_IPV6=0 PROXY_IPV6=0
PROXY_IPV6_UDP=0 PROXY_IPV6_UDP=0
@ -360,6 +361,10 @@ run_v2ray() {
_extra_param="${_extra_param} -loglevel $loglevel" _extra_param="${_extra_param} -loglevel $loglevel"
lua $API_GEN_V2RAY ${_extra_param} > $config_file lua $API_GEN_V2RAY ${_extra_param} > $config_file
ln_run "$(first_type $(config_t_get global_app ${type}_file) ${type})" ${type} $log_file run -c "$config_file" ln_run "$(first_type $(config_t_get global_app ${type}_file) ${type})" ${type} $log_file run -c "$config_file"
local protocol=$(config_n_get $node protocol)
[ "$protocol" == "_iface" ] && {
IFACES="$IFACES $(config_n_get $node iface)"
}
} }
run_dns2socks() { run_dns2socks() {
@ -412,8 +417,11 @@ run_socks() {
error_msg="某种原因,此 Socks 服务的相关配置已失联,启动中止!" error_msg="某种原因,此 Socks 服务的相关配置已失联,启动中止!"
fi fi
if ([ "$type" == "v2ray" ] || [ "$type" == "xray" ]) && ([ -n "$(config_n_get $node balancing_node)" ] || [ "$(config_n_get $node default_node)" != "_direct" -a "$(config_n_get $node default_node)" != "_blackhole" ]); then if [ "$type" == "v2ray" ] || [ "$type" == "xray" ]; then
unset error_msg local protocol=$(config_n_get $node protocol)
if [ "$protocol" == "_balancing" ] || [ "$protocol" == "_shunt" ] || [ "$protocol" == "_iface" ]; then
unset error_msg
fi
fi fi
[ -n "${error_msg}" ] && { [ -n "${error_msg}" ] && {

View File

@ -1222,6 +1222,11 @@ add_firewall_rule() {
load_acl load_acl
# dns_hijack "force" # dns_hijack "force"
for iface in $IFACES; do
$ipt_n -I PSW_OUTPUT -o $iface -j RETURN
$ipt_m -I PSW_OUTPUT -o $iface -j RETURN
done
[ -n "${is_tproxy}" -o -n "${udp_flag}" ] && { [ -n "${is_tproxy}" -o -n "${udp_flag}" ] && {
bridge_nf_ipt=$(sysctl -e -n net.bridge.bridge-nf-call-iptables) bridge_nf_ipt=$(sysctl -e -n net.bridge.bridge-nf-call-iptables)