Skip to content

Commit

Permalink
luci: Xray outbound support network interface
Browse files Browse the repository at this point in the history
  • Loading branch information
xiaorouji committed Feb 6, 2023
1 parent 9606044 commit 959758b
Show file tree
Hide file tree
Showing 8 changed files with 74 additions and 17 deletions.
6 changes: 3 additions & 3 deletions luci-app-passwall/luasrc/model/cbi/passwall/api/api.lua
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ function strToTable(str)
end

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
end
return true
Expand Down Expand Up @@ -220,7 +220,7 @@ function get_valid_nodes()
uci:foreach(appname, "nodes", function(e)
e.id = e[".name"]
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["node_type"] = "special"
nodes[#nodes + 1] = e
Expand Down Expand Up @@ -257,7 +257,7 @@ end
function get_full_node_remarks(n)
local remarks = ""
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}
else
local type2 = n.type
Expand Down
17 changes: 16 additions & 1 deletion luci-app-passwall/luasrc/model/cbi/passwall/api/gen_v2ray.lua
Original file line number Diff line number Diff line change
Expand Up @@ -526,7 +526,22 @@ if node_id then
}
end
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
routing = {
domainStrategy = "AsIs",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -123,9 +123,14 @@ protocol:value("trojan", translate("Trojan"))
protocol:value("wireguard", translate("WireGuard"))
protocol:value("_balancing", translate("Balancing"))
protocol:value("_shunt", translate("Shunt"))
protocol:value("_iface", translate("Custom Interface") .. " (Only Support Xray)")
protocol:depends("type", "V2ray")
protocol:depends("type", "Xray")

iface = s:option(Value, "iface", translate("Interface"))
iface.default = "eth1"
iface:depends("protocol", "_iface")

local nodes_table = {}
for k, e in ipairs(api.get_valid_nodes()) do
if e.node_type == "normal" then
Expand Down
35 changes: 24 additions & 11 deletions luci-app-passwall/luasrc/model/cbi/passwall/server/api/v2ray.lua
Original file line number Diff line number Diff line change
Expand Up @@ -117,19 +117,32 @@ function gen_config(user)
}

if user.outbound_node and user.outbound_node ~= "nil" then
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,
local outbound = nil
if user.outbound_node == "_iface" and user.outbound_node_iface then
outbound = {
protocol = "freedom",
tag = "outbound",
streamSettings = {
sockopt = {
interface = user.outbound_node_iface
}
}
}
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
local outbound = require("luci.model.cbi.passwall.api.gen_v2ray").gen_outbound(outbound_node_t, "outbound")
if outbound then
table.insert(outbounds, 1, outbound)
end
Expand Down
5 changes: 5 additions & 0 deletions luci-app-passwall/luasrc/model/cbi/passwall/server/user.lua
Original file line number Diff line number Diff line change
Expand Up @@ -685,6 +685,7 @@ outbound_node = s:option(ListValue, "outbound_node", translate("outbound node"))
outbound_node:value("nil", translate("Close"))
outbound_node:value("_socks", translate("Custom Socks"))
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
outbound_node.default = "nil"
outbound_node:depends("type", "V2ray")
Expand All @@ -708,6 +709,10 @@ outbound_node_password.password = true
outbound_node_password:depends("outbound_node", "_socks")
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.default = "1"
log.rmempty = false
Expand Down
6 changes: 6 additions & 0 deletions luci-app-passwall/po/zh-cn/passwall.po
Original file line number Diff line number Diff line change
Expand Up @@ -1162,6 +1162,12 @@ msgstr "自定义 Socks"
msgid "Custom HTTP"
msgstr "自定义 HTTP"

msgid "Custom Interface"
msgstr "自定义接口"

msgid "Interface"
msgstr "接口"

msgid "Bind Local"
msgstr "本机监听"

Expand Down
12 changes: 10 additions & 2 deletions luci-app-passwall/root/usr/share/passwall/app.sh
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ DNS_PORT=15353
TUN_DNS="127.0.0.1#${DNS_PORT}"
LOCAL_DNS=119.29.29.29
DEFAULT_DNS=
IFACES=
NO_PROXY=0
PROXY_IPV6=0
PROXY_IPV6_UDP=0
Expand Down Expand Up @@ -360,6 +361,10 @@ run_v2ray() {
_extra_param="${_extra_param} -loglevel $loglevel"
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"
local protocol=$(config_n_get $node protocol)
[ "$protocol" == "_iface" ] && {
IFACES="$IFACES $(config_n_get $node iface)"
}
}

run_dns2socks() {
Expand Down Expand Up @@ -412,8 +417,11 @@ run_socks() {
error_msg="某种原因,此 Socks 服务的相关配置已失联,启动中止!"
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
unset error_msg
if [ "$type" == "v2ray" ] || [ "$type" == "xray" ]; then
local protocol=$(config_n_get $node protocol)
if [ "$protocol" == "_balancing" ] || [ "$protocol" == "_shunt" ] || [ "$protocol" == "_iface" ]; then
unset error_msg
fi
fi

[ -n "${error_msg}" ] && {
Expand Down
5 changes: 5 additions & 0 deletions luci-app-passwall/root/usr/share/passwall/iptables.sh
Original file line number Diff line number Diff line change
Expand Up @@ -1222,6 +1222,11 @@ add_firewall_rule() {
load_acl

# 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}" ] && {
bridge_nf_ipt=$(sysctl -e -n net.bridge.bridge-nf-call-iptables)
Expand Down

0 comments on commit 959758b

Please sign in to comment.