update-03.11

This commit is contained in:
github-actions[bot]
2022-03-11 18:29:27 +08:00
parent 36163fce15
commit 5b37789a46
96 changed files with 3445 additions and 98388 deletions

View File

@@ -1,81 +0,0 @@
local api = require "luci.model.cbi.passwall.api.api"
local uci = api.uci
local json = api.jsonc
local var = api.get_args(arg)
local node_section = var["-node"]
if not node_section then
print("-node 不能为空")
return
end
local run_type = var["-run_type"]
local local_addr = var["-local_addr"]
local local_port = var["-local_port"]
local server_host = var["-server_host"]
local server_port = var["-server_port"]
local loglevel = var["-loglevel"] or 2
local node = uci:get_all("passwall", node_section)
local cipher = "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:AES128-SHA:AES256-SHA:DES-CBC3-SHA"
local cipher13 = "TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384"
local trojan = {
run_type = run_type,
local_addr = local_addr,
local_port = tonumber(local_port),
remote_addr = server_host or node.address,
remote_port = tonumber(server_port) or tonumber(node.port),
password = {node.password},
log_level = tonumber(loglevel),
ssl = {
verify = (node.tls_allowInsecure ~= "1") and true or false,
verify_hostname = true,
cert = nil,
cipher = cipher,
cipher_tls13 = cipher13,
sni = node.tls_serverName or node.address,
alpn = {"h2", "http/1.1"},
reuse_session = true,
session_ticket = (node.tls_sessionTicket and node.tls_sessionTicket == "1") and true or false,
curves = ""
},
udp_timeout = 60,
tcp = {
use_tproxy = (node.type == "Trojan-Plus" and var["-use_tproxy"]) and true or nil,
no_delay = true,
keep_alive = true,
reuse_port = true,
fast_open = (node.tcp_fast_open == "true") and true or false,
fast_open_qlen = 20
}
}
if node.type == "Trojan-Go" then
trojan.ssl.cipher = nil
trojan.ssl.cipher_tls13 = nil
trojan.ssl.fingerprint = (node.fingerprint ~= "disable") and node.fingerprint or ""
trojan.ssl.alpn = (node.trojan_transport == 'ws') and {} or {"h2", "http/1.1"}
if node.tls ~= "1" and node.trojan_transport == "original" then trojan.ssl = nil end
trojan.transport_plugin = ((not node.tls or node.tls ~= "1") and node.trojan_transport == "original") and {
enabled = node.plugin_type ~= nil,
type = node.plugin_type or "plaintext",
command = node.plugin_type ~= "plaintext" and node.plugin_cmd or nil,
option = node.plugin_type ~= "plaintext" and node.plugin_option or nil,
arg = node.plugin_type ~= "plaintext" and { node.plugin_arg } or nil,
env = {}
} or nil
trojan.websocket = (node.trojan_transport == 'ws') and {
enabled = true,
path = node.ws_path or "/",
host = node.ws_host or (node.tls_serverName or node.address)
} or nil
trojan.shadowsocks = (node.ss_aead == "1") and {
enabled = true,
method = node.ss_aead_method or "aes_128_gcm",
password = node.ss_aead_pwd or ""
} or nil
trojan.mux = (node.smux == "1") and {
enabled = true,
concurrency = tonumber(node.mux_concurrency),
idle_timeout = tonumber(node.smux_idle_timeout)
} or nil
end
print(json.stringify(trojan, 1))

View File

@@ -1,189 +0,0 @@
module("luci.model.cbi.passwall.api.kcptun", package.seeall)
local api = require "luci.model.cbi.passwall.api.api"
local fs = api.fs
local sys = api.sys
local util = api.util
local i18n = api.i18n
local pre_release_url = "https://api.github.com/repos/xtaci/kcptun/releases?per_page=1"
local release_url = "https://api.github.com/repos/xtaci/kcptun/releases/latest"
local api_url = release_url
local app_path = api.get_kcptun_path() or ""
function check_path()
if app_path == "" then
return {
code = 1,
error = i18n.translatef("You did not fill in the %s path. Please save and apply then update manually.", "Kcptun")
}
end
return {
code = 0
}
end
function to_check(arch)
local result = check_path()
if result.code ~= 0 then
return result
end
if not arch or arch == "" then arch = api.auto_get_arch() end
local file_tree, sub_version = api.get_file_info(arch)
if file_tree == "" then
return {
code = 1,
error = i18n.translate("Can't determine ARCH, or ARCH not supported.")
}
end
return api.common_to_check(api_url, api.get_kcptun_version(), "linux%-" .. file_tree .. sub_version)
end
function to_download(url, size)
local result = check_path()
if result.code ~= 0 then
return result
end
if not url or url == "" then
return {code = 1, error = i18n.translate("Download url is required.")}
end
sys.call("/bin/rm -f /tmp/kcptun_download.*")
local tmp_file = util.trim(util.exec("mktemp -u -t kcptun_download.XXXXXX"))
if size then
local kb1 = api.get_free_space("/tmp")
if tonumber(size) > tonumber(kb1) then
return {code = 1, error = i18n.translatef("%s not enough space.", "/tmp")}
end
end
result = api.exec(api.curl, {api._unpack(api.curl_args), "-o", tmp_file, url}, nil, api.command_timeout) == 0
if not result then
api.exec("/bin/rm", {"-f", tmp_file})
return {
code = 1,
error = i18n.translatef("File download failed or timed out: %s", url)
}
end
return {code = 0, file = tmp_file}
end
function to_extract(file, subfix)
local result = check_path()
if result.code ~= 0 then
return result
end
if not file or file == "" or not fs.access(file) then
return {code = 1, error = i18n.translate("File path required.")}
end
sys.call("/bin/rm -rf /tmp/kcptun_extract.*")
local new_file_size = api.get_file_space(file)
local tmp_free_size = api.get_free_space("/tmp")
if tmp_free_size <= 0 or tmp_free_size <= new_file_size then
return {code = 1, error = i18n.translatef("%s not enough space.", "/tmp")}
end
local tmp_dir = util.trim(util.exec("mktemp -d -t kcptun_extract.XXXXXX"))
local output = {}
api.exec("/bin/tar", {"-C", tmp_dir, "-zxvf", file},
function(chunk) output[#output + 1] = chunk end)
local files = util.split(table.concat(output))
api.exec("/bin/rm", {"-f", file})
local new_file = nil
for _, f in pairs(files) do
if f:match("client_linux_%s" % subfix) then
new_file = tmp_dir .. "/" .. util.trim(f)
break
end
end
if not new_file then
for _, f in pairs(files) do
if f:match("client_") then
new_file = tmp_dir .. "/" .. util.trim(f)
break
end
end
end
if not new_file then
api.exec("/bin/rm", {"-rf", tmp_dir})
return {
code = 1,
error = i18n.translatef("Can't find client in file: %s", file)
}
end
return {code = 0, file = new_file}
end
function to_move(file)
local result = check_path()
if result.code ~= 0 then
return result
end
if not file or file == "" or not fs.access(file) then
sys.call("/bin/rm -rf /tmp/kcptun_extract.*")
return {code = 1, error = i18n.translate("Client file is required.")}
end
local new_version = api.get_kcptun_version(file)
if new_version == "" then
sys.call("/bin/rm -rf /tmp/kcptun_extract.*")
return {
code = 1,
error = i18n.translate("The client file is not suitable for current device.")
}
end
local flag = sys.call('pgrep -af "passwall/.*kcptun" >/dev/null')
if flag == 0 then
sys.call("/etc/init.d/passwall stop")
end
local old_app_size = 0
if fs.access(app_path) then
old_app_size = api.get_file_space(app_path)
end
local new_app_size = api.get_file_space(file)
local final_dir = api.get_final_dir(app_path)
local final_dir_free_size = api.get_free_space(final_dir)
if final_dir_free_size > 0 then
final_dir_free_size = final_dir_free_size + old_app_size
if new_app_size > final_dir_free_size then
sys.call("/bin/rm -rf /tmp/kcptun_extract.*")
return {code = 1, error = i18n.translatef("%s not enough space.", final_dir)}
end
end
result = api.exec("/bin/mv", {"-f", file, app_path}, nil, api.command_timeout) == 0
sys.call("/bin/rm -rf /tmp/kcptun_extract.*")
if flag == 0 then
sys.call("/etc/init.d/passwall restart >/dev/null 2>&1 &")
end
if not result or not fs.access(app_path) then
return {
code = 1,
error = i18n.translatef("Can't move new file to path: %s", app_path)
}
end
return {code = 0}
end

View File

@@ -1,183 +0,0 @@
module("luci.model.cbi.passwall.api.trojan_go", package.seeall)
local api = require "luci.model.cbi.passwall.api.api"
local fs = api.fs
local sys = api.sys
local util = api.util
local i18n = api.i18n
local pre_release_url = "https://api.github.com/repos/p4gefau1t/trojan-go/releases?per_page=1"
local release_url = "https://api.github.com/repos/p4gefau1t/trojan-go/releases/latest"
local api_url = release_url
local app_path = api.get_trojan_go_path() or ""
function check_path()
if app_path == "" then
return {
code = 1,
error = i18n.translatef("You did not fill in the %s path. Please save and apply then update manually.", "Trojan-GO")
}
end
return {
code = 0
}
end
function to_check(arch)
local result = check_path()
if result.code ~= 0 then
return result
end
if not arch or arch == "" then arch = api.auto_get_arch() end
local file_tree, sub_version = api.get_file_info(arch)
if file_tree == "" then
return {
code = 1,
error = i18n.translate("Can't determine ARCH, or ARCH not supported.")
}
end
if file_tree == "mips" then file_tree = "mips%-hardfloat" end
if file_tree == "mipsle" then file_tree = "mipsle%-hardfloat" end
if file_tree == "arm64" then
file_tree = "armv8"
else
if sub_version and sub_version:match("^[5-8]$") then file_tree = file_tree .. "v" .. sub_version end
end
return api.common_to_check(api_url, api.get_trojan_go_version(), "linux%-" .. file_tree .. "%.zip")
end
function to_download(url, size)
local result = check_path()
if result.code ~= 0 then
return result
end
if not url or url == "" then
return {code = 1, error = i18n.translate("Download url is required.")}
end
sys.call("/bin/rm -f /tmp/trojan-go_download.*")
local tmp_file = util.trim(util.exec("mktemp -u -t trojan-go_download.XXXXXX"))
if size then
local kb1 = api.get_free_space("/tmp")
if tonumber(size) > tonumber(kb1) then
return {code = 1, error = i18n.translatef("%s not enough space.", "/tmp")}
end
end
result = api.exec(api.curl, {api._unpack(api.curl_args), "-o", tmp_file, url}, nil, api.command_timeout) == 0
if not result then
api.exec("/bin/rm", {"-f", tmp_file})
return {
code = 1,
error = i18n.translatef("File download failed or timed out: %s", url)
}
end
return {code = 0, file = tmp_file}
end
function to_extract(file, subfix)
local result = check_path()
if result.code ~= 0 then
return result
end
if not file or file == "" or not fs.access(file) then
return {code = 1, error = i18n.translate("File path required.")}
end
if sys.exec("echo -n $(opkg list-installed | grep -c unzip)") ~= "1" then
api.exec("/bin/rm", {"-f", file})
return {
code = 1,
error = i18n.translate("Not installed unzip, Can't unzip!")
}
end
sys.call("/bin/rm -rf /tmp/trojan-go_extract.*")
local new_file_size = api.get_file_space(file)
local tmp_free_size = api.get_free_space("/tmp")
if tmp_free_size <= 0 or tmp_free_size <= new_file_size then
return {code = 1, error = i18n.translatef("%s not enough space.", "/tmp")}
end
local tmp_dir = util.trim(util.exec("mktemp -d -t trojan-go_extract.XXXXXX"))
local output = {}
api.exec("/usr/bin/unzip", {"-o", file, "-d", tmp_dir},
function(chunk) output[#output + 1] = chunk end)
local files = util.split(table.concat(output))
api.exec("/bin/rm", {"-f", file})
return {code = 0, file = tmp_dir}
end
function to_move(file)
local result = check_path()
if result.code ~= 0 then
return result
end
if not file or file == "" then
sys.call("/bin/rm -rf /tmp/trojan-go_extract.*")
return {code = 1, error = i18n.translate("Client file is required.")}
end
local bin_path = file .. "/trojan-go"
local new_version = api.get_trojan_go_version(bin_path)
if new_version == "" then
sys.call("/bin/rm -rf /tmp/trojan-go_extract.*")
return {
code = 1,
error = i18n.translate("The client file is not suitable for current device.")
}
end
local flag = sys.call('pgrep -af "passwall/.*trojan-go" >/dev/null')
if flag == 0 then
sys.call("/etc/init.d/passwall stop")
end
local old_app_size = 0
if fs.access(app_path) then
old_app_size = api.get_file_space(app_path)
end
local new_app_size = api.get_file_space(bin_path)
local final_dir = api.get_final_dir(app_path)
local final_dir_free_size = api.get_free_space(final_dir)
if final_dir_free_size > 0 then
final_dir_free_size = final_dir_free_size + old_app_size
if new_app_size > final_dir_free_size then
sys.call("/bin/rm -rf /tmp/trojan-go_extract.*")
return {code = 1, error = i18n.translatef("%s not enough space.", final_dir)}
end
end
result = api.exec("/bin/mv", { "-f", bin_path, app_path }, nil, api.command_timeout) == 0
sys.call("/bin/rm -rf /tmp/trojan-go_extract.*")
if flag == 0 then
sys.call("/etc/init.d/passwall restart >/dev/null 2>&1 &")
end
if not result or not fs.access(app_path) then
return {
code = 1,
error = i18n.translatef("Can't move new file to path: %s", app_path)
}
end
return {code = 0}
end

View File

@@ -1,119 +0,0 @@
local api = require "luci.model.cbi.passwall.api.api"
local appname = api.appname
local sys = api.sys
local has_chnlist = api.fs.access("/usr/share/passwall/rules/chnlist")
m = Map(appname)
local global_proxy_mode = (m:get("@global[0]", "tcp_proxy_mode") or "") .. (m:get("@global[0]", "udp_proxy_mode") or "")
-- [[ ACLs Settings ]]--
s = m:section(TypedSection, "acl_rule", translate("ACLs"), "<font color='red'>" .. translate("ACLs is a tools which used to designate specific IP proxy mode.") .. "</font>")
s.template = "cbi/tblsection"
s.sortable = true
s.anonymous = true
s.addremove = true
s.extedit = api.url("acl_config", "%s")
function s.create(e, t)
t = TypedSection.create(e, t)
luci.http.redirect(e.extedit:format(t))
end
---- Enable
o = s:option(Flag, "enabled", translate("Enable"))
o.default = 1
o.rmempty = false
---- Remarks
o = s:option(Value, "remarks", translate("Remarks"))
o.rmempty = true
local mac_t = {}
sys.net.mac_hints(function(e, t)
mac_t[e] = {
ip = t,
mac = e
}
end)
o = s:option(DummyValue, "sources", translate("Source"))
o.rawhtml = true
o.cfgvalue = function(t, n)
local e = ''
local v = Value.cfgvalue(t, n) or ''
string.gsub(v, '[^' .. " " .. ']+', function(w)
local a = w
if mac_t[w] then
a = a .. ' (' .. mac_t[w].ip .. ')'
end
if #e > 0 then
e = e .. "<br />"
end
e = e .. a
end)
return e
end
---- TCP Proxy Mode
tcp_proxy_mode = s:option(ListValue, "tcp_proxy_mode", translatef("%s Proxy Mode", "TCP"))
tcp_proxy_mode.default = "default"
tcp_proxy_mode.rmempty = false
tcp_proxy_mode:value("default", translate("Default"))
tcp_proxy_mode:value("disable", translate("No Proxy"))
tcp_proxy_mode:value("global", translate("Global Proxy"))
if has_chnlist and global_proxy_mode:find("returnhome") then
tcp_proxy_mode:value("returnhome", translate("China List"))
else
tcp_proxy_mode:value("gfwlist", translate("GFW List"))
tcp_proxy_mode:value("chnroute", translate("Not China List"))
end
tcp_proxy_mode:value("direct/proxy", translate("Only use direct/proxy list"))
---- UDP Proxy Mode
udp_proxy_mode = s:option(ListValue, "udp_proxy_mode", translatef("%s Proxy Mode", "UDP"))
udp_proxy_mode.default = "default"
udp_proxy_mode.rmempty = false
udp_proxy_mode:value("default", translate("Default"))
udp_proxy_mode:value("disable", translate("No Proxy"))
udp_proxy_mode:value("global", translate("Global Proxy"))
if has_chnlist and global_proxy_mode:find("returnhome") then
udp_proxy_mode:value("returnhome", translate("China List"))
else
udp_proxy_mode:value("gfwlist", translate("GFW List"))
udp_proxy_mode:value("chnroute", translate("Not China List"))
end
udp_proxy_mode:value("direct/proxy", translate("Only use direct/proxy list"))
--[[
---- TCP No Redir Ports
o = s:option(Value, "tcp_no_redir_ports", translate("TCP No Redir Ports"))
o.default = "default"
o:value("disable", translate("No patterns are used"))
o:value("default", translate("Default"))
o:value("1:65535", translate("All"))
---- UDP No Redir Ports
o = s:option(Value, "udp_no_redir_ports", translate("UDP No Redir Ports"))
o.default = "default"
o:value("disable", translate("No patterns are used"))
o:value("default", translate("Default"))
o:value("1:65535", translate("All"))
---- TCP Redir Ports
o = s:option(Value, "tcp_redir_ports", translate("TCP Redir Ports"))
o.default = "default"
o:value("default", translate("Default"))
o:value("1:65535", translate("All"))
o:value("80,443", "80,443")
o:value("80:65535", "80 " .. translate("or more"))
o:value("1:443", "443 " .. translate("or less"))
---- UDP Redir Ports
o = s:option(Value, "udp_redir_ports", translate("UDP Redir Ports"))
o.default = "default"
o:value("default", translate("Default"))
o:value("1:65535", translate("All"))
o:value("53", "53")
]]--
return m

View File

@@ -1,456 +0,0 @@
local api = require "luci.model.cbi.passwall.api.api"
local appname = api.appname
local uci = api.uci
local datatypes = api.datatypes
local has_v2ray = api.is_finded("v2ray")
local has_xray = api.is_finded("xray")
local has_chnlist = api.fs.access("/usr/share/passwall/rules/chnlist")
m = Map(appname)
local nodes_table = {}
for k, e in ipairs(api.get_valid_nodes()) do
nodes_table[#nodes_table + 1] = e
end
local socks_table = {}
uci:foreach(appname, "socks", function(s)
if s.enabled == "1" and s.node then
local id, remarks
local same, i = s.node:match("^(tcp)")
if same then
remarks = translatef("Same as the tcp node")
else
for k, n in pairs(nodes_table) do
if (s.node == n.id) then
remarks = n["remark"]; break
end
end
end
id = "127.0.0.1" .. ":" .. s.port
socks_table[#socks_table + 1] = {
id = id,
remarks = id .. " - " .. (remarks or translate("Misconfigured"))
}
end
end)
local doh_validate = function(self, value, t)
if value ~= "" then
local flag = 0
local util = require "luci.util"
local val = util.split(value, ",")
local url = val[1]
val[1] = nil
for i = 1, #val do
local v = val[i]
if v then
if not datatypes.ipmask4(v) then
flag = 1
end
end
end
if flag == 0 then
return value
end
end
return nil, translate("DoH request address") .. " " .. translate("Format must be:") .. " URL,IP"
end
local redir_mode_validate = function(self, value, t)
local tcp_proxy_mode_v = tcp_proxy_mode:formvalue(t) or ""
local udp_proxy_mode_v = udp_proxy_mode:formvalue(t) or ""
local localhost_tcp_proxy_mode_v = localhost_tcp_proxy_mode:formvalue(t) or ""
local localhost_udp_proxy_mode_v = localhost_udp_proxy_mode:formvalue(t) or ""
local s = tcp_proxy_mode_v .. udp_proxy_mode_v .. localhost_tcp_proxy_mode_v .. localhost_udp_proxy_mode_v
if s:find("returnhome") then
if s:find("chnroute") or s:find("gfwlist") then
return nil, translate("China list or gfwlist cannot be used together with outside China list!")
end
end
return value
end
m:append(Template(appname .. "/global/status"))
s = m:section(TypedSection, "global")
s.anonymous = true
s.addremove = false
s:tab("Main", translate("Main"))
-- [[ Global Settings ]]--
o = s:taboption("Main", Flag, "enabled", translate("Main switch"))
o.rmempty = false
---- TCP Node
tcp_node = s:taboption("Main", ListValue, "tcp_node", "<a style='color: red'>" .. translate("TCP Node") .. "</a>")
tcp_node.description = ""
--tcp_node.description = translate("For proxy specific list.")
--tcp_node.description = o.description .. "<br />"
local current_node = luci.sys.exec(string.format("[ -f '/tmp/etc/%s/id/TCP' ] && echo -n $(cat /tmp/etc/%s/id/TCP)", appname, appname))
if current_node and current_node ~= "" and current_node ~= "nil" then
local n = uci:get_all(appname, current_node)
if n then
if tonumber(m:get("@auto_switch[0]", "enable") or 0) == 1 then
local remarks = api.get_full_node_remarks(n)
local url = api.url("node_config", current_node)
tcp_node.description = tcp_node.description .. translatef("Current node: %s", string.format('<a href="%s">%s</a>', url, remarks)) .. "<br />"
end
end
end
tcp_node:value("nil", translate("Close"))
-- 分流
if (has_v2ray or has_xray) and #nodes_table > 0 then
local normal_list = {}
local shunt_list = {}
for k, v in pairs(nodes_table) do
if v.node_type == "normal" then
normal_list[#normal_list + 1] = v
end
if v.protocol and v.protocol == "_shunt" then
shunt_list[#shunt_list + 1] = v
end
end
for k, v in pairs(shunt_list) do
uci:foreach(appname, "shunt_rules", function(e)
local id = e[".name"]
o = s:taboption("Main", ListValue, v.id .. "." .. id .. "_node", string.format('* <a href="%s" target="_blank">%s</a>', api.url("shunt_rules", id), translate(e.remarks)))
o:depends("tcp_node", v.id)
o:value("nil", translate("Close"))
o:value("_default", translate("Default"))
o:value("_direct", translate("Direct Connection"))
o:value("_blackhole", translate("Blackhole"))
for k1, v1 in pairs(normal_list) do
o:value(v1.id, v1["remark"])
end
o.cfgvalue = function(self, section)
return m:get(v.id, id) or "nil"
end
o.write = function(self, section, value)
m:set(v.id, id, value)
end
end)
local id = "default_node"
o = s:taboption("Main", ListValue, v.id .. "." .. id, string.format('* <a style="color:red">%s</a>', translate("Default")))
o:depends("tcp_node", v.id)
o:value("_direct", translate("Direct Connection"))
o:value("_blackhole", translate("Blackhole"))
for k1, v1 in pairs(normal_list) do
o:value(v1.id, v1["remark"])
end
o.cfgvalue = function(self, section)
return m:get(v.id, id) or "nil"
end
o.write = function(self, section, value)
m:set(v.id, id, value)
end
local id = "main_node"
o = s:taboption("Main", ListValue, v.id .. "." .. 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:depends("tcp_node", v.id)
o:value("nil", translate("Close"))
for k1, v1 in pairs(normal_list) do
o:value(v1.id, v1["remark"])
end
o.cfgvalue = function(self, section)
return m:get(v.id, id) or "nil"
end
o.write = function(self, section, value)
m:set(v.id, id, value)
end
end
end
udp_node = s:taboption("Main", ListValue, "udp_node", "<a style='color: red'>" .. translate("UDP Node") .. "</a>")
udp_node:value("nil", translate("Close"))
--udp_node.description = translate("For proxy game network.")
udp_node:value("tcp", translate("Same as the tcp node"))
s:tab("DNS", translate("DNS"))
if api.is_finded("smartdns") then
dns_shunt = s:taboption("DNS", ListValue, "dns_shunt", translate("DNS Shunt"))
dns_shunt:value("dnsmasq", "Dnsmasq")
dns_shunt:value("smartdns", "SmartDNS")
group_domestic = s:taboption("DNS", Value, "group_domestic", translate("Domestic group name"))
group_domestic.placeholder = "local"
group_domestic:depends("dns_shunt", "smartdns")
group_domestic.description = translate("You only need to configure domestic DNS packets in SmartDNS and set it redirect or as Dnsmasq upstream, and fill in the domestic DNS group name here.")
end
o = s:taboption("DNS", Flag, "filter_proxy_ipv6", translate("Filter Proxy Host IPv6"), translate("Experimental feature."))
o.default = "0"
---- DNS Forward Mode
dns_mode = s:taboption("DNS", ListValue, "dns_mode", translate("Filter Mode"))
dns_mode.rmempty = false
dns_mode:reset_values()
if api.is_finded("pdnsd") then
dns_mode:value("pdnsd", "pdnsd " .. translatef("Requery DNS By %s", translate("TCP Node")))
end
if api.is_finded("dns2socks") then
dns_mode:value("dns2socks", "dns2socks")
end
if has_v2ray then
dns_mode:value("v2ray", "V2ray")
end
if has_xray then
dns_mode:value("xray", "Xray")
end
dns_mode:value("udp", translatef("Requery DNS By %s", "UDP"))
o = s:taboption("DNS", ListValue, "v2ray_dns_mode", " ")
o:value("tcp", "TCP")
o:value("doh", "DoH")
o:value("fakedns", "FakeDNS")
o:depends("dns_mode", "v2ray")
o:depends("dns_mode", "xray")
o.validate = function(self, value, t)
if value == "fakedns" then
local _dns_mode = dns_mode:formvalue(t)
local _tcp_node = tcp_node:formvalue(t)
if m:get(_tcp_node, "type"):lower() ~= _dns_mode then
return nil, translatef("TCP node must be '%s' type to use FakeDNS.", _dns_mode)
end
end
return value
end
o = s:taboption("DNS", ListValue, "dns_by", translate("Resolver For The List Proxied"))
o:value("tcp", translatef("Requery DNS By %s", translate("TCP Node")))
o:value("socks", translatef("Requery DNS By %s", translate("Socks Node")))
o:depends("v2ray_dns_mode", "tcp")
o:depends("v2ray_dns_mode", "doh")
o = s:taboption("DNS", Value, "socks_server", translate("Socks Server"), translate("Make sure socks service is available on this address."))
for k, v in pairs(socks_table) do o:value(v.id, v.remarks) end
o.validate = function(self, value, t)
if not datatypes.ipaddrport(value) then
return nil, translate("Socks Server") .. " " .. translate("Not valid IP format, please re-enter!")
end
return value
end
o:depends({dns_mode = "dns2socks"})
o:depends({dns_by = "socks"})
---- DoH
o = s:taboption("DNS", Value, "up_trust_doh", translate("DoH request address"))
o:value("https://cloudflare-dns.com/dns-query,1.1.1.1", "CloudFlare")
o:value("https://security.cloudflare-dns.com/dns-query,1.1.1.2", "CloudFlare-Security")
o:value("https://doh.opendns.com/dns-query,208.67.222.222", "OpenDNS")
o:value("https://dns.google/dns-query,8.8.8.8", "Google")
o:value("https://doh.libredns.gr/dns-query,116.202.176.26", "LibreDNS")
o:value("https://doh.libredns.gr/ads,116.202.176.26", "LibreDNS (No Ads)")
o:value("https://dns.quad9.net/dns-query,9.9.9.9", "Quad9-Recommended")
o:value("https://dns.adguard.com/dns-query,176.103.130.130", "AdGuard")
o.default = "https://cloudflare-dns.com/dns-query,1.1.1.1"
o.validate = doh_validate
o:depends("v2ray_dns_mode", "doh")
---- DNS Forward
o = s:taboption("DNS", Value, "dns_forward", translate("Remote DNS"))
--o.description = translate("IP:Port mode acceptable, multi value split with english comma.") .. " " .. translate("If you use dns2socks, only the first one is valid.")
o.datatype = "or(ipaddr,ipaddrport)"
o.default = "1.1.1.1"
o:value("1.1.1.1", "1.1.1.1 (CloudFlare DNS)")
o:value("1.1.1.2", "1.1.1.2 (CloudFlare DNS)")
o:value("8.8.8.8", "8.8.8.8 (Google DNS)")
o:value("8.8.4.4", "8.8.4.4 (Google DNS)")
o:value("208.67.222.222", "208.67.222.222 (Open DNS)")
o:value("208.67.220.220", "208.67.220.220 (Open DNS)")
o:depends({dns_mode = "dns2socks"})
o:depends({dns_mode = "pdnsd"})
o:depends({dns_mode = "udp"})
o:depends({v2ray_dns_mode = "tcp"})
o = s:taboption("DNS", Value, "dns_client_ip", translate("EDNS Client Subnet"))
o.description = translate("Notify the DNS server when the DNS query is notified, the location of the client (cannot be a private IP address).") .. "<br />" ..
translate("This feature requires the DNS server to support the Edns Client Subnet (RFC7871).")
o.datatype = "ipaddr"
o:depends("v2ray_dns_mode", "tcp")
o:depends("v2ray_dns_mode", "doh")
o = s:taboption("DNS", Flag, "dns_cache", translate("Cache Resolved"))
o.default = "1"
o:depends({dns_mode = "dns2socks"})
o:depends({dns_mode = "pdnsd"})
o:depends({dns_mode = "v2ray", v2ray_dns_mode = "tcp"})
o:depends({dns_mode = "v2ray", v2ray_dns_mode = "doh"})
o:depends({dns_mode = "xray", v2ray_dns_mode = "tcp"})
o:depends({dns_mode = "xray", v2ray_dns_mode = "doh"})
o.rmempty = false
if has_chnlist and api.is_finded("chinadns-ng") then
o = s:taboption("DNS", Flag, "chinadns_ng", translate("ChinaDNS-NG"), translate("The effect is better, but will increase the memory."))
o.default = "0"
o:depends({dns_mode = "dns2socks"})
o:depends({dns_mode = "pdnsd"})
o:depends({dns_mode = "v2ray", v2ray_dns_mode = "tcp"})
o:depends({dns_mode = "v2ray", v2ray_dns_mode = "doh"})
o:depends({dns_mode = "xray", v2ray_dns_mode = "tcp"})
o:depends({dns_mode = "xray", v2ray_dns_mode = "doh"})
o:depends({dns_mode = "udp"})
end
o = s:taboption("DNS", Button, "clear_ipset", translate("Clear IPSET"), translate("Try this feature if the rule modification does not take effect."))
o.inputstyle = "remove"
function o.write(e, e)
luci.sys.call("/usr/share/" .. appname .. "/iptables.sh flush_ipset > /dev/null 2>&1 &")
luci.http.redirect(api.url("log"))
end
s:tab("Proxy", translate("Mode"))
---- TCP Default Proxy Mode
tcp_proxy_mode = s:taboption("Proxy", ListValue, "tcp_proxy_mode", "TCP " .. translate("Default") .. translate("Proxy Mode"))
-- o.description = translate("If not available, try clearing the cache.")
tcp_proxy_mode:value("disable", translate("No Proxy"))
tcp_proxy_mode:value("global", translate("Global Proxy"))
tcp_proxy_mode:value("gfwlist", translate("GFW List"))
tcp_proxy_mode:value("chnroute", translate("Not China List"))
if has_chnlist then
tcp_proxy_mode:value("returnhome", translate("China List"))
end
tcp_proxy_mode:value("direct/proxy", translate("Only use direct/proxy list"))
tcp_proxy_mode.default = "chnroute"
--tcp_proxy_mode.validate = redir_mode_validate
---- UDP Default Proxy Mode
udp_proxy_mode = s:taboption("Proxy", ListValue, "udp_proxy_mode", "UDP " .. translate("Default") .. translate("Proxy Mode"))
udp_proxy_mode:value("disable", translate("No Proxy"))
udp_proxy_mode:value("global", translate("Global Proxy"))
udp_proxy_mode:value("gfwlist", translate("GFW List"))
udp_proxy_mode:value("chnroute", translate("Not China List"))
if has_chnlist then
udp_proxy_mode:value("returnhome", translate("China List"))
end
udp_proxy_mode:value("direct/proxy", translate("Only use direct/proxy list"))
udp_proxy_mode.default = "chnroute"
--udp_proxy_mode.validate = redir_mode_validate
---- Localhost TCP Proxy Mode
localhost_tcp_proxy_mode = s:taboption("Proxy", ListValue, "localhost_tcp_proxy_mode", translate("Router Localhost") .. " TCP " .. translate("Proxy Mode"))
-- o.description = translate("The server client can also use this rule to scientifically surf the Internet.")
localhost_tcp_proxy_mode:value("default", translatef("Same as the %s default proxy mode", "TCP"))
localhost_tcp_proxy_mode:value("global", translate("Global Proxy"))
localhost_tcp_proxy_mode:value("gfwlist", translate("GFW List"))
localhost_tcp_proxy_mode:value("chnroute", translate("Not China List"))
if has_chnlist then
localhost_tcp_proxy_mode:value("returnhome", translate("China List"))
end
localhost_tcp_proxy_mode:value("disable", translate("No Proxy"))
localhost_tcp_proxy_mode:value("direct/proxy", translate("Only use direct/proxy list"))
localhost_tcp_proxy_mode.default = "default"
--localhost_tcp_proxy_mode.validate = redir_mode_validate
---- Localhost UDP Proxy Mode
localhost_udp_proxy_mode = s:taboption("Proxy", ListValue, "localhost_udp_proxy_mode", translate("Router Localhost") .. " UDP " .. translate("Proxy Mode"))
localhost_udp_proxy_mode:value("default", translatef("Same as the %s default proxy mode", "UDP"))
localhost_udp_proxy_mode:value("global", translate("Global Proxy"))
localhost_udp_proxy_mode:value("gfwlist", translate("GFW List"))
localhost_udp_proxy_mode:value("chnroute", translate("Not China List"))
if has_chnlist then
localhost_udp_proxy_mode:value("returnhome", translate("China List"))
end
localhost_udp_proxy_mode:value("disable", translate("No Proxy"))
localhost_udp_proxy_mode:value("direct/proxy", translate("Only use direct/proxy list"))
localhost_udp_proxy_mode.default = "default"
localhost_udp_proxy_mode.validate = redir_mode_validate
tips = s:taboption("Proxy", DummyValue, "tips", " ")
tips.rawhtml = true
tips.cfgvalue = function(t, n)
return string.format('<a style="color: red" href="%s">%s</a>', api.url("acl"), translate("Want different devices to use different proxy modes/ports/nodes? Please use access control."))
end
s:tab("log", translate("Log"))
o = s:taboption("log", Flag, "close_log_tcp", translatef("%s Node Log Close", "TCP"))
o.rmempty = false
o = s:taboption("log", Flag, "close_log_udp", translatef("%s Node Log Close", "UDP"))
o.rmempty = false
loglevel = s:taboption("log", ListValue, "loglevel", "V2ray/Xray" .. translate("Log Level"))
loglevel.default = "warning"
loglevel:value("debug")
loglevel:value("info")
loglevel:value("warning")
loglevel:value("error")
trojan_loglevel = s:taboption("log", ListValue, "trojan_loglevel", "Trojan" .. translate("Log Level"))
trojan_loglevel.default = "2"
trojan_loglevel:value("0", "all")
trojan_loglevel:value("1", "info")
trojan_loglevel:value("2", "warn")
trojan_loglevel:value("3", "error")
trojan_loglevel:value("4", "fatal")
s:tab("faq", "FAQ")
o = s:taboption("faq", DummyValue, "")
o.template = appname .. "/global/faq"
-- [[ Socks Server ]]--
o = s:taboption("Main", Flag, "socks_enabled", "Socks " .. translate("Main switch"))
o.rmempty = false
s = m:section(TypedSection, "socks", translate("Socks Config"))
s.anonymous = true
s.addremove = true
s.template = "cbi/tblsection"
function s.create(e, t)
TypedSection.create(e, api.gen_uuid())
end
o = s: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.default = 1
o.rmempty = false
socks_node = s:option(ListValue, "node", translate("Socks Node"))
socks_node:value("tcp", translate("Same as the tcp node"))
local n = 0
uci:foreach(appname, "socks", function(s)
if s[".name"] == section then
return false
end
n = n + 1
end)
o = s:option(Value, "port", "Socks " .. translate("Listen Port"))
o.default = n + 1080
o.datatype = "port"
o.rmempty = false
if has_v2ray or has_xray then
o = s: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
tcp_node:value(v.id, v["remark"])
udp_node:value(v.id, v["remark"])
if v.type == "Socks" then
if has_v2ray or has_xray then
socks_node:value(v.id, v["remark"])
end
else
socks_node:value(v.id, v["remark"])
end
end
m:append(Template(appname .. "/global/footer"))
return m

View File

@@ -1,121 +0,0 @@
local api = require "luci.model.cbi.passwall.api.api"
local appname = api.appname
local sys = api.sys
local net = require "luci.model.network".init()
local datatypes = api.datatypes
local nodes_table = {}
for k, e in ipairs(api.get_valid_nodes()) do
if e.node_type == "normal" then
nodes_table[#nodes_table + 1] = {
id = e[".name"],
obj = e,
remarks = e["remark"]
}
end
end
m = Map(appname)
-- [[ Haproxy Settings ]]--
s = m:section(TypedSection, "global_haproxy")
s.anonymous = true
s:append(Template(appname .. "/haproxy/status"))
---- Balancing Enable
o = s:option(Flag, "balancing_enable", translate("Enable Load Balancing"))
o.rmempty = false
o.default = false
---- Console Username
o = s:option(Value, "console_user", translate("Console Username"))
o.default = ""
o:depends("balancing_enable", true)
---- Console Password
o = s:option(Value, "console_password", translate("Console Password"))
o.password = true
o.default = ""
o:depends("balancing_enable", true)
---- Console Port
o = s:option(Value, "console_port", translate("Console Port"), translate(
"In the browser input routing IP plus port access, such as:192.168.1.1:1188"))
o.default = "1188"
o:depends("balancing_enable", true)
-- [[ Balancing Settings ]]--
s = m:section(TypedSection, "haproxy_config", "",
"<font color='red'>" ..
translate("Add a node, Export Of Multi WAN Only support Multi Wan. Load specific gravity range 1-256. Multiple primary servers can be load balanced, standby will only be enabled when the primary server is offline! Multiple groups can be set, Haproxy port same one for each group.") ..
"\n" .. translate("Note that the node configuration parameters for load balancing must be consistent, otherwise problems can arise!") ..
"</font>")
s.template = "cbi/tblsection"
s.sortable = true
s.anonymous = true
s.addremove = true
s.create = function(e, t)
TypedSection.create(e, api.gen_uuid())
end
s.remove = function(self, section)
for k, v in pairs(self.children) do
v.rmempty = true
v.validate = nil
end
TypedSection.remove(self, section)
end
---- Enable
o = s:option(Flag, "enabled", translate("Enable"))
o.default = 1
o.rmempty = false
---- Node Address
o = s:option(Value, "lbss", translate("Node Address"))
for k, v in pairs(nodes_table) do o:value(v.id, v.remarks) end
o.rmempty = false
o.validate = function(self, value)
if not value then return nil end
local t = m:get(value) or nil
if t and t[".type"] == "nodes" then
return value
end
if datatypes.hostport(value) or datatypes.ip4addrport(value) then
return value
end
if api.is_ipv6addrport(value) then
return value
end
return nil, value
end
---- Haproxy Port
o = s:option(Value, "haproxy_port", translate("Haproxy Port"))
o.datatype = "port"
o.default = 1181
o.rmempty = false
---- Node Weight
o = s:option(Value, "lbweight", translate("Node Weight"))
o.datatype = "uinteger"
o.default = 5
o.rmempty = false
---- Export
o = s:option(ListValue, "export", translate("Export Of Multi WAN"))
o:value(0, translate("Auto"))
local wa = require "luci.tools.webadmin"
wa.cbi_add_networks(o)
o.default = 0
o.rmempty = false
---- Mode
o = s:option(ListValue, "backup", translate("Mode"))
o:value(0, translate("Primary"))
o:value(1, translate("Standby"))
o.rmempty = false
return m

View File

@@ -1,91 +0,0 @@
local api = require "luci.model.cbi.passwall.api.api"
local appname = api.appname
local has_v2ray = api.is_finded("v2ray")
local has_xray = api.is_finded("xray")
m = Map(appname)
-- [[ Rule Settings ]]--
s = m:section(TypedSection, "global_rules", translate("Rule status"))
s.anonymous = true
--[[
o = s:option(Flag, "adblock", translate("Enable adblock"))
o.rmempty = false
]]--
---- gfwlist URL
o = s:option(DynamicList, "gfwlist_url", translate("GFW domains(gfwlist) Update URL"))
o:value("https://cdn.jsdelivr.net/gh/YW5vbnltb3Vz/domain-list-community@release/gfwlist.txt", translate("v2fly/domain-list-community"))
o:value("https://cdn.jsdelivr.net/gh/Loyalsoldier/v2ray-rules-dat@release/gfw.txt", translate("Loyalsoldier/v2ray-rules-dat"))
o:value("https://cdn.jsdelivr.net/gh/Loukky/gfwlist-by-loukky/gfwlist.txt", translate("Loukky/gfwlist-by-loukky"))
o:value("https://cdn.jsdelivr.net/gh/gfwlist/gfwlist/gfwlist.txt", translate("gfwlist/gfwlist"))
o.default = "https://cdn.jsdelivr.net/gh/Loukky/gfwlist-by-loukky/gfwlist.txt"
----chnroute URL
o = s:option(DynamicList, "chnroute_url", translate("China IPs(chnroute) Update URL"))
o:value("https://ispip.clang.cn/all_cn.txt", translate("Clang.CN"))
o:value("https://ispip.clang.cn/all_cn_cidr.txt", translate("Clang.CN.CIDR"))
o:value("https://cdn.jsdelivr.net/gh/soffchen/GeoIP2-CN@release/CN-ip-cidr.txt", translate("soffchen/GeoIP2-CN"))
o:value("https://cdn.jsdelivr.net/gh/Hackl0us/GeoIP2-CN@release/CN-ip-cidr.txt", translate("Hackl0us/GeoIP2-CN"))
o.default = "https://ispip.clang.cn/all_cn.txt"
----chnroute6 URL
o = s:option(DynamicList, "chnroute6_url", translate("China IPv6s(chnroute6) Update URL"))
o:value("https://ispip.clang.cn/all_cn_ipv6.txt", translate("Clang.CN.IPv6"))
o.default = "https://ispip.clang.cn/all_cn_ipv6.txt"
----chnlist URL
o = s:option(DynamicList, "chnlist_url", translate("China List(Chnlist) Update URL"))
o:value("https://cdn.jsdelivr.net/gh/felixonmars/dnsmasq-china-list/accelerated-domains.china.conf", translate("felixonmars/domains.china"))
o:value("https://cdn.jsdelivr.net/gh/felixonmars/dnsmasq-china-list/apple.china.conf", translate("felixonmars/apple.china"))
o:value("https://cdn.jsdelivr.net/gh/felixonmars/dnsmasq-china-list/google.china.conf", translate("felixonmars/google.china"))
s:append(Template(appname .. "/rule/rule_version"))
---- Auto Update
o = s:option(Flag, "auto_update", translate("Enable auto update rules"))
o.default = 0
o.rmempty = false
---- Week Update
o = s:option(ListValue, "week_update", translate("Week update rules"))
o:value(7, translate("Every day"))
for e = 1, 6 do o:value(e, translate("Week") .. e) end
o:value(0, translate("Week") .. translate("day"))
o.default = 0
o:depends("auto_update", true)
---- Time Update
o = s:option(ListValue, "time_update", translate("Day update rules"))
for e = 0, 23 do o:value(e, e .. translate("oclock")) end
o.default = 0
o:depends("auto_update", true)
if has_v2ray or has_xray then
o = s:option(Value, "v2ray_location_asset", translate("Location of V2ray/Xray asset"), translate("This variable specifies a directory where geoip.dat and geosite.dat files are."))
o.default = "/usr/share/v2ray/"
o.rmempty = false
s = m:section(TypedSection, "shunt_rules", "V2ray/Xray " .. translate("Shunt Rule"), "<a style='color: red'>" .. translate("Please note attention to the priority, the higher the order, the higher the priority.") .. "</a>")
s.template = "cbi/tblsection"
s.anonymous = false
s.addremove = true
s.sortable = true
s.extedit = api.url("shunt_rules", "%s")
function s.create(e, t)
TypedSection.create(e, t)
luci.http.redirect(e.extedit:format(t))
end
function s.remove(e, t)
m.uci:foreach(appname, "nodes", function(s)
if s["protocol"] and s["protocol"] == "_shunt" then
m:del(s[".name"], t)
end
end)
TypedSection.remove(e, t)
end
o = s:option(DummyValue, "remarks", translate("Remarks"))
end
return m

View File

@@ -1,205 +0,0 @@
local api = require "luci.model.cbi.passwall.api.api"
local appname = api.appname
local fs = api.fs
local datatypes = api.datatypes
local path = string.format("/usr/share/%s/rules/", appname)
local route_hosts_path = "/etc/"
m = Map(appname)
-- [[ Rule List Settings ]]--
s = m:section(TypedSection, "global_rules")
s.anonymous = true
s:tab("direct_list", translate("Direct List"))
s:tab("proxy_list", translate("Proxy List"))
s:tab("block_list", translate("Block List"))
s:tab("lan_ip_list", translate("Lan IP List"))
s:tab("route_hosts", translate("Route Hosts"))
---- Direct Hosts
local direct_host = path .. "direct_host"
o = s:taboption("direct_list", TextValue, "direct_host", "", "<font color='red'>" .. translate("Join the direct hosts list of domain names will not proxy.") .. "</font>")
o.rows = 15
o.wrap = "off"
o.cfgvalue = function(self, section) return fs.readfile(direct_host) or "" end
o.write = function(self, section, value) fs.writefile(direct_host, value:gsub("\r\n", "\n")) end
o.remove = function(self, section, value) fs.writefile(direct_host, "") end
o.validate = function(self, value)
local hosts= {}
string.gsub(value, '[^' .. "\r\n" .. ']+', function(w) table.insert(hosts, w) end)
for index, host in ipairs(hosts) do
if host:find("#") and host:find("#") == 1 then
return value
end
if not datatypes.hostname(host) then
return nil, host .. " " .. translate("Not valid domain name, please re-enter!")
end
end
return value
end
---- Direct IP
local direct_ip = path .. "direct_ip"
o = s:taboption("direct_list", TextValue, "direct_ip", "", "<font color='red'>" .. translate("These had been joined ip addresses will not proxy. Please input the ip address or ip address segment,every line can input only one ip address. For example: 192.168.0.0/24 or 223.5.5.5.") .. "</font>")
o.rows = 15
o.wrap = "off"
o.cfgvalue = function(self, section) return fs.readfile(direct_ip) or "" end
o.write = function(self, section, value) fs.writefile(direct_ip, value:gsub("\r\n", "\n")) end
o.remove = function(self, section, value) fs.writefile(direct_ip, "") end
o.validate = function(self, value)
local ipmasks= {}
string.gsub(value, '[^' .. "\r\n" .. ']+', function(w) table.insert(ipmasks, w) end)
for index, ipmask in ipairs(ipmasks) do
if ipmask:find("#") and ipmask:find("#") == 1 then
return value
end
if not ( datatypes.ipmask4(ipmask) or datatypes.ipmask6(ipmask) ) then
return nil, ipmask .. " " .. translate("Not valid IP format, please re-enter!")
end
end
return value
end
---- Proxy Hosts
local proxy_host = path .. "proxy_host"
o = s:taboption("proxy_list", TextValue, "proxy_host", "", "<font color='red'>" .. translate("These had been joined websites will use proxy. Please input the domain names of websites, every line can input only one website domain. For example: google.com.") .. "</font>")
o.rows = 15
o.wrap = "off"
o.cfgvalue = function(self, section) return fs.readfile(proxy_host) or "" end
o.write = function(self, section, value) fs.writefile(proxy_host, value:gsub("\r\n", "\n")) end
o.remove = function(self, section, value) fs.writefile(proxy_host, "") end
o.validate = function(self, value)
local hosts= {}
string.gsub(value, '[^' .. "\r\n" .. ']+', function(w) table.insert(hosts, w) end)
for index, host in ipairs(hosts) do
if host:find("#") and host:find("#") == 1 then
return value
end
if not datatypes.hostname(host) then
return nil, host .. " " .. translate("Not valid domain name, please re-enter!")
end
end
return value
end
---- Proxy IP
local proxy_ip = path .. "proxy_ip"
o = s:taboption("proxy_list", TextValue, "proxy_ip", "", "<font color='red'>" .. translate("These had been joined ip addresses will use proxy. Please input the ip address or ip address segment, every line can input only one ip address. For example: 35.24.0.0/24 or 8.8.4.4.") .. "</font>")
o.rows = 15
o.wrap = "off"
o.cfgvalue = function(self, section) return fs.readfile(proxy_ip) or "" end
o.write = function(self, section, value) fs.writefile(proxy_ip, value:gsub("\r\n", "\n")) end
o.remove = function(self, section, value) fs.writefile(proxy_ip, "") end
o.validate = function(self, value)
local ipmasks= {}
string.gsub(value, '[^' .. "\r\n" .. ']+', function(w) table.insert(ipmasks, w) end)
for index, ipmask in ipairs(ipmasks) do
if ipmask:find("#") and ipmask:find("#") == 1 then
return value
end
if not ( datatypes.ipmask4(ipmask) or datatypes.ipmask6(ipmask) ) then
return nil, ipmask .. " " .. translate("Not valid IP format, please re-enter!")
end
end
return value
end
---- Block Hosts
local block_host = path .. "block_host"
o = s:taboption("block_list", TextValue, "block_host", "", "<font color='red'>" .. translate("These had been joined websites will be block. Please input the domain names of websites, every line can input only one website domain. For example: twitter.com.") .. "</font>")
o.rows = 15
o.wrap = "off"
o.cfgvalue = function(self, section) return fs.readfile(block_host) or "" end
o.write = function(self, section, value) fs.writefile(block_host, value:gsub("\r\n", "\n")) end
o.remove = function(self, section, value) fs.writefile(block_host, "") end
o.validate = function(self, value)
local hosts= {}
string.gsub(value, '[^' .. "\r\n" .. ']+', function(w) table.insert(hosts, w) end)
for index, host in ipairs(hosts) do
if host:find("#") and host:find("#") == 1 then
return value
end
if not datatypes.hostname(host) then
return nil, host .. " " .. translate("Not valid domain name, please re-enter!")
end
end
return value
end
---- Block IP
local block_ip = path .. "block_ip"
o = s:taboption("block_list", TextValue, "block_ip", "", "<font color='red'>" .. translate("These had been joined ip addresses will be block. Please input the ip address or ip address segment, every line can input only one ip address.") .. "</font>")
o.rows = 15
o.wrap = "off"
o.cfgvalue = function(self, section) return fs.readfile(block_ip) or "" end
o.write = function(self, section, value) fs.writefile(block_ip, value:gsub("\r\n", "\n")) end
o.remove = function(self, section, value) fs.writefile(block_ip, "") end
o.validate = function(self, value)
local ipmasks= {}
string.gsub(value, '[^' .. "\r\n" .. ']+', function(w) table.insert(ipmasks, w) end)
for index, ipmask in ipairs(ipmasks) do
if ipmask:find("#") and ipmask:find("#") == 1 then
return value
end
if not ( datatypes.ipmask4(ipmask) or datatypes.ipmask6(ipmask) ) then
return nil, ipmask .. " " .. translate("Not valid IP format, please re-enter!")
end
end
return value
end
---- Lan IPv4
local lanlist_ipv4 = path .. "lanlist_ipv4"
o = s:taboption("lan_ip_list", TextValue, "lanlist_ipv4", "", "<font color='red'>" .. translate("The list is the IPv4 LAN IP list, which represents the direct connection IP of the LAN. If you need the LAN IP in the proxy list, please clear it from the list. Do not modify this list by default.") .. "</font>")
o.rows = 15
o.wrap = "off"
o.cfgvalue = function(self, section) return fs.readfile(lanlist_ipv4) or "" end
o.write = function(self, section, value) fs.writefile(lanlist_ipv4, value:gsub("\r\n", "\n")) end
o.remove = function(self, section, value) fs.writefile(lanlist_ipv4, "") end
o.validate = function(self, value)
local ipmasks= {}
string.gsub(value, '[^' .. "\r\n" .. ']+', function(w) table.insert(ipmasks, w) end)
for index, ipmask in ipairs(ipmasks) do
if ipmask:find("#") and ipmask:find("#") == 1 then
return value
end
if not datatypes.ipmask4(ipmask) then
return nil, ipmask .. " " .. translate("Not valid IPv4 format, please re-enter!")
end
end
return value
end
---- Lan IPv6
local lanlist_ipv6 = path .. "lanlist_ipv6"
o = s:taboption("lan_ip_list", TextValue, "lanlist_ipv6", "", "<font color='red'>" .. translate("The list is the IPv6 LAN IP list, which represents the direct connection IP of the LAN. If you need the LAN IP in the proxy list, please clear it from the list. Do not modify this list by default.") .. "</font>")
o.rows = 15
o.wrap = "off"
o.cfgvalue = function(self, section) return fs.readfile(lanlist_ipv6) or "" end
o.write = function(self, section, value) fs.writefile(lanlist_ipv6, value:gsub("\r\n", "\n")) end
o.remove = function(self, section, value) fs.writefile(lanlist_ipv6, "") end
o.validate = function(self, value)
local ipmasks= {}
string.gsub(value, '[^' .. "\r\n" .. ']+', function(w) table.insert(ipmasks, w) end)
for index, ipmask in ipairs(ipmasks) do
if ipmask:find("#") and ipmask:find("#") == 1 then
return value
end
if not datatypes.ipmask6(ipmask) then
return nil, ipmask .. " " .. translate("Not valid IPv6 format, please re-enter!")
end
end
return value
end
---- Route Hosts
local hosts = route_hosts_path .. "hosts"
o = s:taboption("route_hosts", TextValue, "hosts", "", "<font color='red'>" .. translate("Configure routing etc/hosts file, if you don't know what you are doing, please don't change the content.") .. "</font>")
o.rows = 15
o.wrap = "off"
o.cfgvalue = function(self, section) return fs.readfile(hosts) or "" end
o.write = function(self, section, value) fs.writefile(hosts, value:gsub("\r\n", "\n")) end
o.remove = function(self, section, value) fs.writefile(hosts, "") end
return m

View File

@@ -1,61 +0,0 @@
module("luci.model.cbi.passwall.server.api.trojan", package.seeall)
function gen_config(user)
local cipher = "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:AES128-SHA:AES256-SHA:DES-CBC3-SHA"
local cipher13 = "TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384"
local config = {
run_type = "server",
local_addr = "::",
local_port = tonumber(user.port),
remote_addr = (user.remote_enable == "1" and user.remote_address) and user.remote_address or nil,
remote_port = (user.remote_enable == "1" and user.remote_port) and tonumber(user.remote_port) or nil,
password = user.uuid,
log_level = (user.log and user.log == "1") and tonumber(user.loglevel) or 5,
ssl = {
cert = user.tls_certificateFile,
key = user.tls_keyFile,
key_password = "",
cipher = cipher,
cipher_tls13 = cipher13,
prefer_server_cipher = true,
reuse_session = true,
session_ticket = (user.tls_sessionTicket == "1") and true or false,
session_timeout = 600,
plain_http_response = "",
curves = "",
dhparam = ""
},
tcp = {
prefer_ipv4 = false,
no_delay = true,
keep_alive = true,
reuse_port = false,
fast_open = (user.tcp_fast_open and user.tcp_fast_open == "1") and true or false,
fast_open_qlen = 20
}
}
if user.type == "Trojan-Go" then
config.ssl.cipher = nil
config.ssl.cipher_tls13 = nil
config.udp_timeout = 60
config.disable_http_check = true
config.transport_plugin = ((user.tls == nil or user.tls ~= "1") and user.trojan_transport == "original") and {
enabled = user.plugin_type ~= nil,
type = user.plugin_type or "plaintext",
command = user.plugin_type ~= "plaintext" and user.plugin_cmd or nil,
option = user.plugin_type ~= "plaintext" and user.plugin_option or nil,
arg = user.plugin_type ~= "plaintext" and { user.plugin_arg } or nil,
env = {}
} or nil
config.websocket = (user.trojan_transport == 'ws') and {
enabled = true,
path = user.ws_path or "/",
host = user.ws_host or ""
} or nil
config.shadowsocks = (user.ss_aead == "1") and {
enabled = true,
method = user.ss_aead_method or "aes_128_gcm",
password = user.ss_aead_pwd or ""
} or nil
end
return config
end

View File

@@ -1,175 +0,0 @@
<%
local api = require "luci.model.cbi.passwall.api.api"
local kcptun_version = api.get_kcptun_version()
-%>
<script type="text/javascript">
//<![CDATA[
var kcptunInfo;
var tokenStr = '<%=token%>';
var manuallyUpdateText = '<%:Manually update%>';
var noUpdateText = '<%:It is the latest version%>';
var updateSuccessText = '<%:Update successful%>';
var clickToUpdateText = '<%:Click to update%>';
var inProgressText = '<%:Updating...%>';
var unexpectedErrorText = '<%:Unexpected error%>';
var updateInProgressNotice = '<%:Updating, are you sure to close?%>';
var downloadingText = '<%:Downloading...%>';
var decompressioningText = '<%:Unpacking...%>';
var movingText = '<%:Moving...%>';
window.onload = function () {
var kcptunCheckBtn = document.getElementById('_kcptun-check_btn');
var kcptunDetailElm = document.getElementById('_kcptun-check_btn-detail');
};
function addPageNotice_kcptun() {
window.onbeforeunload = function (e) {
e.returnValue = updateInProgressNotice;
return updateInProgressNotice;
};
}
function removePageNotice_kcptun() {
window.onbeforeunload = undefined;
}
function onUpdateSuccess_kcptun(btn) {
alert(updateSuccessText);
if (btn) {
btn.value = updateSuccessText;
btn.placeholder = updateSuccessText;
btn.disabled = true;
}
window.setTimeout(function () {
window.location.reload();
}, 1000);
}
function onRequestError_kcptun(btn, errorMessage) {
btn.disabled = false;
btn.value = manuallyUpdateText;
if (errorMessage) {
alert(errorMessage);
}
}
function onBtnClick_kcptun(btn) {
if (kcptunInfo === undefined) {
checkUpdate_kcptun(btn);
} else {
doUpdate_kcptun(btn);
}
}
function checkUpdate_kcptun(btn) {
btn.disabled = true;
btn.value = inProgressText;
addPageNotice_kcptun();
var ckeckDetailElm = document.getElementById(btn.id + '-detail');
XHR.get('<%=api.url("kcptun_check")%>', {
token: tokenStr,
arch: ''
}, function (x, json) {
removePageNotice_kcptun();
if (json.code) {
kcptunInfo = undefined;
onRequestError_kcptun(btn, json.error);
} else {
if (json.has_update) {
kcptunInfo = json;
btn.disabled = false;
btn.value = clickToUpdateText;
btn.placeholder = clickToUpdateText;
if (ckeckDetailElm) {
var urlNode = '';
if (json.remote_version) {
urlNode = '<em style="color:red;">' + json.remote_version + '</em>';
if (json.html_url) {
urlNode = '<a href="' + json.html_url + '" target="_blank">' + urlNode + '</a>';
}
}
ckeckDetailElm.innerHTML = urlNode;
}
} else {
btn.disabled = true;
btn.value = noUpdateText;
}
}
}, 300);
}
function doUpdate_kcptun(btn) {
btn.disabled = true;
btn.value = downloadingText;
addPageNotice_kcptun();
var kcptunUpdateUrl = '<%=api.url("kcptun_update")%>';
// Download file
XHR.get(kcptunUpdateUrl, {
token: tokenStr,
url: kcptunInfo ? kcptunInfo.data.browser_download_url : '',
size: kcptunInfo ? kcptunInfo.data.size / 1024 : null
}, function (x, json) {
if (json.code) {
removePageNotice_kcptun();
onRequestError_kcptun(btn, json.error);
} else {
btn.value = decompressioningText;
// Extract file
XHR.get(kcptunUpdateUrl, {
token: tokenStr,
task: 'extract',
file: json.file,
subfix: kcptunInfo ? kcptunInfo.type : ''
}, function (x, json) {
if (json.code) {
removePageNotice_kcptun();
onRequestError_kcptun(btn, json.error);
} else {
btn.value = movingText;
// Move file to target dir
XHR.get(kcptunUpdateUrl, {
token: tokenStr,
task: 'move',
file: json.file
}, function (x, json) {
removePageNotice_kcptun();
if (json.code) {
onRequestError_kcptun(btn, json.error);
} else {
onUpdateSuccess_kcptun(btn);
}
}, 300)
}
}, 300)
}
}, 300)
}
//]]>
</script>
<div class="cbi-value">
<label class="cbi-value-title">Kcptun
<%:Version%>
</label>
<div class="cbi-value-field">
<div class="cbi-value-description">
<span><%=kcptun_version ~="" and kcptun_version or translate("Null") %> 】</span>
<input class="btn cbi-button cbi-button-apply" type="button" id="_kcptun-check_btn"
onclick="onBtnClick_kcptun(this);" value="<%:Manually update%>" />
<span id="_kcptun-check_btn-detail"></span>
</div>
</div>
</div>

View File

@@ -1,175 +0,0 @@
<%
local api = require "luci.model.cbi.passwall.api.api"
local trojan_go_version = api.get_trojan_go_version()
-%>
<script type="text/javascript">
//<![CDATA[
var trojanInfo;
var tokenStr = '<%=token%>';
var manuallyUpdateText = '<%:Manually update%>';
var noUpdateText = '<%:It is the latest version%>';
var updateSuccessText = '<%:Update successful%>';
var clickToUpdateText = '<%:Click to update%>';
var inProgressText = '<%:Updating...%>';
var unexpectedErrorText = '<%:Unexpected error%>';
var updateInProgressNotice = '<%:Updating, are you sure to close?%>';
var downloadingText = '<%:Downloading...%>';
var decompressioningText = '<%:Unpacking...%>';
var movingText = '<%:Moving...%>';
window.onload = function () {
var trojanCheckBtn = document.getElementById('_trojan-check_btn');
var trojanDetailElm = document.getElementById('_trojan-check_btn-detail');
};
function addPageNotice_trojan() {
window.onbeforeunload = function (e) {
e.returnValue = updateInProgressNotice;
return updateInProgressNotice;
};
}
function removePageNotice_trojan() {
window.onbeforeunload = undefined;
}
function onUpdateSuccess_trojan(btn) {
alert(updateSuccessText);
if (btn) {
btn.value = updateSuccessText;
btn.placeholder = updateSuccessText;
btn.disabled = true;
}
window.setTimeout(function () {
window.location.reload();
}, 1000);
}
function onRequestError_trojan(btn, errorMessage) {
btn.disabled = false;
btn.value = manuallyUpdateText;
if (errorMessage) {
alert(errorMessage);
}
}
function onBtnClick_trojan(btn) {
if (trojanInfo === undefined) {
checkUpdate_trojan(btn);
} else {
doUpdate_trojan(btn);
}
}
function checkUpdate_trojan(btn) {
btn.disabled = true;
btn.value = inProgressText;
addPageNotice_trojan();
var ckeckDetailElm = document.getElementById(btn.id + '-detail');
XHR.get('<%=api.url("trojan_go_check")%>', {
token: tokenStr,
arch: ''
}, function (x, json) {
removePageNotice_trojan();
if (json.code) {
trojanInfo = undefined;
onRequestError_trojan(btn, json.error);
} else {
if (json.has_update) {
trojanInfo = json;
btn.disabled = false;
btn.value = clickToUpdateText;
btn.placeholder = clickToUpdateText;
if (ckeckDetailElm) {
var urlNode = '';
if (json.remote_version) {
urlNode = '<em style="color:red;">' + json.remote_version + '</em>';
if (json.html_url) {
urlNode = '<a href="' + json.html_url + '" target="_blank">' + urlNode + '</a>';
}
}
ckeckDetailElm.innerHTML = urlNode;
}
} else {
btn.disabled = true;
btn.value = noUpdateText;
}
}
}, 300);
}
function doUpdate_trojan(btn) {
btn.disabled = true;
btn.value = downloadingText;
addPageNotice_trojan();
var trojanUpdateUrl = '<%=api.url("trojan_go_update")%>';
// Download file
XHR.get(trojanUpdateUrl, {
token: tokenStr,
url: trojanInfo ? trojanInfo.data.browser_download_url : '',
size: trojanInfo ? trojanInfo.data.size / 1024 : null
}, function (x, json) {
if (json.code) {
removePageNotice_trojan();
onRequestError_trojan(btn, json.error);
} else {
btn.value = decompressioningText;
// Extract file
XHR.get(trojanUpdateUrl, {
token: tokenStr,
task: 'extract',
file: json.file,
subfix: trojanInfo ? trojanInfo.type : ''
}, function (x, json) {
if (json.code) {
removePageNotice_trojan();
onRequestError_trojan(btn, json.error);
} else {
btn.value = movingText;
// Move file to target dir
XHR.get(trojanUpdateUrl, {
token: tokenStr,
task: 'move',
file: json.file
}, function (x, json) {
removePageNotice_trojan();
if (json.code) {
onRequestError_trojan(btn, json.error);
} else {
onUpdateSuccess_trojan(btn);
}
}, 300)
}
}, 300)
}
}, 300)
}
//]]>
</script>
<div class="cbi-value">
<label class="cbi-value-title">Trojan-Go
<%:Version%>
</label>
<div class="cbi-value-field">
<div class="cbi-value-description">
<span><%=trojan_go_version ~="" and trojan_go_version or translate("Null") %> 】</span>
<input class="btn cbi-button cbi-button-apply" type="button" id="_trojan-check_btn"
onclick="onBtnClick_trojan(this);" value="<%:Manually update%>" />
<span id="_trojan-check_btn-detail"></span>
</div>
</div>
</div>

File diff suppressed because one or more lines are too long

View File

@@ -1,257 +0,0 @@
<%
local api = require "luci.model.cbi.passwall.api.api"
local status = api.uci_get_type("global_other", "status", "")
-%>
<style>
/* @media screen and (min-width: 1600px) {
#_passwall_status_fieldset > fieldset {
padding: 0px;
}
#_passwall_status_fieldset > fieldset > div {
width: 200px;
height: 60px;
background: #f7fafd;
float: left;
margin: 5px;
padding: 0.3rem 1rem;
border-radius: 10px;
display: flex;
align-items: center;
clear: unset;
}
#_passwall_status_fieldset > fieldset > div > .cbi-value-title {
text-align: left;
width: unset;
padding-top: unset;
}
#_passwall_status_fieldset > fieldset > div > .cbi-value-field {
padding-top: unset;
}
#_passwall_status_fieldset > fieldset > div > .cbi-value-field > font {
padding-top: unset;
}
#_node_status > font {
display: block;
}
}
*/
</style>
<fieldset id="_passwall_status_fieldset" class="cbi-section">
<legend>
<%:Running Status%>
</legend>
<fieldset class="cbi-section">
<div class="cbi-value">
<label class="cbi-value-title">TCP
<%:Status%>
</label>
<div class="cbi-value-field" id="_tcp_node_status">
<%:Collecting data...%>
</div>
</div>
<div class="cbi-value">
<label class="cbi-value-title">UDP
<%:Status%>
</label>
<div class="cbi-value-field" id="_udp_node_status">
<%:Collecting data...%>
</div>
</div>
<% if api.is_finded("haproxy") then %>
<div class="cbi-value">
<label class="cbi-value-title">
<%:Load Balancing%>
</label>
<div class="cbi-value-field" id="_haproxy_status">
<%:Collecting data...%>
</div>
</div>
<% end %>
<div class="cbi-value">
<label class="cbi-value-title">DNS
<%:Status%>
</label>
<div class="cbi-value-field" id="_dns_mode_status">
<%:Collecting data...%>
</div>
</div>
<div class="cbi-value">
<label class="cbi-value-title">
<%:Baidu Connection%>
</label>
<div class="cbi-value-field">
<input type="button" class="btn cbi-button cbi-button-apply" value="<%:Check%>" onclick="return check_connect(this, 'baidu', 'https://www.baidu.com')" />
<font id="_baidu_status"></font>
</div>
</div>
<div class="cbi-value">
<label class="cbi-value-title">
<%:Google Connection%>
</label>
<div class="cbi-value-field">
<input type="button" class="btn cbi-button cbi-button-apply" value="<%:Check%>" onclick="return check_connect(this, 'google', 'https://www.google.com/generate_204')" />
<font id="_google_status"></font>
</div>
</div>
<div class="cbi-value">
<label class="cbi-value-title">
<%:GitHub Connection%>
</label>
<div class="cbi-value-field">
<input type="button" class="btn cbi-button cbi-button-apply" value="<%:Check%>" onclick="return check_connect(this, 'github', 'https://github.com')" />
<font id="_github_status"></font>
</div>
</div>
<div class="cbi-value">
<label class="cbi-value-title">
<%:Instagram Connection%>
</label>
<div class="cbi-value-field">
<input type="button" class="btn cbi-button cbi-button-apply" value="<%:Check%>" onclick="return check_connect(this, 'instagram', 'https://www.instagram.com')" />
<font id="_instagram_status"></font>
</div>
</div>
<% if status:find("show_check_port") then %>
<div class="cbi-value">
<label class="cbi-value-title">
<%:Node Check%>
</label>
<div class="cbi-value-field">
<input type="button" class="btn cbi-button cbi-button-apply" value="<%:Check%>" onclick="return check_port(this)" />
<font id="_node_status"></font>
<input id="clear_check_port_btn" type="button" class="btn cbi-button cbi-button-remove" style="display:none" value="<%:Clear%>" onclick="return clear_check_port(this)" />
</div>
</div>
<% end %>
<% if status:find("show_ip111") then %>
<div class="cbi-value">
<label class="cbi-value-title"></label>
<div class="cbi-value-field">
<input type="button" class="btn cbi-button cbi-button-reload" value="IP111.cn" onclick="javascript:window.open('http://www.ip111.cn/','target');" />
</div>
</div>
<% end %>
</fieldset>
</fieldset>
<script type="text/javascript">
//<![CDATA[
var dns_mode_status = document.getElementById('_dns_mode_status');
var haproxy_status = document.getElementById('_haproxy_status');
XHR.poll(3, '<%=api.url("status")%>', null,
function(x, json) {
if (x && x.status == 200) {
var tcp_node_status = document.getElementById('_tcp_node_status');
if (tcp_node_status) {
if (true) {
var text = '';
if (json["tcp_node_status"])
text += '<font color="green"><%:RUNNING%> ✓</font>';
else
text += '<font color="red"><%:NOT RUNNING%> X</font>';
tcp_node_status.innerHTML = text;
}
}
var udp_node_status = document.getElementById('_udp_node_status');
if (udp_node_status) {
if (true) {
var text = '';
if (json["udp_node_status"])
text += '<font color="green"><%:RUNNING%> ✓</font>';
else
text += '<font color="red"><%:NOT RUNNING%> X</font>';
udp_node_status.innerHTML = text;
}
}
if (haproxy_status)
haproxy_status.innerHTML = json.haproxy_status ? '<font color="green"><%:RUNNING%> ✓</font>' : '<font color="red"><%:NOT RUNNING%> X</font>';
if (dns_mode_status)
dns_mode_status.innerHTML = json.dns_mode_status ? '<font color="green"><%:RUNNING%> ✓</font>' : '<font color="red"><%:NOT RUNNING%> X</font>';
}
});
function check_connect(btn, type, url) {
btn.disabled = true;
btn.value = '<%:Check...%>';
var sendDate = (new Date()).getTime();
XHR.get('<%=api.url("connect_status")%>', {
type: type,
url: url
},
function(x, rv) {
var s = document.getElementById('_' + type + '_status');
if (s) {
if (rv.ping_type && rv.ping_type == "curl") {
var use_time = rv.use_time;
var color="red";
if (use_time < 1000) {
color = "green";
} else if (use_time < 2000) {
color = "#b9b90b";
} else {
color = "red";
}
s.setAttribute("color", color);
s.innerHTML = use_time + " ms";
} else if (rv.status) {
s.setAttribute("color", "green");
s.innerHTML = "<%:Working...%>";
} else {
s.setAttribute("color", "red");
s.innerHTML = '<%:Problem detected!%> X';
}
}
btn.disabled = false;
btn.value = '<%:Check%>';
}
);
return false;
}
function check_port(btn) {
btn.disabled = true;
btn.value = '<%:Check...%>';
XHR.get('<%=api.url("check_port")%>', null,
function(x, rv) {
if (x && x.status == 200) {
var str = '<br />';
for (var i = 0; i < rv.length; i++) {
var obj = rv[i];
if (obj.flag) {
str += '<font color="green">' + obj.remark + ' OK.</font>';
} else {
str += '<font color="red">' + obj.remark + ' Error.</font>';
}
str += '<br />';
}
document.getElementById('_node_status').innerHTML = str;
var clear_btn = document.getElementById('clear_check_port_btn');
clear_btn.style.display = "inline-block";
btn.disabled = false;
btn.value = '<%:Check%>';
}
}
);
return false;
}
function clear_check_port(btn) {
btn.style.display = 'none';
var s = document.getElementById('_node_status');
s.innerHTML = "";
return false;
}
//]]>
</script>

View File

@@ -1,26 +0,0 @@
<%
local api = require "luci.model.cbi.passwall.api.api"
local console_port = api.uci_get_type("global_haproxy", "console_port", "")
-%>
<p id="_status"></p>
<script type="text/javascript">//<![CDATA[
XHR.poll(3, '<%=api.url("haproxy_status")%>', null,
function(x, result) {
if (x && x.status == 200) {
var _status = document.getElementById('_status');
if (_status) {
if (result) {
_status.innerHTML = '<input type="button" class="btn cbi-button cbi-button-apply" value="<%:Enter interface%>" onclick="openwebui()" />';
} else {
_status.innerHTML = '';
}
}
}
});
function openwebui(){
var url = window.location.hostname + ":<%=console_port%>";
window.open('http://' + url, 'target', '');
}
//]]></script>

View File

@@ -1,16 +0,0 @@
#!/bin/sh /etc/rc.common
START=99
start() {
lua /usr/lib/lua/luci/model/cbi/passwall/server/api/app.lua start
}
stop() {
lua /usr/lib/lua/luci/model/cbi/passwall/server/api/app.lua stop
}
restart() {
stop
start
}

View File

@@ -1,35 +0,0 @@
#!/bin/sh
uci -q batch <<-EOF >/dev/null
set dhcp.@dnsmasq[0].localuse=1
commit dhcp
delete ucitrack.@passwall[-1]
add ucitrack passwall
set ucitrack.@passwall[-1].init=passwall
commit ucitrack
delete firewall.passwall
set firewall.passwall=include
set firewall.passwall.type=script
set firewall.passwall.path=/var/etc/passwall.include
set firewall.passwall.reload=1
commit firewall
delete ucitrack.@passwall_server[-1]
add ucitrack passwall_server
set ucitrack.@passwall_server[-1].init=passwall_server
commit ucitrack
delete firewall.passwall_server
set firewall.passwall_server=include
set firewall.passwall_server.type=script
set firewall.passwall_server.path=/var/etc/passwall_server.include
set firewall.passwall_server.reload=1
commit firewall
set uhttpd.main.max_requests=50
commit uhttpd
EOF
[ ! -s "/etc/config/passwall" ] && cp -f /usr/share/passwall/0_default_config /etc/config/passwall
touch /etc/config/passwall_show >/dev/null 2>&1
rm -f /tmp/luci-indexcache
rm -rf /tmp/luci-modulecache/
killall -HUP rpcd 2>/dev/null
exit 0

File diff suppressed because it is too large Load Diff

View File

@@ -1,311 +0,0 @@
#!/bin/sh
stretch() {
#zhenduiluanshezhiDNSderen
local dnsmasq_server=$(uci -q get dhcp.@dnsmasq[0].server)
local dnsmasq_noresolv=$(uci -q get dhcp.@dnsmasq[0].noresolv)
local _flag
for server in $dnsmasq_server; do
[ -z "$(echo $server | grep '\/')" ] && _flag=1
done
[ -z "$_flag" ] && [ "$dnsmasq_noresolv" = "1" ] && {
uci -q delete dhcp.@dnsmasq[0].noresolv
uci -q set dhcp.@dnsmasq[0].resolvfile="$RESOLVFILE"
uci commit dhcp
}
}
backup_servers() {
DNSMASQ_DNS=$(uci show dhcp | grep "@dnsmasq" | grep ".server=" | awk -F '=' '{print $2}' | sed "s/'//g" | tr ' ' ',')
if [ -n "${DNSMASQ_DNS}" ]; then
uci -q set $CONFIG.@global[0].dnsmasq_servers="${DNSMASQ_DNS}"
uci commit $CONFIG
fi
}
restore_servers() {
OLD_SERVER=$(uci -q get $CONFIG.@global[0].dnsmasq_servers | tr "," " ")
for server in $OLD_SERVER; do
uci -q del_list dhcp.@dnsmasq[0].server=$server
uci -q add_list dhcp.@dnsmasq[0].server=$server
done
uci commit dhcp
uci -q delete $CONFIG.@global[0].dnsmasq_servers
uci commit $CONFIG
}
logic_restart() {
local no_log
eval_set_val $@
_LOG_FILE=$LOG_FILE
[ -n "$no_log" ] && LOG_FILE="/dev/null"
if [ -f "$TMP_PATH/default_DNS" ]; then
backup_servers
#sed -i "/list server/d" /etc/config/dhcp >/dev/null 2>&1
for server in $(uci -q get dhcp.@dnsmasq[0].server); do
[ -n "$(echo $server | grep '\/')" ] || uci -q del_list dhcp.@dnsmasq[0].server="$server"
done
/etc/init.d/dnsmasq restart >/dev/null 2>&1
restore_servers
else
/etc/init.d/dnsmasq restart >/dev/null 2>&1
fi
echolog "重启 dnsmasq 服务"
LOG_FILE=${_LOG_FILE}
}
restart() {
local no_log
eval_set_val $@
_LOG_FILE=$LOG_FILE
[ -n "$no_log" ] && LOG_FILE="/dev/null"
/etc/init.d/dnsmasq restart >/dev/null 2>&1
echolog "重启 dnsmasq 服务"
LOG_FILE=${_LOG_FILE}
}
gen_items() {
local ipsets dnss outf ipsetoutf
eval_set_val $@
awk -v ipsets="${ipsets}" -v dnss="${dnss}" -v outf="${outf}" -v ipsetoutf="${ipsetoutf}" '
BEGIN {
if(outf == "") outf="/dev/stdout";
if(ipsetoutf == "") ipsetoutf=outf;
split(dnss, dns, ","); setdns=length(dns)>0; setlist=length(ipsets)>0;
if(setdns) for(i in dns) if(length(dns[i])==0) delete dns[i];
fail=1;
}
! /^$/&&!/^#/ {
fail=0
if(setdns) for(i in dns) printf("server=/.%s/%s\n", $0, dns[i]) >>outf;
if(setlist) printf("ipset=/.%s/%s\n", $0, ipsets) >>ipsetoutf;
}
END {fflush(outf); close(outf); fflush(ipsetoutf); close(ipsetoutf); exit(fail);}
'
}
gen_address_items() {
local address outf
eval_set_val $@
awk -v address="${address}" -v outf="${outf}" '
BEGIN {
if(outf == "") outf="/dev/stdout";
if(address == "") address="0.0.0.0,::";
split(address, ad, ","); setad=length(ad)>0;
if(setad) for(i in ad) if(length(ad[i])==0) delete ad[i];
fail=1;
}
! /^$/&&!/^#/ {
fail=0
if(setad) for(i in ad) printf("address=/.%s/%s\n", $0, ad[i]) >>outf;
}
END {fflush(outf); close(outf); exit(fail);}
'
}
ipset_merge() {
awk '{gsub(/ipset=\//,""); gsub(/\//," ");key=$1;value=$2;if (sum[key] != "") {sum[key]=sum[key]","value} else {sum[key]=sum[key]value}} END{for(i in sum) print "ipset=/"i"/"sum[i]}' "${1}/ipset.conf" > "${1}/ipset.conf2"
mv -f "${1}/ipset.conf2" "${1}/ipset.conf"
}
add() {
local fwd_dns item servers msg
local DNS_MODE TMP_DNSMASQ_PATH DNSMASQ_CONF_FILE DEFAULT_DNS LOCAL_DNS TUN_DNS REMOTE_FAKEDNS CHINADNS_DNS TCP_NODE PROXY_MODE NO_LOGIC_LOG NO_PROXY_IPV6
eval_set_val $@
_LOG_FILE=$LOG_FILE
[ -n "$NO_LOGIC_LOG" ] && LOG_FILE="/dev/null"
global=$(echo "${PROXY_MODE}" | grep "global")
returnhome=$(echo "${PROXY_MODE}" | grep "returnhome")
chnlist=$(echo "${PROXY_MODE}" | grep "chnroute")
gfwlist=$(echo "${PROXY_MODE}" | grep "gfwlist")
mkdir -p "${TMP_DNSMASQ_PATH}" "${DNSMASQ_PATH}" "/tmp/dnsmasq.d"
count_hosts_str="!"
#屏蔽列表
[ -s "${RULES_PATH}/block_host" ] && {
cat "${RULES_PATH}/block_host" | tr -s '\n' | grep -v "^#" | sort -u | gen_address_items address="0.0.0.0" outf="${TMP_DNSMASQ_PATH}/00-block_host.conf"
}
#始终用国内DNS解析节点域名
fwd_dns="${LOCAL_DNS}"
servers=$(uci show "${CONFIG}" | grep ".address=" | cut -d "'" -f 2)
hosts_foreach "servers" host_from_url | grep '[a-zA-Z]$' | sort -u | gen_items ipsets="vpsiplist,vpsiplist6" dnss="${fwd_dns}" outf="${TMP_DNSMASQ_PATH}/10-vpsiplist_host.conf" ipsetoutf="${TMP_DNSMASQ_PATH}/ipset.conf"
echolog " - [$?]节点列表中的域名(vpsiplist)${fwd_dns:-默认}"
#始终用国内DNS解析直连白名单列表
[ -s "${RULES_PATH}/direct_host" ] && {
fwd_dns="${LOCAL_DNS}"
#[ -n "$CHINADNS_DNS" ] && unset fwd_dns
cat "${RULES_PATH}/direct_host" | tr -s '\n' | grep -v "^#" | sort -u | gen_items ipsets="whitelist,whitelist6" dnss="${fwd_dns}" outf="${TMP_DNSMASQ_PATH}/11-direct_host.conf" ipsetoutf="${TMP_DNSMASQ_PATH}/ipset.conf"
echolog " - [$?]域名白名单(whitelist)${fwd_dns:-默认}"
}
subscribe_list=""
for item in $(get_enabled_anonymous_secs "@subscribe_list"); do
host=$(host_from_url "$(config_n_get ${item} url)")
subscribe_list="${subscribe_list}\n${host}"
done
[ -n "$subscribe_list" ] && {
if [ "$(config_t_get global_subscribe subscribe_proxy 0)" = "0" ]; then
#如果没有开启通过代理订阅
fwd_dns="${LOCAL_DNS}"
echo -e "$subscribe_list" | sort -u | gen_items ipsets="whitelist,whitelist6" dnss="${fwd_dns}" outf="${TMP_DNSMASQ_PATH}/12-subscribe.conf" ipsetoutf="${TMP_DNSMASQ_PATH}/ipset.conf"
echolog " - [$?]节点订阅域名(whitelist)${fwd_dns:-默认}"
else
#如果开启了通过代理订阅
fwd_dns="${TUN_DNS}"
local ipset_flag="blacklist,blacklist6"
if [ "${NO_PROXY_IPV6}" = "1" ]; then
ipset_flag="blacklist"
echo -e "$subscribe_list" | sort -u | gen_address_items address="::" outf="${TMP_DNSMASQ_PATH}/91-subscribe-noipv6.conf"
fi
[ -n "${REMOTE_FAKEDNS}" ] && unset ipset_flag
echo -e "$subscribe_list" | sort -u | gen_items ipsets="${ipset_flag}" dnss="${fwd_dns}" outf="${TMP_DNSMASQ_PATH}/91-subscribe.conf" ipsetoutf="${TMP_DNSMASQ_PATH}/ipset.conf"
echolog " - [$?]节点订阅域名(blacklist)${fwd_dns:-默认}"
fi
}
#始终使用远程DNS解析代理黑名单列表
[ -s "${RULES_PATH}/proxy_host" ] && {
local ipset_flag="blacklist,blacklist6"
if [ "${NO_PROXY_IPV6}" = "1" ]; then
ipset_flag="blacklist"
cat "${RULES_PATH}/proxy_host" | tr -s '\n' | grep -v "^#" | sort -u | gen_address_items address="::" outf="${TMP_DNSMASQ_PATH}/97-proxy_host-noipv6.conf"
fi
fwd_dns="${TUN_DNS}"
[ -n "${REMOTE_FAKEDNS}" ] && unset ipset_flag
cat "${RULES_PATH}/proxy_host" | tr -s '\n' | grep -v "^#" | sort -u | gen_items ipsets="${ipset_flag}" dnss="${fwd_dns}" outf="${TMP_DNSMASQ_PATH}/97-proxy_host.conf" ipsetoutf="${TMP_DNSMASQ_PATH}/ipset.conf"
echolog " - [$?]代理域名表(blacklist)${fwd_dns:-默认}"
}
#分流规则
[ "$(config_n_get $TCP_NODE protocol)" = "_shunt" ] && {
fwd_dns="${TUN_DNS}"
msg_dns="${fwd_dns}"
local default_node_id=$(config_n_get $TCP_NODE default_node _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_id=$(config_n_get $TCP_NODE ${shunt_id} nil)
[ "$shunt_node_id" = "nil" ] && continue
[ "$shunt_node_id" = "_default" ] && shunt_node_id=$default_node_id
[ "$shunt_node_id" = "_blackhole" ] && continue
local str=$(echo -n $(config_n_get $shunt_id domain_list | grep -v 'regexp:\|geosite:\|ext:' | sed 's/domain:\|full:\|//g' | tr -s "\r\n" "\n" | sort -u) | sed "s/ /|/g")
[ -n "$str" ] && count_hosts_str="${count_hosts_str}|${str}"
[ "$shunt_node_id" = "_direct" ] && {
[ -n "$str" ] && echo $str | sed "s/|/\n/g" | gen_items ipsets="whitelist,whitelist6" "${LOCAL_DNS}" "${TMP_DNSMASQ_PATH}/13-shunt_host.conf"
msg_dns="${LOCAL_DNS}"
continue
}
local shunt_node=$(config_n_get $shunt_node_id address nil)
[ "$shunt_node" = "nil" ] && continue
[ -n "$str" ] && {
local ipset_flag="shuntlist,shuntlist6"
if [ "${NO_PROXY_IPV6}" = "1" ]; then
ipset_flag="shuntlist"
echo $str | sed "s/|/\n/g" | gen_address_items address="::" outf="${TMP_DNSMASQ_PATH}/98-shunt_host-noipv6.conf"
fi
[ -n "${REMOTE_FAKEDNS}" ] && unset ipset_flag
echo $str | sed "s/|/\n/g" | gen_items ipsets="${ipset_flag}" dnss="${fwd_dns}" outf="${TMP_DNSMASQ_PATH}/98-shunt_host.conf" ipsetoutf="${TMP_DNSMASQ_PATH}/ipset.conf"
msg_dns="${fwd_dns}"
}
done
echolog " - [$?]V2ray/Xray分流规则(shuntlist)${msg_dns:-默认}"
}
[ -s "${RULES_PATH}/direct_host" ] && direct_hosts_str="$(echo -n $(cat ${RULES_PATH}/direct_host | tr -s '\n' | grep -v "^#" | sort -u) | sed "s/ /|/g")"
[ -s "${RULES_PATH}/proxy_host" ] && proxy_hosts_str="$(echo -n $(cat ${RULES_PATH}/proxy_host | tr -s '\n' | grep -v "^#" | sort -u) | sed "s/ /|/g")"
[ -n "$direct_hosts_str" ] && count_hosts_str="${count_hosts_str}|${direct_hosts_str}"
[ -n "$proxy_hosts_str" ] && count_hosts_str="${count_hosts_str}|${proxy_hosts_str}"
#如果没有使用回国模式
if [ -z "${returnhome}" ]; then
# GFW 模式
[ -s "${RULES_PATH}/gfwlist" ] && {
grep -v -E "$count_hosts_str" "${RULES_PATH}/gfwlist" > "${TMP_PATH}/gfwlist"
local ipset_flag="gfwlist,gfwlist6"
if [ "${NO_PROXY_IPV6}" = "1" ]; then
ipset_flag="gfwlist"
sort -u "${TMP_PATH}/gfwlist" | gen_address_items address="::" outf="${TMP_DNSMASQ_PATH}/99-gfwlist-noipv6.conf"
fi
fwd_dns="${TUN_DNS}"
[ -n "$CHINADNS_DNS" ] && unset fwd_dns
[ -n "${REMOTE_FAKEDNS}" ] && unset ipset_flag
sort -u "${TMP_PATH}/gfwlist" | gen_items ipsets="${ipset_flag}" dnss="${fwd_dns}" outf="${TMP_DNSMASQ_PATH}/99-gfwlist.conf" ipsetoutf="${TMP_DNSMASQ_PATH}/ipset.conf"
echolog " - [$?]防火墙域名表(gfwlist)${fwd_dns:-默认}"
rm -f "${TMP_PATH}/gfwlist"
}
# 中国列表以外 模式
[ -n "${CHINADNS_DNS}" ] && {
fwd_dns="${LOCAL_DNS}"
[ -n "$CHINADNS_DNS" ] && unset fwd_dns
[ -s "${RULES_PATH}/chnlist" ] && {
grep -v -E "$count_hosts_str" "${RULES_PATH}/chnlist" | gen_items ipsets="chnroute,chnroute6" dnss="${fwd_dns}" outf="${TMP_DNSMASQ_PATH}/19-chinalist_host.conf" ipsetoutf="${TMP_DNSMASQ_PATH}/ipset.conf"
echolog " - [$?]中国域名表(chnroute)${fwd_dns:-默认}"
}
}
else
#回国模式
[ -s "${RULES_PATH}/chnlist" ] && {
grep -v -E "$count_hosts_str" "${RULES_PATH}/chnlist" > "${TMP_PATH}/chnlist"
local ipset_flag="chnroute,chnroute6"
if [ "${NO_PROXY_IPV6}" = "1" ]; then
ipset_flag="chnroute"
sort -u "${TMP_PATH}/chnlist" | gen_address_items address="::" outf="${TMP_DNSMASQ_PATH}/99-chinalist_host-noipv6.conf"
fi
fwd_dns="${TUN_DNS}"
[ -n "${REMOTE_FAKEDNS}" ] && unset ipset_flag
sort -u "${TMP_PATH}/chnlist" | gen_items ipsets="${ipset_flag}" dnss="${fwd_dns}" outf="${TMP_DNSMASQ_PATH}/99-chinalist_host.conf" ipsetoutf="${TMP_DNSMASQ_PATH}/ipset.conf"
echolog " - [$?]中国域名表(chnroute)${fwd_dns:-默认}"
rm -f "${TMP_PATH}/chnlist"
}
fi
ipset_merge ${TMP_DNSMASQ_PATH}
echo "conf-dir=${TMP_DNSMASQ_PATH}" > $DNSMASQ_CONF_FILE
[ -n "${CHINADNS_DNS}" ] && {
echo "${DEFAULT_DNS}" > $TMP_PATH/default_DNS
cat <<-EOF >> $DNSMASQ_CONF_FILE
server=${CHINADNS_DNS}
all-servers
no-poll
no-resolv
EOF
echolog " - [$?]以上所列以外及默认(ChinaDNS-NG)${CHINADNS_DNS}"
}
echolog " - PassWall必须依赖于Dnsmasq如果你自行配置了错误的DNS流程将会导致域名(直连/代理域名)分流失效!!!"
LOG_FILE=${_LOG_FILE}
}
del() {
rm -rf /tmp/dnsmasq.d/dnsmasq-$CONFIG.conf
rm -rf $DNSMASQ_PATH/dnsmasq-$CONFIG.conf
rm -rf $TMP_DNSMASQ_PATH
}
arg1=$1
shift
case $arg1 in
stretch)
stretch $@
;;
add)
add $@
;;
del)
del $@
;;
restart)
restart $@
;;
logic_restart)
logic_restart $@
;;
*) ;;
esac

View File

@@ -1,225 +0,0 @@
#!/bin/sh
restart() {
local no_log
eval_set_val $@
_LOG_FILE=$LOG_FILE
[ -n "$no_log" ] && LOG_FILE="/dev/null"
rm -rf /tmp/smartdns.cache
/etc/init.d/smartdns reload >/dev/null 2>&1
/etc/init.d/dnsmasq restart >/dev/null 2>&1
LOG_FILE=${_LOG_FILE}
}
gen_items() {
local ipsets group address speed_check_mode outf
eval_set_val $@
awk -v ipsets="${ipsets}" -v group="${group}" -v speed_check_mode="${speed_check_mode}" -v address="${address}" -v outf="${outf}" '
BEGIN {
if(outf == "") outf="/dev/stdout";
if(group != "") group=" -n " group;
if(ipsets != "") ipsets=" -p " ipsets;
if(speed_check_mode != "") speed_check_mode=" -c " speed_check_mode;
if(address != "") address=" -a " address;
fail=1;
}
! /^$/&&!/^#/ {
fail=0
printf("domain-rules /%s/ %s%s%s%s\n", $0, group, ipsets, address, speed_check_mode) >>outf;
}
END {fflush(outf); close(outf); exit(fail);}
'
}
gen_address_items() {
local address outf
eval_set_val $@
awk -v address="${address}" -v outf="${outf}" '
BEGIN {
if(outf == "") outf="/dev/stdout";
setaddress=length(address)>0;
fail=1;
}
! /^$/&&!/^#/ {
fail=0
if(setaddress) printf("address /%s/%s\n", $0, address) >>outf;
}
END {fflush(outf); close(outf); exit(fail);}
'
}
add() {
local fwd_dns fwd_group item servers msg
local DNS_MODE SMARTDNS_CONF DNSMASQ_CONF_FILE DEFAULT_DNS LOCAL_GROUP REMOTE_GROUP REMOTE_FAKEDNS TUN_DNS TCP_NODE PROXY_MODE NO_LOGIC_LOG NO_PROXY_IPV6
eval_set_val $@
_LOG_FILE=$LOG_FILE
[ -n "$NO_LOGIC_LOG" ] && LOG_FILE="/dev/null"
global=$(echo "${PROXY_MODE}" | grep "global")
returnhome=$(echo "${PROXY_MODE}" | grep "returnhome")
chnlist=$(echo "${PROXY_MODE}" | grep "chnroute")
gfwlist=$(echo "${PROXY_MODE}" | grep "gfwlist")
touch ${SMARTDNS_CONF}
count_hosts_str="!"
[ -z "${REMOTE_GROUP}" ] && {
REMOTE_GROUP="${CONFIG}_proxy"
[ -n "${TUN_DNS}" ] && TUN_DNS="$(echo ${TUN_DNS} | sed 's/#/:/g')"
sed -i "/passwall/d" /etc/smartdns/custom.conf >/dev/null 2>&1
echo "server ${TUN_DNS} -group ${REMOTE_GROUP} -exclude-default-group" >> ${SMARTDNS_CONF}
}
#屏蔽列表
[ -s "${RULES_PATH}/block_host" ] && {
cat "${RULES_PATH}/block_host" | tr -s '\n' | grep -v "^#" | sort -u | gen_address_items address="-" outf="${SMARTDNS_CONF}"
}
#始终用国内DNS解析节点域名
servers=$(uci show "${CONFIG}" | grep ".address=" | cut -d "'" -f 2)
hosts_foreach "servers" host_from_url | grep '[a-zA-Z]$' | sort -u | gen_items ipsets="#4:vpsiplist,#6:vpsiplist6" group="${LOCAL_GROUP}" outf="${SMARTDNS_CONF}"
echolog " - [$?]节点列表中的域名(vpsiplist)使用分组:${LOCAL_GROUP:-默认}"
#始终用国内DNS解析直连白名单列表
[ -s "${RULES_PATH}/direct_host" ] && {
cat "${RULES_PATH}/direct_host" | tr -s '\n' | grep -v "^#" | sort -u | gen_items ipsets="#4:whitelist,#6:whitelist6" group="${LOCAL_GROUP}" outf="${SMARTDNS_CONF}"
echolog " - [$?]域名白名单(whitelist)使用分组:${LOCAL_GROUP:-默认}"
}
subscribe_list=""
for item in $(get_enabled_anonymous_secs "@subscribe_list"); do
host=$(host_from_url "$(config_n_get ${item} url)")
subscribe_list="${subscribe_list}\n${host}"
done
[ -n "$subscribe_list" ] && {
if [ "$(config_t_get global_subscribe subscribe_proxy 0)" = "0" ]; then
#如果没有开启通过代理订阅
echo -e "$subscribe_list" | sort -u | gen_items ipsets="#4:whitelist,#6:whitelist6" group="${LOCAL_GROUP}" outf="${SMARTDNS_CONF}"
echolog " - [$?]节点订阅域名(whitelist)使用分组:${LOCAL_GROUP:-默认}"
else
#如果开启了通过代理订阅
local ipset_flag="#4:blacklist,#6:blacklist6"
if [ "${NO_PROXY_IPV6}" = "1" ]; then
ipset_flag="#4:blacklist"
address="#6"
fi
[ -n "${REMOTE_FAKEDNS}" ] && unset ipset_flag
echo -e "$subscribe_list" | sort -u | gen_items ipsets="${ipset_flag}" group="${REMOTE_GROUP}" address="${address}" speed_check_mode="none" outf="${SMARTDNS_CONF}"
echolog " - [$?]节点订阅域名(blacklist)使用分组:${REMOTE_GROUP}"
fi
}
#始终使用远程DNS解析代理黑名单列表
[ -s "${RULES_PATH}/proxy_host" ] && {
local ipset_flag="#4:blacklist,#6:blacklist6"
if [ "${NO_PROXY_IPV6}" = "1" ]; then
ipset_flag="#4:blacklist"
address="#6"
fi
[ -n "${REMOTE_FAKEDNS}" ] && unset ipset_flag
cat "${RULES_PATH}/proxy_host" | tr -s '\n' | grep -v "^#" | sort -u | gen_items ipsets="${ipset_flag}" group="${REMOTE_GROUP}" address="${address}" speed_check_mode="none" outf="${SMARTDNS_CONF}"
echolog " - [$?]代理域名表(blacklist)使用分组:${REMOTE_GROUP}"
}
#分流规则
[ "$(config_n_get $TCP_NODE protocol)" = "_shunt" ] && {
local default_node_id=$(config_n_get $TCP_NODE default_node _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_id=$(config_n_get $TCP_NODE ${shunt_id} nil)
[ "$shunt_node_id" = "nil" ] && continue
[ "$shunt_node_id" = "_default" ] && shunt_node_id=$default_node_id
[ "$shunt_node_id" = "_blackhole" ] && continue
local str=$(echo -n $(config_n_get $shunt_id domain_list | grep -v 'regexp:\|geosite:\|ext:' | sed 's/domain:\|full:\|//g' | tr -s "\r\n" "\n" | sort -u) | sed "s/ /|/g")
[ -n "$str" ] && count_hosts_str="${count_hosts_str}|${str}"
[ "$shunt_node_id" = "_direct" ] && {
[ -n "$str" ] && echo $str | sed "s/|/\n/g" | gen_items ipsets="#4:whitelist,#6:whitelist6" group="${LOCAL_GROUP}" outf="${SMARTDNS_CONF}"
msg_dns="${LOCAL_GROUP}"
continue
}
local shunt_node=$(config_n_get $shunt_node_id address nil)
[ "$shunt_node" = "nil" ] && continue
[ -n "$str" ] && {
local ipset_flag="#4:shuntlist,#6:shuntlist6"
if [ "${NO_PROXY_IPV6}" = "1" ]; then
ipset_flag="#4:shuntlist"
address="#6"
fi
[ -n "${REMOTE_FAKEDNS}" ] && unset ipset_flag
echo $str | sed "s/|/\n/g" | gen_items ipsets="${ipset_flag}" group="${REMOTE_GROUP}" address="${address}" speed_check_mode="none" outf="${SMARTDNS_CONF}"
msg_dns="${REMOTE_GROUP}"
}
done
echolog " - [$?]V2ray/Xray分流规则(shuntlist)${msg_dns:-默认}"
}
[ -s "${RULES_PATH}/direct_host" ] && direct_hosts_str="$(echo -n $(cat ${RULES_PATH}/direct_host | tr -s '\n' | grep -v "^#" | sort -u) | sed "s/ /|/g")"
[ -s "${RULES_PATH}/proxy_host" ] && proxy_hosts_str="$(echo -n $(cat ${RULES_PATH}/proxy_host | tr -s '\n' | grep -v "^#" | sort -u) | sed "s/ /|/g")"
[ -n "$direct_hosts_str" ] && count_hosts_str="${count_hosts_str}|${direct_hosts_str}"
[ -n "$proxy_hosts_str" ] && count_hosts_str="${count_hosts_str}|${proxy_hosts_str}"
#如果没有使用回国模式
if [ -z "${returnhome}" ]; then
# GFW 模式
[ -s "${RULES_PATH}/gfwlist" ] && {
grep -v -E "$count_hosts_str" "${RULES_PATH}/gfwlist" > "${TMP_PATH}/gfwlist"
local ipset_flag="#4:gfwlist,#6:gfwlist6"
if [ "${NO_PROXY_IPV6}" = "1" ]; then
ipset_flag="#4:gfwlist"
address="#6"
fi
[ -n "${REMOTE_FAKEDNS}" ] && unset ipset_flag
sort -u "${TMP_PATH}/gfwlist" | gen_items ipsets="${ipset_flag}" group="${REMOTE_GROUP}" address="${address}" speed_check_mode="none" outf="${SMARTDNS_CONF}"
echolog " - [$?]防火墙域名表(gfwlist)使用分组:${REMOTE_GROUP}"
rm -f "${TMP_PATH}/gfwlist"
}
# 中国列表以外 模式
[ -s "${RULES_PATH}/chnlist" ] && [ -n "${chnlist}" ] && {
grep -v -E "$count_hosts_str" "${RULES_PATH}/chnlist" | gen_items ipsets="#4:chnroute,#6:chnroute6" group="${LOCAL_GROUP}" outf="${SMARTDNS_CONF}"
echolog " - [$?]中国域名表(chnroute)使用分组:${LOCAL_GROUP:-默认}"
}
else
#回国模式
[ -s "${RULES_PATH}/chnlist" ] && {
grep -v -E "$count_hosts_str" "${RULES_PATH}/chnlist" > "${TMP_PATH}/chnlist"
local ipset_flag="#4:chnroute,#6:chnroute6"
if [ "${NO_PROXY_IPV6}" = "1" ]; then
ipset_flag="#4:chnroute"
address="#6"
fi
[ -n "${REMOTE_FAKEDNS}" ] && unset ipset_flag
sort -u "${TMP_PATH}/chnlist" | gen_items ipsets="${ipset_flag}" group="${REMOTE_GROUP}" address="${address}" speed_check_mode="none" outf="${SMARTDNS_CONF}"
echolog " - [$?]中国域名表(chnroute)使用分组:${REMOTE_GROUP}"
rm -f "${TMP_PATH}/chnlist"
}
fi
echo "conf-file ${SMARTDNS_CONF}" >> /etc/smartdns/custom.conf
echolog " - 请让SmartDNS作为Dnsmasq的上游或重定向"
LOG_FILE=${_LOG_FILE}
}
del() {
rm -rf /tmp/etc/smartdns/passwall.conf
sed -i "/passwall/d" /etc/smartdns/custom.conf >/dev/null 2>&1
rm -rf /tmp/smartdns.cache
/etc/init.d/smartdns reload >/dev/null 2>&1
}
arg1=$1
shift
case $arg1 in
add)
add $@
;;
del)
del $@
;;
restart)
restart $@
;;
*) ;;
esac

File diff suppressed because it is too large Load Diff

View File

@@ -1,98 +0,0 @@
#!/bin/sh
CONFIG=passwall
TMP_PATH=/tmp/etc/$CONFIG
TMP_BIN_PATH=$TMP_PATH/bin
TMP_SCRIPT_FUNC_PATH=$TMP_PATH/script_func
TMP_ID_PATH=$TMP_PATH/id
LOCK_FILE_DIR=/tmp/lock
LOCK_FILE=${LOCK_FILE_DIR}/${CONFIG}_script.lock
config_n_get() {
local ret=$(uci -q get $CONFIG.$1.$2 2>/dev/null)
echo ${ret:=$3}
}
config_t_get() {
local index=0
[ -n "$4" ] && index=$4
local ret=$(uci -q get $CONFIG.@$1[$index].$2 2>/dev/null)
echo ${ret:=$3}
}
ENABLED=$(config_t_get global enabled 0)
[ "$ENABLED" != 1 ] && return 1
ENABLED=$(config_t_get global_delay start_daemon 0)
[ "$ENABLED" != 1 ] && return 1
sleep 58s
while [ "$ENABLED" -eq 1 ]; do
[ -f "$LOCK_FILE" ] && {
sleep 6s
continue
}
touch $LOCK_FILE
#TCP
[ -f "$TMP_ID_PATH/TCP" ] && {
TCP_NODE=$(cat $TMP_ID_PATH/TCP)
if [ "$TCP_NODE" != "nil" ]; then
icount=$(pgrep -af "$TMP_BIN_PATH.*(tcp|TCP)" | grep -v -E 'acl/|acl_' | wc -l)
if [ $icount = 0 ]; then
/etc/init.d/$CONFIG restart
exit 0
fi
fi
}
#udp
[ -f "$TMP_ID_PATH/UDP" ] && {
UDP_NODE=$(cat $TMP_ID_PATH/UDP)
if [ "$UDP_NODE" != "nil" ]; then
[ "$UDP_NODE" == "tcp" ] && UDP_NODE=$TCP_NODE
icount=$(pgrep -af "$TMP_BIN_PATH.*(udp|UDP)" | grep -v -E 'acl/|acl_' | wc -l)
if [ $icount = 0 ]; then
/etc/init.d/$CONFIG restart
exit 0
fi
fi
}
#dns
dns_mode=$(config_t_get global dns_mode)
if [ "$dns_mode" == "pdnsd" ] || [ "$dns_mode" == "dns2socks" ] || [ "$dns_mode" == "v2ray" ] || [ "$dns_mode" == "xray" ]; then
icount=$(netstat -apn | grep 7913 | wc -l)
if [ $icount = 0 ]; then
/etc/init.d/$CONFIG restart
exit 0
fi
fi
[ -f "$TMP_BIN_PATH/chinadns-ng" ] && {
if ! pgrep -x "$TMP_BIN_PATH/chinadns-ng" > /dev/null 2>&1; then
/etc/init.d/$CONFIG restart
exit 0
fi
}
#haproxy
use_haproxy=$(config_t_get global_haproxy balancing_enable 0)
if [ $use_haproxy -gt 0 ]; then
if ! pgrep -x "$TMP_BIN_PATH/haproxy" > /dev/null 2>&1; then
/etc/init.d/$CONFIG restart
exit 0
fi
fi
#socks
for filename in $(ls ${TMP_SCRIPT_FUNC_PATH} | grep "SOCKS_*"); do
cfgid=$(echo $filename | awk -F 'SOCKS_' '{print $2}')
icount=$(pgrep -af "$TMP_BIN_PATH.*$cfgid" | grep -i 'socks' | wc -l)
if [ $icount = 0 ]; then
cmd=$(cat ${TMP_SCRIPT_FUNC_PATH}/${filename})
/usr/share/${CONFIG}/app.sh ${cmd}
fi
done
rm -f $LOCK_FILE
sleep 58s
done

View File

@@ -1,401 +0,0 @@
#!/usr/bin/lua
require 'nixio'
require 'luci.sys'
local luci = luci
local ucic = luci.model.uci.cursor()
local jsonc = require "luci.jsonc"
local name = 'passwall'
local api = require ("luci.model.cbi." .. name .. ".api.api")
local arg1 = arg[1]
local rule_path = "/usr/share/" .. name .. "/rules"
local reboot = 0
local gfwlist_update = 0
local chnroute_update = 0
local chnroute6_update = 0
local chnlist_update = 0
local geoip_update = 0
local geosite_update = 0
-- match comments/title/whitelist/ip address/excluded_domain
local comment_pattern = "^[!\\[@]+"
local ip_pattern = "^%d+%.%d+%.%d+%.%d+"
local ip4_ipset_pattern = "^%d+%.%d+%.%d+%.%d+[%/][%d]+$"
local ip6_ipset_pattern = ":-[%x]+%:+[%x]-[%/][%d]+$"
local domain_pattern = "([%w%-%_]+%.[%w%.%-%_]+)[%/%*]*"
local excluded_domain = {"apple.com","sina.cn","sina.com.cn","baidu.com","byr.cn","jlike.com","weibo.com","zhongsou.com","youdao.com","sogou.com","so.com","soso.com","aliyun.com","taobao.com","jd.com","qq.com","bing.com"}
local gfwlist_url = ucic:get(name, "@global_rules[0]", "gfwlist_url") or {"https://cdn.jsdelivr.net/gh/Loyalsoldier/v2ray-rules-dat@release/gfw.txt"}
local chnroute_url = ucic:get(name, "@global_rules[0]", "chnroute_url") or {"https://ispip.clang.cn/all_cn.txt"}
local chnroute6_url = ucic:get(name, "@global_rules[0]", "chnroute6_url") or {"https://ispip.clang.cn/all_cn_ipv6.txt"}
local chnlist_url = ucic:get(name, "@global_rules[0]", "chnlist_url") or {"https://cdn.jsdelivr.net/gh/felixonmars/dnsmasq-china-list/accelerated-domains.china.conf","https://cdn.jsdelivr.net/gh/felixonmars/dnsmasq-china-list/apple.china.conf","https://cdn.jsdelivr.net/gh/felixonmars/dnsmasq-china-list/google.china.conf"}
local geoip_api = "https://api.github.com/repos/Loyalsoldier/v2ray-rules-dat/releases/latest"
local geosite_api = "https://api.github.com/repos/Loyalsoldier/v2ray-rules-dat/releases/latest"
local v2ray_asset_location = ucic:get_first(name, 'global_rules', "v2ray_location_asset", "/usr/share/v2ray/")
local log = function(...)
if arg1 then
local result = os.date("%Y-%m-%d %H:%M:%S: ") .. table.concat({...}, " ")
if arg1 == "log" then
local f, err = io.open("/tmp/log/passwall.log", "a")
if f and err == nil then
f:write(result .. "\n")
f:close()
end
elseif arg1 == "print" then
print(result)
end
end
end
-- trim
local function trim(text)
if not text or text == "" then return "" end
return (string.gsub(text, "^%s*(.-)%s*$", "%1"))
end
-- curl
local function curl(url, file)
local cmd = "curl -skL -w %{http_code} --retry 3 --connect-timeout 3 '" .. url .. "'"
if file then
cmd = cmd .. " -o " .. file
end
local stdout = luci.sys.exec(cmd)
if file then
return tonumber(trim(stdout))
else
return trim(stdout)
end
end
--check excluded domain
local function check_excluded_domain(value)
for k,v in ipairs(excluded_domain) do
if value:find(v) then
return true
end
end
end
local function line_count(file_path)
local num = 0
for _ in io.lines(file_path) do
num = num + 1
end
return num;
end
--fetch rule
local function fetch_rule(rule_name,rule_type,url,exclude_domain)
local sret = 200
local sret_tmp = 0
local domains = {}
local file_tmp = "/tmp/" ..rule_name.. "_tmp"
local download_file_tmp = "/tmp/" ..rule_name.. "_dl"
local unsort_file_tmp = "/tmp/" ..rule_name.. "_unsort"
log(rule_name.. " 开始更新...")
for k,v in ipairs(url) do
sret_tmp = curl(v, download_file_tmp..k)
if sret_tmp == 200 then
if rule_name == "gfwlist" then
local domains = {}
local gfwlist = io.open(download_file_tmp..k, "r")
local decode = api.base64Decode(gfwlist:read("*all"))
gfwlist:close()
gfwlist = io.open(download_file_tmp..k, "w")
gfwlist:write(decode)
gfwlist:close()
end
if rule_type == "domain" and exclude_domain == true then
for line in io.lines(download_file_tmp..k) do
if not (string.find(line, comment_pattern) or string.find(line, ip_pattern) or check_excluded_domain(line)) then
local start, finish, match = string.find(line, domain_pattern)
if (start) then
domains[match] = true
end
end
end
elseif rule_type == "domain" then
for line in io.lines(download_file_tmp..k) do
if not (string.find(line, comment_pattern) or string.find(line, ip_pattern)) then
local start, finish, match = string.find(line, domain_pattern)
if (start) then
domains[match] = true
end
end
end
elseif rule_type == "ip4" then
local out = io.open(unsort_file_tmp, "a")
for line in io.lines(download_file_tmp..k) do
local start, finish, match = string.find(line, ip4_ipset_pattern)
if (start) then
out:write(string.format("%s\n", line))
end
end
out:close()
elseif rule_type == "ip6" then
local out = io.open(unsort_file_tmp, "a")
for line in io.lines(download_file_tmp..k) do
local start, finish, match = string.find(line, ip6_ipset_pattern)
if (start) then
out:write(string.format("%s\n", line))
end
end
out:close()
end
os.remove(download_file_tmp..k)
else
sret = 0
log(rule_name.. "" ..k.. "条规则:" ..v.. "下载失败!")
end
end
if sret == 200 then
if rule_type == "domain" then
local out = io.open(unsort_file_tmp, "w")
for k,v in pairs(domains) do
out:write(string.format("%s\n", k))
end
out:close()
end
luci.sys.call("cat " ..unsort_file_tmp.. " | sort -u > "..file_tmp)
os.remove(unsort_file_tmp)
end
if sret == 200 then
local old_md5 = luci.sys.exec("echo -n $(md5sum " .. rule_path .. "/" ..rule_name.. " | awk '{print $1}')")
local new_md5 = luci.sys.exec("echo -n $([ -f '" ..file_tmp.. "' ] && md5sum " ..file_tmp.." | awk '{print $1}')")
if old_md5 ~= new_md5 then
local count = line_count(file_tmp)
luci.sys.exec("mv -f "..file_tmp .. " " ..rule_path .. "/" ..rule_name)
reboot = 1
log(rule_name.. " 更新成功,总规则数 " ..count.. " 条。")
else
log(rule_name.. " 版本一致,无需更新。")
end
else
log(rule_name.. " 文件下载失败!")
end
os.remove(file_tmp)
return 0
end
local function fetch_gfwlist()
fetch_rule("gfwlist","domain",gfwlist_url,true)
end
local function fetch_chnroute()
fetch_rule("chnroute","ip4",chnroute_url,false)
end
local function fetch_chnroute6()
fetch_rule("chnroute6","ip6",chnroute6_url,false)
end
local function fetch_chnlist()
fetch_rule("chnlist","domain",chnlist_url,false)
end
--获取geoip
local function fetch_geoip()
--请求geoip
xpcall(function()
local json_str = curl(geoip_api)
local json = jsonc.parse(json_str)
if json.tag_name and json.assets then
for _, v in ipairs(json.assets) do
if v.name and v.name == "geoip.dat.sha256sum" then
local sret = curl(v.browser_download_url, "/tmp/geoip.dat.sha256sum")
if sret == 200 then
local f = io.open("/tmp/geoip.dat.sha256sum", "r")
local content = f:read()
f:close()
f = io.open("/tmp/geoip.dat.sha256sum", "w")
f:write(content:gsub("geoip.dat", "/tmp/geoip.dat"), "")
f:close()
if nixio.fs.access(v2ray_asset_location .. "geoip.dat") then
luci.sys.call(string.format("cp -f %s %s", v2ray_asset_location .. "geoip.dat", "/tmp/geoip.dat"))
if luci.sys.call('sha256sum -c /tmp/geoip.dat.sha256sum > /dev/null 2>&1') == 0 then
log("geoip 版本一致,无需更新。")
return 1
end
end
for _2, v2 in ipairs(json.assets) do
if v2.name and v2.name == "geoip.dat" then
sret = curl(v2.browser_download_url, "/tmp/geoip.dat")
if luci.sys.call('sha256sum -c /tmp/geoip.dat.sha256sum > /dev/null 2>&1') == 0 then
luci.sys.call(string.format("mkdir -p %s && cp -f %s %s", v2ray_asset_location, "/tmp/geoip.dat", v2ray_asset_location .. "geoip.dat"))
reboot = 1
log("geoip 更新成功。")
return 1
else
log("geoip 更新失败,请稍后再试。")
end
break
end
end
end
break
end
end
end
end,
function(e)
end)
return 0
end
--获取geosite
local function fetch_geosite()
--请求geosite
xpcall(function()
local json_str = curl(geosite_api)
local json = jsonc.parse(json_str)
if json.tag_name and json.assets then
for _, v in ipairs(json.assets) do
if v.name and v.name == "geosite.dat.sha256sum" then
local sret = curl(v.browser_download_url, "/tmp/geosite.dat.sha256sum")
if sret == 200 then
local f = io.open("/tmp/geosite.dat.sha256sum", "r")
local content = f:read()
f:close()
f = io.open("/tmp/geosite.dat.sha256sum", "w")
f:write(content:gsub("geosite.dat", "/tmp/geosite.dat"), "")
f:close()
if nixio.fs.access(v2ray_asset_location .. "geosite.dat") then
luci.sys.call(string.format("cp -f %s %s", v2ray_asset_location .. "geosite.dat", "/tmp/geosite.dat"))
if luci.sys.call('sha256sum -c /tmp/geosite.dat.sha256sum > /dev/null 2>&1') == 0 then
log("geosite 版本一致,无需更新。")
return 1
end
end
for _2, v2 in ipairs(json.assets) do
if v2.name and v2.name == "geosite.dat" then
sret = curl(v2.browser_download_url, "/tmp/geosite.dat")
if luci.sys.call('sha256sum -c /tmp/geosite.dat.sha256sum > /dev/null 2>&1') == 0 then
luci.sys.call(string.format("mkdir -p %s && cp -f %s %s", v2ray_asset_location, "/tmp/geosite.dat", v2ray_asset_location .. "geosite.dat"))
reboot = 1
log("geosite 更新成功。")
return 1
else
log("geosite 更新失败,请稍后再试。")
end
break
end
end
end
break
end
end
end
end,
function(e)
end)
return 0
end
if arg[2] then
if arg[2]:find("gfwlist") then
gfwlist_update = 1
end
if arg[2]:find("chnroute") then
chnroute_update = 1
end
if arg[2]:find("chnroute6") then
chnroute6_update = 1
end
if arg[2]:find("chnlist") then
chnlist_update = 1
end
if arg[2]:find("geoip") then
geoip_update = 1
end
if arg[2]:find("geosite") then
geosite_update = 1
end
else
gfwlist_update = ucic:get_first(name, 'global_rules', "gfwlist_update", 1)
chnroute_update = ucic:get_first(name, 'global_rules', "chnroute_update", 1)
chnroute6_update = ucic:get_first(name, 'global_rules', "chnroute6_update", 1)
chnlist_update = ucic:get_first(name, 'global_rules', "chnlist_update", 1)
geoip_update = ucic:get_first(name, 'global_rules', "geoip_update", 1)
geosite_update = ucic:get_first(name, 'global_rules', "geosite_update", 1)
end
if gfwlist_update == 0 and chnroute_update == 0 and chnroute6_update == 0 and chnlist_update == 0 and geoip_update == 0 and geosite_update == 0 then
os.exit(0)
end
log("开始更新规则...")
if tonumber(gfwlist_update) == 1 then
xpcall(fetch_gfwlist,function(e)
log(e)
log(debug.traceback())
log('更新gfwlist发生错误...')
end)
end
if tonumber(chnroute_update) == 1 then
xpcall(fetch_chnroute,function(e)
log(e)
log(debug.traceback())
log('更新chnroute发生错误...')
end)
end
if tonumber(chnroute6_update) == 1 then
xpcall(fetch_chnroute6,function(e)
log(e)
log(debug.traceback())
log('更新chnroute6发生错误...')
end)
end
if tonumber(chnlist_update) == 1 then
xpcall(fetch_chnlist,function(e)
log(e)
log(debug.traceback())
log('更新chnlist发生错误...')
end)
end
if tonumber(geoip_update) == 1 then
log("geoip 开始更新...")
local status = fetch_geoip()
os.remove("/tmp/geoip.dat")
os.remove("/tmp/geoip.dat.sha256sum")
end
if tonumber(geosite_update) == 1 then
log("geosite 开始更新...")
local status = fetch_geosite()
os.remove("/tmp/geosite.dat")
os.remove("/tmp/geosite.dat.sha256sum")
end
ucic:set(name, ucic:get_first(name, 'global_rules'), "gfwlist_update", gfwlist_update)
ucic:set(name, ucic:get_first(name, 'global_rules'), "chnroute_update", chnroute_update)
ucic:set(name, ucic:get_first(name, 'global_rules'), "chnroute6_update", chnroute6_update)
ucic:set(name, ucic:get_first(name, 'global_rules'), "chnlist_update", chnlist_update)
ucic:set(name, ucic:get_first(name, 'global_rules'), "geoip_update", geoip_update)
ucic:set(name, ucic:get_first(name, 'global_rules'), "geosite_update", geosite_update)
ucic:save(name)
luci.sys.call("uci commit " .. name)
if reboot == 1 then
log("重启服务,应用新的规则。")
luci.sys.call("/usr/share/" .. name .. "/iptables.sh flush_ipset > /dev/null 2>&1 &")
end
log("规则更新完毕...")

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -1,18 +0,0 @@
apple.com
microsoft.com
dyndns.com
douyucdn.cn
douyucdn2.cn
#steam
steamcontent.com
dl.steam.clngaa.com
dl.steam.ksyna.com
st.dl.bscstorage.net
st.dl.eccdnx.com
st.dl.pinyuncloud.com
cdn.mileweb.cs.steampowered.com.8686c.com
cdn-ws.content.steamchina.com
cdn-qc.content.steamchina.com
cdn-ali.content.steamchina.com
epicgames-download1-1251447533.file.myqcloud.com

View File

@@ -1,6 +0,0 @@
114.114.114.114
114.114.115.115
223.5.5.5
223.6.6.6
119.29.29.29
180.76.76.76

File diff suppressed because it is too large Load Diff

View File

@@ -1,9 +0,0 @@
0.0.0.0/8
10.0.0.0/8
100.64.0.0/10
127.0.0.0/8
169.254.0.0/16
172.16.0.0/12
192.168.0.0/16
224.0.0.0/4
240.0.0.0/4

View File

@@ -1,13 +0,0 @@
::/128
::1/128
::ffff:0:0/96
::ffff:0:0:0/96
64:ff9b::/96
100::/64
2001::/32
2001:20::/28
2001:db8::/32
2002::/16
fc00::/7
fe80::/10
ff00::/8

View File

@@ -1,14 +0,0 @@
bing.com
sspanel.net
v2ex.com
#google
googleapis.cn
googleapis.com
google.com.tw
google.com.hk
gstatic.com
xn--ngstr-lra8j.com
#github
github.com

View File

@@ -1,19 +0,0 @@
149.154.160.0/20
91.108.4.0/22
91.108.56.0/24
109.239.140.0/24
67.198.55.0/24
8.8.4.4
8.8.8.8
208.67.222.222
208.67.220.220
1.1.1.1
1.1.1.2
1.0.0.1
9.9.9.9
149.112.112.112
2001:67c:4e8::/48
2001:b28:f23c::/48
2001:b28:f23d::/48
2001:b28:f23f::/48
2001:b28:f242::/48

View File

@@ -1,11 +0,0 @@
{
"luci-app-passwall": {
"description": "Grant UCI access for luci-app-passwall",
"read": {
"uci": [ "passwall", "passwall_server" ]
},
"write": {
"uci": [ "passwall", "passwall_server" ]
}
}
}

View File

@@ -1,23 +1,19 @@
# Copyright (C) 2018-2020 L-WRT Team
# Copyright (C) 2021 xiaorouji
# Copyright (C) 2022 xiaorouji
#
# This is free software, licensed under the GNU General Public License v3.
include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-passwall
PKG_VERSION:=4.51
PKG_RELEASE:=2
#20220228
PKG_NAME:=luci-app-passwall2
PKG_VERSION:=1.0
PKG_RELEASE:=3
PKG_CONFIG_DEPENDS:= \
CONFIG_PACKAGE_$(PKG_NAME)_Transparent_Proxy \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Brook \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_ChinaDNS_NG \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Haproxy \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Hysteria \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_IPv6_Nat \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_NaiveProxy \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_PDNSD \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Libev_Client \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Libev_Server \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Rust_Client \
@@ -25,26 +21,19 @@ PKG_CONFIG_DEPENDS:= \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Libev_Client \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Libev_Server \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Simple_Obfs \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Trojan_GO \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Trojan_Plus \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_V2ray \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_V2ray_Plugin \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Xray \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Xray_Plugin
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Xray
LUCI_TITLE:=LuCI support for PassWall
LUCI_TITLE:=LuCI support for PassWall 2
LUCI_PKGARCH:=all
LUCI_DEPENDS:=+coreutils +coreutils-base64 +coreutils-nohup +curl \
+dnsmasq-full +dns2socks +ip-full +ipset +ipt2socks +iptables +iptables-mod-tproxy +iptables-mod-iprange \
+kmod-ipt-nat +libuci-lua +lua +luci-compat +luci-lib-jsonc +microsocks +resolveip +tcping \
+ip-full +libuci-lua +lua +luci-compat +luci-lib-jsonc +resolveip +tcping \
+v2ray-core +v2ray-geoip +v2ray-geosite \
+unzip \
+PACKAGE_$(PKG_NAME)_INCLUDE_Brook:brook \
+PACKAGE_$(PKG_NAME)_INCLUDE_ChinaDNS_NG:chinadns-ng \
+PACKAGE_$(PKG_NAME)_INCLUDE_Haproxy:haproxy \
+PACKAGE_$(PKG_NAME)_INCLUDE_Hysteria:hysteria \
+PACKAGE_$(PKG_NAME)_INCLUDE_IPv6_Nat:ip6tables-mod-nat \
+PACKAGE_$(PKG_NAME)_INCLUDE_NaiveProxy:naiveproxy \
+PACKAGE_$(PKG_NAME)_INCLUDE_PDNSD:pdnsd-alt \
+PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Libev_Client:shadowsocks-libev-ss-local \
+PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Libev_Client:shadowsocks-libev-ss-redir \
+PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Libev_Server:shadowsocks-libev-ss-server \
@@ -53,28 +42,28 @@ LUCI_DEPENDS:=+coreutils +coreutils-base64 +coreutils-nohup +curl \
+PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Libev_Client:shadowsocksr-libev-ssr-redir \
+PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Libev_Server:shadowsocksr-libev-ssr-server \
+PACKAGE_$(PKG_NAME)_INCLUDE_Simple_Obfs:simple-obfs \
+PACKAGE_$(PKG_NAME)_INCLUDE_Trojan_GO:trojan-go \
+PACKAGE_$(PKG_NAME)_INCLUDE_Trojan_Plus:trojan-plus \
+PACKAGE_$(PKG_NAME)_INCLUDE_V2ray:v2ray-core \
+PACKAGE_$(PKG_NAME)_INCLUDE_V2ray_Plugin:v2ray-plugin \
+PACKAGE_$(PKG_NAME)_INCLUDE_Xray:xray-core \
+PACKAGE_$(PKG_NAME)_INCLUDE_Xray_Plugin:xray-plugin
+PACKAGE_$(PKG_NAME)_INCLUDE_Xray:xray-core
define Package/$(PKG_NAME)/config
menu "Configuration"
config PACKAGE_$(PKG_NAME)_Transparent_Proxy
bool "Transparent Proxy"
select PACKAGE_dnsmasq-full
select PACKAGE_ipset
select PACKAGE_iptables
select PACKAGE_iptables-legacy
select PACKAGE_iptables-mod-iprange
select PACKAGE_iptables-mod-socket
select PACKAGE_iptables-mod-tproxy
select PACKAGE_kmod-ipt-nat
default y
config PACKAGE_$(PKG_NAME)_INCLUDE_Brook
bool "Include Brook"
default n
config PACKAGE_$(PKG_NAME)_INCLUDE_ChinaDNS_NG
bool "Include ChinaDNS-NG"
default y
config PACKAGE_$(PKG_NAME)_INCLUDE_Haproxy
bool "Include Haproxy"
default y if aarch64||arm||i386||x86_64
config PACKAGE_$(PKG_NAME)_INCLUDE_Hysteria
bool "Include Hysteria"
default n
@@ -89,10 +78,6 @@ config PACKAGE_$(PKG_NAME)_INCLUDE_NaiveProxy
depends on !(arc||(arm&&TARGET_gemini)||armeb||mips||mips64||powerpc)
default n
config PACKAGE_$(PKG_NAME)_INCLUDE_PDNSD
bool "Include PDNSD"
default y
config PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Libev_Client
bool "Include Shadowsocks Libev Client"
default y
@@ -118,18 +103,6 @@ config PACKAGE_$(PKG_NAME)_INCLUDE_Simple_Obfs
bool "Include Simple-Obfs (Shadowsocks Plugin)"
default y
config PACKAGE_$(PKG_NAME)_INCLUDE_Trojan_GO
bool "Include Trojan-GO"
default n
config PACKAGE_$(PKG_NAME)_INCLUDE_Trojan_Plus
bool "Include Trojan-Plus"
default y
config PACKAGE_$(PKG_NAME)_INCLUDE_V2ray
bool "Include V2ray"
default y if aarch64||arm||i386||x86_64
config PACKAGE_$(PKG_NAME)_INCLUDE_V2ray_Plugin
bool "Include V2ray-Plugin (Shadowsocks Plugin)"
default y if aarch64||arm||i386||x86_64
@@ -138,24 +111,12 @@ config PACKAGE_$(PKG_NAME)_INCLUDE_Xray
bool "Include Xray"
default y if aarch64||arm||i386||x86_64
config PACKAGE_$(PKG_NAME)_INCLUDE_Xray_Plugin
bool "Include Xray-Plugin (Shadowsocks Plugin)"
default n
endmenu
endef
define Package/$(PKG_NAME)/conffiles
/etc/config/passwall
/etc/config/passwall_server
/usr/share/passwall/rules/direct_host
/usr/share/passwall/rules/direct_ip
/usr/share/passwall/rules/proxy_host
/usr/share/passwall/rules/proxy_ip
/usr/share/passwall/rules/block_host
/usr/share/passwall/rules/block_ip
/usr/share/passwall/rules/lanlist_ipv4
/usr/share/passwall/rules/lanlist_ipv6
/etc/config/passwall2
/etc/config/passwall2_server
endef
include $(TOPDIR)/feeds/luci/luci.mk

View File

@@ -1,8 +1,7 @@
-- Copyright (C) 2018-2020 L-WRT Team
-- Copyright (C) 2021 xiaorouji
-- Copyright (C) 2022 xiaorouji
module("luci.controller.passwall", package.seeall)
local api = require "luci.model.cbi.passwall.api.api"
module("luci.controller.passwall2", package.seeall)
local api = require "luci.model.cbi.passwall2.api.api"
local appname = api.appname
local ucic = luci.model.uci.cursor()
local http = require "luci.http"
@@ -11,20 +10,19 @@ local i18n = require "luci.i18n"
local brook = require("luci.model.cbi." .. appname ..".api.brook")
local v2ray = require("luci.model.cbi." .. appname ..".api.v2ray")
local xray = require("luci.model.cbi." .. appname ..".api.xray")
local trojan_go = require("luci.model.cbi." .. appname ..".api.trojan_go")
local hysteria = require("luci.model.cbi." .. appname ..".api.hysteria")
function index()
appname = require "luci.model.cbi.passwall.api.api".appname
appname = require "luci.model.cbi.passwall2.api.api".appname
entry({"admin", "services", appname}).dependent = true
entry({"admin", "services", appname, "reset_config"}, call("reset_config")).leaf = true
entry({"admin", "services", appname, "show"}, call("show_menu")).leaf = true
entry({"admin", "services", appname, "hide"}, call("hide_menu")).leaf = true
if not nixio.fs.access("/etc/config/passwall") then return end
if nixio.fs.access("/etc/config/passwall_show") then
e = entry({"admin", "services", appname}, alias("admin", "services", appname, "settings"), _("Pass Wall"), -1)
if not nixio.fs.access("/etc/config/passwall2") then return end
if nixio.fs.access("/etc/config/passwall2_show") then
e = entry({"admin", "services", appname}, alias("admin", "services", appname, "settings"), _("PassWall 2"), -1)
e.dependent = true
e.acl_depends = { "luci-app-passwall" }
e.acl_depends = { "luci-app-passwall2" }
end
--[[ Client ]]
entry({"admin", "services", appname, "settings"}, cbi(appname .. "/client/global"), _("Basic Settings"), 1).dependent = true
@@ -32,12 +30,8 @@ function index()
entry({"admin", "services", appname, "node_subscribe"}, cbi(appname .. "/client/node_subscribe"), _("Node Subscribe"), 3).dependent = true
entry({"admin", "services", appname, "auto_switch"}, cbi(appname .. "/client/auto_switch"), _("Auto Switch"), 4).leaf = true
entry({"admin", "services", appname, "other"}, cbi(appname .. "/client/other", {autoapply = true}), _("Other Settings"), 92).leaf = true
if nixio.fs.access("/usr/sbin/haproxy") then
entry({"admin", "services", appname, "haproxy"}, cbi(appname .. "/client/haproxy"), _("Load Balancing"), 93).leaf = true
end
entry({"admin", "services", appname, "app_update"}, cbi(appname .. "/client/app_update"), _("App Update"), 95).leaf = true
entry({"admin", "services", appname, "rule"}, cbi(appname .. "/client/rule"), _("Rule Manage"), 96).leaf = true
entry({"admin", "services", appname, "rule_list"}, cbi(appname .. "/client/rule_list"), _("Rule List"), 97).leaf = true
entry({"admin", "services", appname, "node_subscribe_config"}, cbi(appname .. "/client/node_subscribe_config")).leaf = true
entry({"admin", "services", appname, "node_config"}, cbi(appname .. "/client/node_config")).leaf = true
entry({"admin", "services", appname, "shunt_rules"}, cbi(appname .. "/client/shunt_rules")).leaf = true
@@ -62,7 +56,6 @@ function index()
entry({"admin", "services", appname, "get_log"}, call("get_log")).leaf = true
entry({"admin", "services", appname, "clear_log"}, call("clear_log")).leaf = true
entry({"admin", "services", appname, "status"}, call("status")).leaf = true
entry({"admin", "services", appname, "haproxy_status"}, call("haproxy_status")).leaf = true
entry({"admin", "services", appname, "socks_status"}, call("socks_status")).leaf = true
entry({"admin", "services", appname, "connect_status"}, call("connect_status")).leaf = true
entry({"admin", "services", appname, "ping_node"}, call("ping_node")).leaf = true
@@ -78,8 +71,6 @@ function index()
entry({"admin", "services", appname, "v2ray_update"}, call("v2ray_update")).leaf = true
entry({"admin", "services", appname, "xray_check"}, call("xray_check")).leaf = true
entry({"admin", "services", appname, "xray_update"}, call("xray_update")).leaf = true
entry({"admin", "services", appname, "trojan_go_check"}, call("trojan_go_check")).leaf = true
entry({"admin", "services", appname, "trojan_go_update"}, call("trojan_go_update")).leaf = true
entry({"admin", "services", appname, "hysteria_check"}, call("hysteria_check")).leaf = true
entry({"admin", "services", appname, "hysteria_update"}, call("hysteria_update")).leaf = true
end
@@ -90,20 +81,20 @@ local function http_write_json(content)
end
function reset_config()
luci.sys.call('/etc/init.d/passwall stop')
luci.sys.call('[ -f "/usr/share/passwall/0_default_config" ] && cp -f /usr/share/passwall/0_default_config /etc/config/passwall')
luci.sys.call('/etc/init.d/passwall2 stop')
luci.sys.call('[ -f "/usr/share/passwall2/0_default_config" ] && cp -f /usr/share/passwall2/0_default_config /etc/config/passwall2')
luci.http.redirect(api.url())
end
function show_menu()
luci.sys.call("touch /etc/config/passwall_show")
luci.sys.call("touch /etc/config/passwall2_show")
luci.sys.call("rm -rf /tmp/luci-*")
luci.sys.call("/etc/init.d/rpcd restart >/dev/null")
luci.http.redirect(api.url())
end
function hide_menu()
luci.sys.call("rm -rf /etc/config/passwall_show")
luci.sys.call("rm -rf /etc/config/passwall2_show")
luci.sys.call("rm -rf /tmp/luci-*")
luci.sys.call("/etc/init.d/rpcd restart >/dev/null")
luci.http.redirect(luci.dispatcher.build_url("admin", "status", "overview"))
@@ -113,7 +104,7 @@ function link_add_node()
local lfile = "/tmp/links.conf"
local link = luci.http.formvalue("link")
luci.sys.call('echo \'' .. link .. '\' > ' .. lfile)
luci.sys.call("lua /usr/share/passwall/subscribe.lua add log")
luci.sys.call("lua /usr/share/passwall2/subscribe.lua add log")
end
function autoswitch_add_node()
@@ -121,7 +112,7 @@ function autoswitch_add_node()
if key and key ~= "" then
for k, e in ipairs(api.get_valid_nodes()) do
if e.node_type == "normal" and e["remark"]:find(key) then
luci.sys.call(string.format("uci -q del_list passwall.@auto_switch[0].tcp_node='%s' && uci -q add_list passwall.@auto_switch[0].tcp_node='%s'", e.id, e.id))
luci.sys.call(string.format("uci -q del_list passwall2.@auto_switch[0].node='%s' && uci -q add_list passwall2.@auto_switch[0].node='%s'", e.id, e.id))
end
end
end
@@ -131,9 +122,9 @@ end
function autoswitch_remove_node()
local key = luci.http.formvalue("key")
if key and key ~= "" then
for k, e in ipairs(ucic:get(appname, "@auto_switch[0]", "tcp_node") or {}) do
for k, e in ipairs(ucic:get(appname, "@auto_switch[0]", "node") or {}) do
if e and (ucic:get(appname, e, "remarks") or ""):find(key) then
luci.sys.call(string.format("uci -q del_list passwall.@auto_switch[0].tcp_node='%s'", e))
luci.sys.call(string.format("uci -q del_list passwall2.@auto_switch[0].node='%s'", e))
end
end
end
@@ -142,26 +133,18 @@ end
function get_now_use_node()
local e = {}
local data, code, msg = nixio.fs.readfile("/tmp/etc/passwall/id/TCP")
local data, code, msg = nixio.fs.readfile("/tmp/etc/passwall2/id/global")
if data then
e["TCP"] = util.trim(data)
end
local data, code, msg = nixio.fs.readfile("/tmp/etc/passwall/id/UDP")
if data then
e["UDP"] = util.trim(data)
e["global"] = util.trim(data)
end
luci.http.prepare_content("application/json")
luci.http.write_json(e)
end
function get_redir_log()
local proto = luci.http.formvalue("proto")
proto = proto:upper()
if proto == "UDP" and (ucic:get(appname, "@global[0]", "udp_node") or "nil") == "tcp" and not nixio.fs.access("/tmp/etc/passwall/" .. proto .. ".log") then
proto = "TCP"
end
if nixio.fs.access("/tmp/etc/passwall/" .. proto .. ".log") then
local content = luci.sys.exec("cat /tmp/etc/passwall/" .. proto .. ".log")
local id = luci.http.formvalue("id")
if nixio.fs.access("/tmp/etc/passwall2/" .. id .. ".log") then
local content = luci.sys.exec("cat /tmp/etc/passwall2/" .. id .. ".log")
content = content:gsub("\n", "<br />")
luci.http.write(content)
else
@@ -170,32 +153,17 @@ function get_redir_log()
end
function get_log()
-- luci.sys.exec("[ -f /tmp/log/passwall.log ] && sed '1!G;h;$!d' /tmp/log/passwall.log > /tmp/log/passwall_show.log")
luci.http.write(luci.sys.exec("[ -f '/tmp/log/passwall.log' ] && cat /tmp/log/passwall.log"))
-- luci.sys.exec("[ -f /tmp/log/passwall2.log ] && sed '1!G;h;$!d' /tmp/log/passwall2.log > /tmp/log/passwall2_show.log")
luci.http.write(luci.sys.exec("[ -f '/tmp/log/passwall2.log' ] && cat /tmp/log/passwall2.log"))
end
function clear_log()
luci.sys.call("echo '' > /tmp/log/passwall.log")
luci.sys.call("echo '' > /tmp/log/passwall2.log")
end
function status()
-- local dns_mode = ucic:get(appname, "@global[0]", "dns_mode")
local e = {}
e.dns_mode_status = luci.sys.call("netstat -apn | grep ':7913 ' >/dev/null") == 0
e.haproxy_status = luci.sys.call(string.format("top -bn1 | grep -v grep | grep '%s/bin/' | grep haproxy >/dev/null", appname)) == 0
e["tcp_node_status"] = luci.sys.call(string.format("top -bn1 | grep -v -E 'grep|acl/|acl_' | grep '%s/bin/' | grep -i 'TCP' >/dev/null", appname)) == 0
if (ucic:get(appname, "@global[0]", "udp_node") or "nil") == "tcp" then
e["udp_node_status"] = e["tcp_node_status"]
else
e["udp_node_status"] = luci.sys.call(string.format("top -bn1 | grep -v -E 'grep|acl/|acl_' | grep '%s/bin/' | grep -i 'UDP' >/dev/null", appname)) == 0
end
luci.http.prepare_content("application/json")
luci.http.write_json(e)
end
function haproxy_status()
local e = luci.sys.call(string.format("top -bn1 | grep -v grep | grep '%s/bin/' | grep haproxy >/dev/null", appname)) == 0
e["global_status"] = luci.sys.call(string.format("top -bn1 | grep -v -E 'grep|acl/|acl_' | grep '%s/bin/' | grep -i 'global' >/dev/null", appname)) == 0
luci.http.prepare_content("application/json")
luci.http.write_json(e)
end
@@ -257,7 +225,7 @@ function urltest_node()
local id = luci.http.formvalue("id")
local e = {}
e.index = index
local result = luci.sys.exec(string.format("/usr/share/passwall/test.sh url_test_node %s %s", id, "urltest_node"))
local result = luci.sys.exec(string.format("/usr/share/passwall2/test.sh url_test_node %s %s", id, "urltest_node"))
local code = tonumber(luci.sys.exec("echo -n '" .. result .. "' | awk -F ':' '{print $1}'") or "0")
if code ~= 0 then
local use_time = luci.sys.exec("echo -n '" .. result .. "' | awk -F ':' '{print $2}'")
@@ -276,7 +244,7 @@ function set_node()
local section = luci.http.formvalue("section")
ucic:set(appname, "@global[0]", protocol .. "_node", section)
ucic:commit(appname)
luci.sys.call("/etc/init.d/passwall restart > /dev/null 2>&1 &")
luci.sys.call("/etc/init.d/passwall2 restart > /dev/null 2>&1 &")
luci.http.redirect(api.url("log"))
end
@@ -303,18 +271,13 @@ end
function clear_all_nodes()
ucic:set(appname, '@global[0]', "enabled", "0")
ucic:set(appname, '@global[0]', "tcp_node", "nil")
ucic:set(appname, '@global[0]', "udp_node", "nil")
ucic:set_list(appname, "@auto_switch[0]", "tcp_node", {})
ucic:set(appname, '@global[0]', "node", "nil")
ucic:set_list(appname, "@auto_switch[0]", "node", {})
ucic:foreach(appname, "socks", function(t)
ucic:delete(appname, t[".name"])
end)
ucic:foreach(appname, "haproxy_config", function(t)
ucic:delete(appname, t[".name"])
end)
ucic:foreach(appname, "acl_rule", function(t)
ucic:set(appname, t[".name"], "tcp_node", "default")
ucic:set(appname, t[".name"], "udp_node", "default")
ucic:set(appname, t[".name"], "node", "default")
end)
ucic:foreach(appname, "nodes", function(node)
ucic:delete(appname, node['.name'])
@@ -326,35 +289,24 @@ end
function delete_select_nodes()
local ids = luci.http.formvalue("ids")
local auto_switch_tcp_node_list = ucic:get(appname, "@auto_switch[0]", "tcp_node") or {}
local auto_switch_node_list = ucic:get(appname, "@auto_switch[0]", "node") or {}
string.gsub(ids, '[^' .. "," .. ']+', function(w)
for k, v in ipairs(auto_switch_tcp_node_list) do
for k, v in ipairs(auto_switch_node_list) do
if v == w then
luci.sys.call(string.format("uci -q del_list passwall.@auto_switch[0].tcp_node='%s'", w))
luci.sys.call(string.format("uci -q del_list passwall2.@auto_switch[0].node='%s'", w))
end
end
if (ucic:get(appname, "@global[0]", "tcp_node") or "nil") == w then
ucic:set(appname, '@global[0]', "tcp_node", "nil")
end
if (ucic:get(appname, "@global[0]", "udp_node") or "nil") == w then
ucic:set(appname, '@global[0]', "udp_node", "nil")
if (ucic:get(appname, "@global[0]", "node") or "nil") == w then
ucic:set(appname, '@global[0]', "node", "nil")
end
ucic:foreach(appname, "socks", function(t)
if t["node"] == w then
ucic:delete(appname, t[".name"])
end
end)
ucic:foreach(appname, "haproxy_config", function(t)
if t["lbss"] == w then
ucic:delete(appname, t[".name"])
end
end)
ucic:foreach(appname, "acl_rule", function(t)
if t["tcp_node"] == w then
ucic:set(appname, t[".name"], "tcp_node", "default")
end
if t["udp_node"] == w then
ucic:set(appname, t[".name"], "udp_node", "default")
if t["node"] == w then
ucic:set(appname, t[".name"], "node", "default")
end
end)
ucic:delete(appname, w)
@@ -365,7 +317,7 @@ end
function update_rules()
local update = luci.http.formvalue("update")
luci.sys.call("lua /usr/share/passwall/rule_update.lua log '" .. update .. "' > /dev/null 2>&1 &")
luci.sys.call("lua /usr/share/passwall2/rule_update.lua log '" .. update .. "' > /dev/null 2>&1 &")
http_write_json()
end
@@ -378,8 +330,8 @@ end
function server_user_log()
local id = luci.http.formvalue("id")
if nixio.fs.access("/tmp/etc/passwall_server/" .. id .. ".log") then
local content = luci.sys.exec("cat /tmp/etc/passwall_server/" .. id .. ".log")
if nixio.fs.access("/tmp/etc/passwall2_server/" .. id .. ".log") then
local content = luci.sys.exec("cat /tmp/etc/passwall2_server/" .. id .. ".log")
content = content:gsub("\n", "<br />")
luci.http.write(content)
else
@@ -388,11 +340,11 @@ function server_user_log()
end
function server_get_log()
luci.http.write(luci.sys.exec("[ -f '/tmp/log/passwall_server.log' ] && cat /tmp/log/passwall_server.log"))
luci.http.write(luci.sys.exec("[ -f '/tmp/log/passwall2_server.log' ] && cat /tmp/log/passwall2_server.log"))
end
function server_clear_log()
luci.sys.call("echo '' > /tmp/log/passwall_server.log")
luci.sys.call("echo '' > /tmp/log/passwall2_server.log")
end
function brook_check()
@@ -450,25 +402,6 @@ function xray_update()
http_write_json(json)
end
function trojan_go_check()
local json = trojan_go.to_check("")
http_write_json(json)
end
function trojan_go_update()
local json = nil
local task = http.formvalue("task")
if task == "extract" then
json = trojan_go.to_extract(http.formvalue("file"), http.formvalue("subfix"))
elseif task == "move" then
json = trojan_go.to_move(http.formvalue("file"))
else
json = trojan_go.to_download(http.formvalue("url"), http.formvalue("size"))
end
http_write_json(json)
end
function hysteria_check()
local json = hysteria.to_check("")
http_write_json(json)

View File

@@ -1,4 +1,4 @@
module("luci.model.cbi.passwall.api.api", package.seeall)
module("luci.model.cbi.passwall2.api.api", package.seeall)
fs = require "nixio.fs"
sys = require "luci.sys"
uci = require"luci.model.uci".cursor()
@@ -7,7 +7,7 @@ datatypes = require "luci.cbi.datatypes"
jsonc = require "luci.jsonc"
i18n = require "luci.i18n"
appname = "passwall"
appname = "passwall2"
curl = "/usr/bin/curl"
curl_args = {"-skfL", "--connect-timeout 3", "--retry 3", "-m 60"}
command_timeout = 300
@@ -287,15 +287,15 @@ function clone(org)
end
function get_bin_version_cache(file, cmd)
sys.call("mkdir -p /tmp/etc/passwall_tmp")
sys.call("mkdir -p /tmp/etc/passwall2_tmp")
if fs.access(file) then
chmod_755(file)
local md5 = sys.exec("echo -n $(md5sum " .. file .. " | awk '{print $1}')")
if fs.access("/tmp/etc/passwall_tmp/" .. md5) then
return sys.exec("echo -n $(cat /tmp/etc/passwall_tmp/%s)" % md5)
if fs.access("/tmp/etc/passwall2_tmp/" .. md5) then
return sys.exec("echo -n $(cat /tmp/etc/passwall2_tmp/%s)" % md5)
else
local version = sys.exec(string.format("echo -n $(%s %s)", file, cmd))
sys.call("echo '" .. version .. "' > " .. "/tmp/etc/passwall_tmp/" .. md5)
sys.call("echo '" .. version .. "' > " .. "/tmp/etc/passwall2_tmp/" .. md5)
return version
end
end
@@ -324,17 +324,6 @@ function get_xray_version(file)
return get_bin_version_cache(file, cmd)
end
function get_trojan_go_path()
local path = uci_get_type("global_app", "trojan_go_file")
return path
end
function get_trojan_go_version(file)
if file == nil then file = get_trojan_go_path() end
local cmd = "-version | awk '{print $2}' | sed -n 1P"
return get_bin_version_cache(file, cmd)
end
function get_brook_path()
local path = uci_get_type("global_app", "brook_file")
return path

View File

@@ -1,5 +1,5 @@
module("luci.model.cbi.passwall.api.brook", package.seeall)
local api = require "luci.model.cbi.passwall.api.api"
module("luci.model.cbi.passwall2.api.brook", package.seeall)
local api = require "luci.model.cbi.passwall2.api.api"
local fs = api.fs
local sys = api.sys
local util = api.util
@@ -96,9 +96,9 @@ function to_move(file)
}
end
local flag = sys.call('pgrep -af "passwall/.*brook" >/dev/null')
local flag = sys.call('pgrep -af "passwall2/.*brook" >/dev/null')
if flag == 0 then
sys.call("/etc/init.d/passwall stop")
sys.call("/etc/init.d/passwall2 stop")
end
local old_app_size = 0
@@ -120,7 +120,7 @@ function to_move(file)
sys.call("/bin/rm -rf /tmp/brook_download.*")
if flag == 0 then
sys.call("/etc/init.d/passwall restart >/dev/null 2>&1 &")
sys.call("/etc/init.d/passwall2 restart >/dev/null 2>&1 &")
end
if not result or not fs.access(app_path) then

View File

@@ -1,4 +1,4 @@
local api = require "luci.model.cbi.passwall.api.api"
local api = require "luci.model.cbi.passwall2.api.api"
local uci = api.uci
local jsonc = api.jsonc
@@ -18,7 +18,7 @@ local local_http_address = var["-local_http_address"] or "0.0.0.0"
local local_http_port = var["-local_http_port"]
local local_http_username = var["-local_http_username"]
local local_http_password = var["-local_http_password"]
local node = uci:get_all("passwall", node_section)
local node = uci:get_all("passwall2", node_section)
local config = {
server = node.address .. ":" .. node.port,

View File

@@ -1,4 +1,4 @@
local api = require "luci.model.cbi.passwall.api.api"
local api = require "luci.model.cbi.passwall2.api.api"
local uci = api.uci
local jsonc = api.jsonc
@@ -13,7 +13,7 @@ local local_addr = var["-local_addr"]
local local_port = var["-local_port"]
local server_host = var["-server_host"]
local server_port = var["-server_port"]
local node = uci:get_all("passwall", node_section)
local node = uci:get_all("passwall2", node_section)
local config = {
listen = run_type .. "://" .. local_addr .. ":" .. local_port,

View File

@@ -1,4 +1,4 @@
local api = require "luci.model.cbi.passwall.api.api"
local api = require "luci.model.cbi.passwall2.api.api"
local uci = api.uci
local jsonc = api.jsonc
@@ -14,7 +14,7 @@ local server_host = var["-server_host"]
local server_port = var["-server_port"]
local protocol = var["-protocol"]
local mode = var["-mode"]
local node = uci:get_all("passwall", node_section)
local node = uci:get_all("passwall2", node_section)
local config = {
server = server_host or node.address,

View File

@@ -1,10 +1,10 @@
module("luci.model.cbi.passwall.api.gen_v2ray", package.seeall)
local api = require "luci.model.cbi.passwall.api.api"
module("luci.model.cbi.passwall2.api.gen_v2ray", package.seeall)
local api = require "luci.model.cbi.passwall2.api.api"
local var = api.get_args(arg)
local node_section = var["-node"]
local proto = var["-proto"]
local proxy_way = var["-proxy_way"]
local flag = var["-flag"]
local node_id = var["-node"]
local tcp_proxy_way = var["-tcp_proxy_way"]
local redir_port = var["-redir_port"]
local sniffing = var["-sniffing"]
local route_only = var["-route_only"]
@@ -17,18 +17,20 @@ local local_http_port = var["-local_http_port"]
local local_http_username = var["-local_http_username"]
local local_http_password = var["-local_http_password"]
local dns_listen_port = var["-dns_listen_port"]
local local_dns_ip = var["-local_dns_ip"] or "119.29.29.29"
local local_dns_address = var["-local_dns_address"] or "tcp+local://119.29.29.29"
local local_dns_port = var["-local_dns_port"] or 53
local dns_server = var["-dns_server"]
local dns_direct_domains = {}
local dns_direct_expectIPs = {}
local dns_tcp_server = var["-dns_tcp_server"]
local dns_cache = var["-dns_cache"]
local doh_url = var["-doh_url"]
local doh_host = var["-doh_host"]
local dns_client_ip = var["-dns_client_ip"]
local dns_query_strategy = var["-dns_query_strategy"]
local dns_socks_address = var["-dns_socks_address"]
local dns_socks_port = var["-dns_socks_port"]
local dns_fakedns = var["-dns_fakedns"]
local loglevel = var["-loglevel"] or "warning"
local network = proto
local new_port
local uci = api.uci
@@ -75,30 +77,25 @@ function gen_outbound(node, tag, proxy_table)
end
if node.type ~= "V2ray" and node.type ~= "Xray" then
if node.type == "Socks" then
node.protocol = "socks"
node.transport = "tcp"
else
local node_type = proto or "socks"
local relay_port = node.port
new_port = get_new_port()
node.port = new_port
sys.call(string.format('/usr/share/%s/app.sh run_socks "%s"> /dev/null',
appname,
string.format("flag=%s node=%s bind=%s socks_port=%s config_file=%s relay_port=%s",
new_port, --flag
node_id, --node
"127.0.0.1", --bind
new_port, --socks port
string.format("/tmp/etc/%s/v2_%s_%s_%s.json", appname, node_type, node_id, new_port), --config file
(proxy == 1 and proxy_tag ~= "nil" and relay_port) and tostring(relay_port) or "" --relay port
)
local relay_port = node.port
new_port = get_new_port()
sys.call(string.format('/usr/share/%s/app.sh run_socks "%s"> /dev/null',
appname,
string.format("flag=%s node=%s bind=%s socks_port=%s config_file=%s relay_port=%s",
new_port, --flag
node_id, --node
"127.0.0.1", --bind
new_port, --socks port
string.format("%s_%s_%s_%s.json", flag, tag, node_id, new_port), --config file
(proxy == 1 and proxy_tag ~= "nil" and relay_port) and tostring(relay_port) or "" --relay port
)
)
node.protocol = "socks"
node.transport = "tcp"
node.address = "127.0.0.1"
end
)
node = {}
node.protocol = "socks"
node.transport = "tcp"
node.address = "127.0.0.1"
node.port = new_port
node.stream_security = "none"
else
if node.tls and node.tls == "1" then
@@ -205,7 +202,7 @@ function gen_outbound(node, tag, proxy_table)
port = tonumber(node.port),
method = node.method or nil,
flow = node.flow or nil,
ivCheck = (node.iv_check == "1") and true or false,
ivCheck = (node.protocol == "shadowsocks") and node.iv_check == "1" or nil,
password = node.password or "",
users = (node.username and node.password) and {
{
@@ -235,8 +232,7 @@ function gen_outbound(node, tag, proxy_table)
return result
end
if node_section then
local node = uci:get_all(appname, node_section)
if true then
if local_socks_port then
local inbound = {
listen = local_socks_address,
@@ -255,7 +251,6 @@ if node_section then
}
end
table.insert(inbounds, inbound)
network = "tcp,udp"
end
if local_http_port then
local inbound = {
@@ -279,8 +274,15 @@ if node_section then
table.insert(inbounds, {
port = tonumber(redir_port),
protocol = "dokodemo-door",
settings = {network = proto, followRedirect = true},
streamSettings = {sockopt = {tproxy = proxy_way}},
settings = {network = "tcp", followRedirect = true},
streamSettings = {sockopt = {tproxy = tcp_proxy_way}},
sniffing = {enabled = sniffing and true or false, destOverride = {"http", "tls", (dns_fakedns) and "fakedns"}, metadataOnly = false, routeOnly = route_only and true or nil}
})
table.insert(inbounds, {
port = tonumber(redir_port),
protocol = "dokodemo-door",
settings = {network = "udp", followRedirect = true},
streamSettings = {sockopt = {tproxy = "tproxy"}},
sniffing = {enabled = sniffing and true or false, destOverride = {"http", "tls", (dns_fakedns) and "fakedns"}, metadataOnly = false, routeOnly = route_only and true or nil}
})
end
@@ -301,232 +303,246 @@ if node_section then
end
end
if node.protocol == "_shunt" then
table.insert(outbounds, {
protocol = "freedom",
tag = "direct",
settings = {
domainStrategy = "UseIPv4"
},
streamSettings = {
sockopt = {
mark = 255
}
}
})
table.insert(outbounds, {
protocol = "blackhole",
tag = "blackhole"
})
local rules = {}
local nodes = {}
if node_id then
local node = uci:get_all(appname, node_id)
if node then
nodes[node_id] = node
end
end
local default_node_id = node.default_node or "_direct"
local default_outboundTag
if default_node_id == "_direct" then
default_outboundTag = "direct"
elseif default_node_id == "_blackhole" then
default_outboundTag = "blackhole"
else
local default_node = uci:get_all(appname, default_node_id)
local main_node_id = node.main_node or "nil"
local proxy = 0
local proxy_tag
if main_node_id ~= "nil" then
local main_node = uci:get_all(appname, main_node_id)
if main_node and api.is_normal_node(main_node) and main_node_id ~= default_node_id then
local main_node_outbound = gen_outbound(main_node, "main")
if main_node_outbound then
table.insert(outbounds, main_node_outbound)
proxy = 1
proxy_tag = "main"
if default_node.type ~= "V2ray" and default_node.type ~= "Xray" then
proxy_tag = nil
new_port = get_new_port()
table.insert(inbounds, {
tag = "proxy_default",
listen = "127.0.0.1",
port = new_port,
protocol = "dokodemo-door",
settings = {network = "tcp,udp", address = default_node.address, port = tonumber(default_node.port)}
})
if default_node.tls_serverName == nil then
default_node.tls_serverName = default_node.address
for k, v in pairs(nodes) do
local node = v
if node.protocol == "_shunt" then
local rules = {}
local default_node_id = node.default_node or "_direct"
local default_outboundTag
if default_node_id == "_direct" then
default_outboundTag = "direct"
elseif default_node_id == "_blackhole" then
default_outboundTag = "blackhole"
else
local default_node = uci:get_all(appname, default_node_id)
local main_node_id = node.main_node or "nil"
local proxy = 0
local proxy_tag
if main_node_id ~= "nil" then
local main_node = uci:get_all(appname, main_node_id)
if main_node and api.is_normal_node(main_node) and main_node_id ~= default_node_id then
local main_node_outbound = gen_outbound(main_node, "main")
if main_node_outbound then
table.insert(outbounds, main_node_outbound)
proxy = 1
proxy_tag = "main"
if default_node.type ~= "V2ray" and default_node.type ~= "Xray" then
proxy_tag = nil
new_port = get_new_port()
table.insert(inbounds, {
tag = "proxy_default",
listen = "127.0.0.1",
port = new_port,
protocol = "dokodemo-door",
settings = {network = "tcp,udp", address = default_node.address, port = tonumber(default_node.port)}
})
if default_node.tls_serverName == nil then
default_node.tls_serverName = default_node.address
end
default_node.address = "127.0.0.1"
default_node.port = new_port
table.insert(rules, 1, {
type = "field",
inboundTag = {"proxy_default"},
outboundTag = "main"
})
end
default_node.address = "127.0.0.1"
default_node.port = new_port
table.insert(rules, 1, {
type = "field",
inboundTag = {"proxy_default"},
outboundTag = "main"
})
end
end
end
end
if default_node and api.is_normal_node(default_node) then
local default_outbound = gen_outbound(default_node, "default", { proxy = proxy, tag = proxy_tag })
if default_outbound then
table.insert(outbounds, default_outbound)
default_outboundTag = "default"
if default_node and api.is_normal_node(default_node) then
local default_outbound = gen_outbound(default_node, "default", { proxy = proxy, tag = proxy_tag })
if default_outbound then
table.insert(outbounds, default_outbound)
default_outboundTag = "default"
end
end
end
end
uci:foreach(appname, "shunt_rules", function(e)
local name = e[".name"]
local _node_id = node[name] or "nil"
local proxy_tag = node[name .. "_proxy_tag"] or "nil"
local outboundTag
if _node_id == "_direct" then
outboundTag = "direct"
elseif _node_id == "_blackhole" then
outboundTag = "blackhole"
elseif _node_id == "_default" then
outboundTag = "default"
else
if _node_id ~= "nil" then
local _node = uci:get_all(appname, _node_id)
if _node and api.is_normal_node(_node) then
local new_outbound
for index, value in ipairs(outbounds) do
if value["_flag_tag"] == _node_id and value["_flag_proxy_tag"] == proxy_tag then
new_outbound = api.clone(value)
break
end
end
if new_outbound then
new_outbound["tag"] = name
table.insert(outbounds, new_outbound)
outboundTag = name
else
if _node.type ~= "V2ray" and _node.type ~= "Xray" then
if proxy_tag ~= "nil" then
new_port = get_new_port()
table.insert(inbounds, {
tag = "proxy_" .. name,
listen = "127.0.0.1",
port = new_port,
protocol = "dokodemo-door",
settings = {network = "tcp,udp", address = _node.address, port = tonumber(_node.port)}
})
if _node.tls_serverName == nil then
_node.tls_serverName = _node.address
uci:foreach(appname, "shunt_rules", function(e)
local name = e[".name"]
if name and e.remarks then
local _node_id = node[name] or "nil"
local proxy_tag = node[name .. "_proxy_tag"] or "nil"
local outboundTag
if _node_id == "_direct" then
outboundTag = "direct"
elseif _node_id == "_blackhole" then
outboundTag = "blackhole"
elseif _node_id == "_default" then
outboundTag = "default"
else
if _node_id ~= "nil" then
local _node = uci:get_all(appname, _node_id)
if _node and api.is_normal_node(_node) then
local new_outbound
for index, value in ipairs(outbounds) do
if value["_flag_tag"] == _node_id and value["_flag_proxy_tag"] == proxy_tag then
new_outbound = api.clone(value)
break
end
end
if new_outbound then
new_outbound["tag"] = name
table.insert(outbounds, new_outbound)
outboundTag = name
else
if _node.type ~= "V2ray" and _node.type ~= "Xray" then
if proxy_tag ~= "nil" then
new_port = get_new_port()
table.insert(inbounds, {
tag = "proxy_" .. name,
listen = "127.0.0.1",
port = new_port,
protocol = "dokodemo-door",
settings = {network = "tcp,udp", address = _node.address, port = tonumber(_node.port)}
})
if _node.tls_serverName == nil then
_node.tls_serverName = _node.address
end
_node.address = "127.0.0.1"
_node.port = new_port
table.insert(rules, 1, {
type = "field",
inboundTag = {"proxy_" .. name},
outboundTag = proxy_tag
})
end
end
local _outbound = gen_outbound(_node, name, { proxy = (proxy_tag ~= "nil") and 1 or 0, tag = (proxy_tag ~= "nil") and proxy_tag or nil })
if _outbound then
table.insert(outbounds, _outbound)
outboundTag = name
end
_node.address = "127.0.0.1"
_node.port = new_port
table.insert(rules, 1, {
type = "field",
inboundTag = {"proxy_" .. name},
outboundTag = proxy_tag
})
end
end
local _outbound = gen_outbound(_node, name, { proxy = (proxy_tag ~= "nil") and 1 or 0, tag = (proxy_tag ~= "nil") and proxy_tag or nil })
if _outbound then
table.insert(outbounds, _outbound)
outboundTag = name
end
end
end
if outboundTag then
if outboundTag == "default" then
outboundTag = default_outboundTag
end
local protocols = nil
if e["protocol"] and e["protocol"] ~= "" then
protocols = {}
string.gsub(e["protocol"], '[^' .. " " .. ']+', function(w)
table.insert(protocols, w)
end)
end
local domains = nil
if e.domain_list then
domains = {}
string.gsub(e.domain_list, '[^' .. "\r\n" .. ']+', function(w)
table.insert(domains, w)
if outboundTag == "direct" then
table.insert(dns_direct_domains, w)
end
end)
end
local ip = nil
if e.ip_list then
ip = {}
string.gsub(e.ip_list, '[^' .. "\r\n" .. ']+', function(w)
table.insert(ip, w)
if outboundTag == "direct" then
table.insert(dns_direct_expectIPs, w)
end
end)
end
local source = nil
if e.source then
source = {}
string.gsub(e.source, '[^' .. "\r\n" .. ']+', function(w)
table.insert(source, w)
end)
end
local rule = {
type = "field",
outboundTag = outboundTag,
network = e["network"],
source = source,
sourcePort = e["sourcePort"] and e["sourcePort"] ~= "",
port = e["port"] and e["port"] ~= "",
protocol = protocols
}
if domains then
local _rule = api.clone(rule)
_rule.domains = domains
table.insert(rules, _rule)
end
if ip then
local _rule = api.clone(rule)
_rule.ip = ip
table.insert(rules, _rule)
end
if not domains and not ip then
table.insert(rules, rule)
end
end
end
end
if outboundTag then
if outboundTag == "default" then
outboundTag = default_outboundTag
end
local protocols = nil
if e["protocol"] and e["protocol"] ~= "" then
protocols = {}
string.gsub(e["protocol"], '[^' .. " " .. ']+', function(w)
table.insert(protocols, w)
end)
end
if e.domain_list then
local _domain = {}
string.gsub(e.domain_list, '[^' .. "\r\n" .. ']+', function(w)
table.insert(_domain, w)
end)
table.insert(rules, {
type = "field",
outboundTag = outboundTag,
domain = _domain,
protocol = protocols
})
end
if e.ip_list then
local _ip = {}
string.gsub(e.ip_list, '[^' .. "\r\n" .. ']+', function(w)
table.insert(_ip, w)
end)
table.insert(rules, {
type = "field",
outboundTag = outboundTag,
ip = _ip,
protocol = protocols
})
end
if not e.domain_list and not e.ip_list and protocols then
table.insert(rules, {
type = "field",
outboundTag = outboundTag,
protocol = protocols
})
end
end
end)
end)
if default_outboundTag then
table.insert(rules, {
type = "field",
outboundTag = default_outboundTag,
network = network
})
end
routing = {
domainStrategy = node.domainStrategy or "AsIs",
domainMatcher = node.domainMatcher or "hybrid",
rules = rules
}
elseif node.protocol == "_balancing" then
if node.balancing_node then
local nodes = node.balancing_node
local length = #nodes
for i = 1, length do
local node = uci:get_all(appname, nodes[i])
local outbound = gen_outbound(node)
if outbound then table.insert(outbounds, outbound) end
if default_outboundTag then
table.insert(rules, {
type = "field",
outboundTag = default_outboundTag,
network = "tcp,udp"
})
end
routing = {
domainStrategy = node.domainStrategy or "AsIs",
domainMatcher = node.domainMatcher or "hybrid",
balancers = {{tag = "balancer", selector = nodes}},
rules = {
{type = "field", network = "tcp,udp", balancerTag = "balancer"}
rules = rules
}
elseif node.protocol == "_balancing" then
if node.balancing_node then
local nodes = node.balancing_node
local length = #nodes
for i = 1, length do
local node = uci:get_all(appname, nodes[i])
local outbound = gen_outbound(node)
if outbound then table.insert(outbounds, outbound) end
end
routing = {
domainStrategy = node.domainStrategy or "AsIs",
domainMatcher = node.domainMatcher or "hybrid",
balancers = {{tag = "balancer", selector = nodes}},
rules = {
{type = "field", network = "tcp,udp", balancerTag = "balancer"}
}
}
end
else
local outbound = gen_outbound(node)
if outbound then table.insert(outbounds, outbound) end
routing = {
domainStrategy = "AsIs",
domainMatcher = "hybrid",
rules = {}
}
end
else
local outbound = gen_outbound(node)
if outbound then table.insert(outbounds, outbound) end
routing = {
domainStrategy = "AsIs",
domainMatcher = "hybrid",
rules = {}
}
end
end
if dns_server or dns_fakedns then
table.insert(outbounds, {
protocol = "dns",
tag = "dns-out"
})
local rules = {}
dns = {
tag = "dns-in1",
disableCache = (dns_cache and dns_cache == "0") and true or false,
disableFallback = true,
disableFallbackIfMatch = true,
servers = {
dns_server
},
@@ -537,18 +553,12 @@ if dns_server or dns_fakedns then
dns.hosts = {
[doh_host] = dns_server
}
if not redir_port and not dns_socks_port then
doh_url = doh_url:gsub("https://", "https+local://")
end
dns.servers = {
doh_url
}
end
if dns_tcp_server then
if not redir_port and not dns_socks_port then
dns_tcp_server = dns_tcp_server:gsub("tcp://", "tcp+local://")
end
dns.servers = {
dns_tcp_server
}
@@ -566,6 +576,20 @@ if dns_server or dns_fakedns then
}
end
local nodes_domain = {}
local nodes_domain_text = sys.exec('uci show passwall2 | grep ".address=" | cut -d "\'" -f 2 | grep "[a-zA-Z]$" | sort -u')
string.gsub(nodes_domain_text, '[^' .. "\r\n" .. ']+', function(w)
table.insert(nodes_domain, w)
table.insert(dns_direct_domains, w)
end)
table.insert(dns.servers, {
address = local_dns_address,
port = tonumber(local_dns_port),
domains = #dns_direct_domains > 0 and dns_direct_domains or nil,
--expectIPs = #dns_direct_expectIPs > 0 and dns_direct_expectIPs or nil
})
if dns_listen_port then
table.insert(inbounds, {
listen = "127.0.0.1",
@@ -588,36 +612,9 @@ if dns_server or dns_fakedns then
outboundTag = "dns-out"
})
if dns_socks_address and dns_socks_port then
table.insert(outbounds, 1, {
tag = "out",
protocol = "socks",
streamSettings = {
network = "tcp",
security = "none"
},
settings = {
servers = {
{
address = dns_socks_address,
port = tonumber(dns_socks_port)
}
}
}
})
local outboundTag = "out"
table.insert(rules, {
type = "field",
inboundTag = {
"dns-in1"
},
outboundTag = outboundTag
})
end
if node_section and (proto and proto:find("tcp")) and redir_port and not dns_fakedns then
local outboundTag = node_section
local node = uci:get_all(appname, node_section)
if node_id and redir_port and not dns_fakedns then
local outboundTag = node_id
local node = uci:get_all(appname, node_id)
if node.protocol == "_shunt" then
outboundTag = "default"
end
@@ -629,6 +626,22 @@ if dns_server or dns_fakedns then
outboundTag = outboundTag
})
end
if nodes_domain and #nodes_domain > 0 then
table.insert(rules, {
type = "field",
domains = nodes_domain,
outboundTag = "direct"
})
end
table.insert(rules, {
type = "field",
ip = {
local_dns_ip
},
outboundTag = "direct"
})
if not routing then
routing = {
@@ -678,5 +691,25 @@ if inbounds or outbounds then
}
]]--
}
table.insert(outbounds, {
protocol = "dns",
tag = "dns-out"
})
table.insert(outbounds, {
protocol = "freedom",
tag = "direct",
settings = {
domainStrategy = "UseIPv4"
},
streamSettings = {
sockopt = {
mark = 255
}
}
})
table.insert(outbounds, {
protocol = "blackhole",
tag = "blackhole"
})
print(jsonc.stringify(config, 1))
end

View File

@@ -1,4 +1,4 @@
local api = require "luci.model.cbi.passwall.api.api"
local api = require "luci.model.cbi.passwall2.api.api"
local jsonc = api.jsonc
local inbounds = {}
local outbounds = {}
@@ -98,7 +98,7 @@ table.insert(outbounds, {
local config = {
log = {
-- error = string.format("/tmp/etc/passwall/%s.log", node[".name"]),
-- error = string.format("/tmp/etc/passwall2/%s.log", node[".name"]),
loglevel = "warning"
},
-- 传入连接

View File

@@ -1,5 +1,5 @@
module("luci.model.cbi.passwall.api.hysteria", package.seeall)
local api = require "luci.model.cbi.passwall.api.api"
module("luci.model.cbi.passwall2.api.hysteria", package.seeall)
local api = require "luci.model.cbi.passwall2.api.api"
local fs = api.fs
local sys = api.sys
local util = api.util
@@ -96,9 +96,9 @@ function to_move(file)
}
end
local flag = sys.call('pgrep -af "passwall/.*hysteria" >/dev/null')
local flag = sys.call('pgrep -af "passwall2/.*hysteria" >/dev/null')
if flag == 0 then
sys.call("/etc/init.d/passwall stop")
sys.call("/etc/init.d/passwall2 stop")
end
local old_app_size = 0
@@ -120,7 +120,7 @@ function to_move(file)
sys.call("/bin/rm -rf /tmp/hysteria_download.*")
if flag == 0 then
sys.call("/etc/init.d/passwall restart >/dev/null 2>&1 &")
sys.call("/etc/init.d/passwall2 restart >/dev/null 2>&1 &")
end
if not result or not fs.access(app_path) then

View File

@@ -1,5 +1,5 @@
module("luci.model.cbi.passwall.api.v2ray", package.seeall)
local api = require "luci.model.cbi.passwall.api.api"
module("luci.model.cbi.passwall2.api.v2ray", package.seeall)
local api = require "luci.model.cbi.passwall2.api.api"
local fs = api.fs
local sys = api.sys
local util = api.util
@@ -143,9 +143,9 @@ function to_move(file)
}
end
local flag = sys.call('pgrep -af "passwall/.*v2ray" >/dev/null')
local flag = sys.call('pgrep -af "passwall2/.*v2ray" >/dev/null')
if flag == 0 then
sys.call("/etc/init.d/passwall stop")
sys.call("/etc/init.d/passwall2 stop")
end
local old_app_size = 0
@@ -167,7 +167,7 @@ function to_move(file)
sys.call("/bin/rm -rf /tmp/v2ray_extract.*")
if flag == 0 then
sys.call("/etc/init.d/passwall restart >/dev/null 2>&1 &")
sys.call("/etc/init.d/passwall2 restart >/dev/null 2>&1 &")
end
if not result or not fs.access(app_path) then

View File

@@ -1,5 +1,5 @@
module("luci.model.cbi.passwall.api.xray", package.seeall)
local api = require "luci.model.cbi.passwall.api.api"
module("luci.model.cbi.passwall2.api.xray", package.seeall)
local api = require "luci.model.cbi.passwall2.api.api"
local fs = api.fs
local sys = api.sys
local util = api.util
@@ -143,9 +143,9 @@ function to_move(file)
}
end
local flag = sys.call('pgrep -af "passwall/.*xray" >/dev/null')
local flag = sys.call('pgrep -af "passwall2/.*xray" >/dev/null')
if flag == 0 then
sys.call("/etc/init.d/passwall stop")
sys.call("/etc/init.d/passwall2 stop")
end
local old_app_size = 0
@@ -167,7 +167,7 @@ function to_move(file)
sys.call("/bin/rm -rf /tmp/xray_extract.*")
if flag == 0 then
sys.call("/etc/init.d/passwall restart >/dev/null 2>&1 &")
sys.call("/etc/init.d/passwall2 restart >/dev/null 2>&1 &")
end
if not result or not fs.access(app_path) then

View File

@@ -0,0 +1,55 @@
local api = require "luci.model.cbi.passwall2.api.api"
local appname = api.appname
local sys = api.sys
local has_chnlist = api.fs.access("/usr/share/passwall2/rules/chnlist")
m = Map(appname)
-- [[ ACLs Settings ]]--
s = m:section(TypedSection, "acl_rule", translate("ACLs"), "<font color='red'>" .. translate("ACLs is a tools which used to designate specific IP proxy mode.") .. "</font>")
s.template = "cbi/tblsection"
s.sortable = true
s.anonymous = true
s.addremove = true
s.extedit = api.url("acl_config", "%s")
function s.create(e, t)
t = TypedSection.create(e, t)
luci.http.redirect(e.extedit:format(t))
end
---- Enable
o = s:option(Flag, "enabled", translate("Enable"))
o.default = 1
o.rmempty = false
---- Remarks
o = s:option(Value, "remarks", translate("Remarks"))
o.rmempty = true
local mac_t = {}
sys.net.mac_hints(function(e, t)
mac_t[e] = {
ip = t,
mac = e
}
end)
o = s:option(DummyValue, "sources", translate("Source"))
o.rawhtml = true
o.cfgvalue = function(t, n)
local e = ''
local v = Value.cfgvalue(t, n) or ''
string.gsub(v, '[^' .. " " .. ']+', function(w)
local a = w
if mac_t[w] then
a = a .. ' (' .. mac_t[w].ip .. ')'
end
if #e > 0 then
e = e .. "<br />"
end
e = e .. a
end)
return e
end
return m

View File

@@ -1,9 +1,6 @@
local api = require "luci.model.cbi.passwall.api.api"
local api = require "luci.model.cbi.passwall2.api.api"
local appname = api.appname
local sys = api.sys
local has_v2ray = api.is_finded("v2ray")
local has_xray = api.is_finded("xray")
local has_chnlist = api.fs.access("/usr/share/passwall/rules/chnlist")
m = Map(appname)
@@ -12,8 +9,6 @@ for k, e in ipairs(api.get_valid_nodes()) do
nodes_table[#nodes_table + 1] = e
end
local global_proxy_mode = (m:get("@global[0]", "tcp_proxy_mode") or "") .. (m:get("@global[0]", "udp_proxy_mode") or "")
local dynamicList_write = function(self, section, value)
local t = {}
local t2 = {}
@@ -135,36 +130,6 @@ sources.validate = function(self, value, t)
end
sources.write = dynamicList_write
---- TCP Proxy Mode
tcp_proxy_mode = s:option(ListValue, "tcp_proxy_mode", translatef("%s Proxy Mode", "TCP"))
tcp_proxy_mode.default = "default"
tcp_proxy_mode.rmempty = false
tcp_proxy_mode:value("default", translate("Default"))
tcp_proxy_mode:value("disable", translate("No Proxy"))
tcp_proxy_mode:value("global", translate("Global Proxy"))
if has_chnlist and global_proxy_mode:find("returnhome") then
tcp_proxy_mode:value("returnhome", translate("China List"))
else
tcp_proxy_mode:value("gfwlist", translate("GFW List"))
tcp_proxy_mode:value("chnroute", translate("Not China List"))
end
tcp_proxy_mode:value("direct/proxy", translate("Only use direct/proxy list"))
---- UDP Proxy Mode
udp_proxy_mode = s:option(ListValue, "udp_proxy_mode", translatef("%s Proxy Mode", "UDP"))
udp_proxy_mode.default = "default"
udp_proxy_mode.rmempty = false
udp_proxy_mode:value("default", translate("Default"))
udp_proxy_mode:value("disable", translate("No Proxy"))
udp_proxy_mode:value("global", translate("Global Proxy"))
if has_chnlist and global_proxy_mode:find("returnhome") then
udp_proxy_mode:value("returnhome", translate("China List"))
else
udp_proxy_mode:value("gfwlist", translate("GFW List"))
udp_proxy_mode:value("chnroute", translate("Not China List"))
end
udp_proxy_mode:value("direct/proxy", translate("Only use direct/proxy list"))
---- TCP No Redir Ports
o = s:option(Value, "tcp_no_redir_ports", translate("TCP No Redir Ports"))
o.default = "default"
@@ -179,67 +144,18 @@ o:value("disable", translate("No patterns are used"))
o:value("default", translate("Default"))
o:value("1:65535", translate("All"))
---- TCP Proxy Drop Ports
o = s:option(Value, "tcp_proxy_drop_ports", translate("TCP Proxy Drop Ports"))
o.default = "default"
o:value("disable", translate("No patterns are used"))
o:value("default", translate("Default"))
---- UDP Proxy Drop Ports
o = s:option(Value, "udp_proxy_drop_ports", translate("UDP Proxy Drop Ports"))
o.default = "default"
o:value("disable", translate("No patterns are used"))
o:value("default", translate("Default"))
o:value("80,443", translate("QUIC"))
---- TCP Redir Ports
o = s:option(Value, "tcp_redir_ports", translate("TCP Redir Ports"))
o.default = "default"
o:value("default", translate("Default"))
o:value("1:65535", translate("All"))
o:value("80,443", "80,443")
o:value("80:65535", "80 " .. translate("or more"))
o:value("1:443", "443 " .. translate("or less"))
---- UDP Redir Ports
o = s:option(Value, "udp_redir_ports", translate("UDP Redir Ports"))
o.default = "default"
o:value("default", translate("Default"))
o:value("1:65535", translate("All"))
o:value("53", "53")
tcp_node = s:option(ListValue, "tcp_node", "<a style='color: red'>" .. translate("TCP Node") .. "</a>")
tcp_node.default = "default"
tcp_node:value("default", translate("Default"))
udp_node = s:option(ListValue, "udp_node", "<a style='color: red'>" .. translate("UDP Node") .. "</a>")
udp_node.default = "default"
udp_node:value("default", translate("Default"))
udp_node:value("tcp", translate("Same as the tcp node"))
node = s:option(ListValue, "node", "<a style='color: red'>" .. translate("Node") .. "</a>")
node.default = "default"
node:value("default", translate("Default"))
for k, v in pairs(nodes_table) do
tcp_node:value(v.id, v["remark"])
udp_node:value(v.id, v["remark"])
node:value(v.id, v["remark"])
end
---- DNS Forward Mode
o = s:option(ListValue, "dns_mode", translate("Filter Mode"))
o:depends({ tcp_node = "default", ['!reverse'] = true })
if api.is_finded("dns2socks") then
o:value("dns2socks", "dns2socks")
end
if has_v2ray then
o:value("v2ray", "V2ray")
end
if has_xray then
o:value("xray", "Xray")
end
o = s:option(ListValue, "v2ray_dns_mode", " ")
o = s:option(ListValue, "dns_protocol", translate("DNS Protocol"))
o:value("tcp", "TCP")
o:value("doh", "DoH")
o:depends("dns_mode", "v2ray")
o:depends("dns_mode", "xray")
o:depends({ node = "default", ['!reverse'] = true })
---- DNS Forward
o = s:option(Value, "dns_forward", translate("Remote DNS"))
@@ -250,10 +166,8 @@ o:value("8.8.8.8", "8.8.8.8 (Google DNS)")
o:value("8.8.4.4", "8.8.4.4 (Google DNS)")
o:value("208.67.222.222", "208.67.222.222 (Open DNS)")
o:value("208.67.220.220", "208.67.220.220 (Open DNS)")
o:depends("dns_mode", "dns2socks")
o:depends("v2ray_dns_mode", "tcp")
o:depends("dns_protocol", "tcp")
if has_v2ray or has_xray then
---- DoH
o = s:option(Value, "dns_doh", translate("DoH request address"))
o:value("https://cloudflare-dns.com/dns-query,1.1.1.1", "CloudFlare")
@@ -286,11 +200,11 @@ o.validate = function(self, value, t)
end
return nil, translate("DoH request address") .. " " .. translate("Format must be:") .. " URL,IP"
end
o:depends("v2ray_dns_mode", "doh")
end
o:depends("dns_protocol", "doh")
o = s:option(Value, "dns_client_ip", translate("EDNS Client Subnet"))
o.datatype = "ipaddr"
o:depends("v2ray_dns_mode", "doh")
o:depends("dns_protocol", "tcp")
o:depends("dns_protocol", "doh")
return m

View File

@@ -1,4 +1,4 @@
local api = require "luci.model.cbi.passwall.api.api"
local api = require "luci.model.cbi.passwall2.api.api"
local appname = api.appname
m = Map(appname)
@@ -11,7 +11,6 @@ s = m:section(TypedSection, "global_app", translate("App Update"),
s.anonymous = true
s:append(Template(appname .. "/app_update/v2ray_version"))
s:append(Template(appname .. "/app_update/xray_version"))
s:append(Template(appname .. "/app_update/trojan_go_version"))
s:append(Template(appname .. "/app_update/brook_version"))
s:append(Template(appname .. "/app_update/hysteria_version"))
@@ -23,10 +22,6 @@ o = s:option(Value, "xray_file", translatef("%s App Path", "Xray"))
o.default = "/usr/bin/xray"
o.rmempty = false
o = s:option(Value, "trojan_go_file", translatef("%s App Path", "Trojan-Go"))
o.default = "/usr/bin/trojan-go"
o.rmempty = false
o = s:option(Value, "brook_file", translatef("%s App Path", "Brook"))
o.default = "/usr/bin/brook"
o.rmempty = false

View File

@@ -1,4 +1,4 @@
local api = require "luci.model.cbi.passwall.api.api"
local api = require "luci.model.cbi.passwall2.api.api"
local appname = api.appname
local nodes_table = {}
@@ -29,7 +29,7 @@ o = s:option(Value, "retry_num", translate("Timeout retry num"))
o.datatype = "uinteger"
o.default = 3
o = s:option(DynamicList, "tcp_node", "TCP " .. translate("List of backup nodes"))
o = s:option(DynamicList, "node", translate("List of backup nodes"))
for k, v in pairs(nodes_table) do
if v.node_type == "normal" then
o:value(v.id, v["remark"])
@@ -54,9 +54,9 @@ function o.write(self, section, value)
return DynamicList.write(self, section, t)
end
o = s:option(Flag, "restore_switch", "TCP " .. translate("Restore Switch"), translate("When detects main node is available, switch back to the main node."))
o = s:option(Flag, "restore_switch", translate("Restore Switch"), translate("When detects main node is available, switch back to the main node."))
o = s:option(ListValue, "shunt_logic", "TCP " .. translate("If the main node is V2ray/Xray shunt"))
o = s:option(ListValue, "shunt_logic", translate("If the main node is shunt"))
o:value("0", translate("Switch it"))
o:value("1", translate("Applying to the default node"))
o:value("2", translate("Applying to the default preproxy node"))

View File

@@ -0,0 +1,261 @@
local api = require "luci.model.cbi.passwall2.api.api"
local appname = api.appname
local uci = api.uci
local datatypes = api.datatypes
local has_v2ray = api.is_finded("v2ray")
local has_xray = api.is_finded("xray")
m = Map(appname)
local nodes_table = {}
for k, e in ipairs(api.get_valid_nodes()) do
nodes_table[#nodes_table + 1] = e
end
local socks_table = {}
uci:foreach(appname, "socks", function(s)
if s.enabled == "1" and s.node then
local id, remarks
for k, n in pairs(nodes_table) do
if (s.node == n.id) then
remarks = n["remark"]; break
end
end
id = "127.0.0.1" .. ":" .. s.port
socks_table[#socks_table + 1] = {
id = id,
remarks = id .. " - " .. (remarks or translate("Misconfigured"))
}
end
end)
local doh_validate = function(self, value, t)
if value ~= "" then
local flag = 0
local util = require "luci.util"
local val = util.split(value, ",")
local url = val[1]
val[1] = nil
for i = 1, #val do
local v = val[i]
if v then
if not datatypes.ipmask4(v) then
flag = 1
end
end
end
if flag == 0 then
return value
end
end
return nil, translate("DoH request address") .. " " .. translate("Format must be:") .. " URL,IP"
end
m:append(Template(appname .. "/global/status"))
s = m:section(TypedSection, "global")
s.anonymous = true
s.addremove = false
s:tab("Main", translate("Main"))
-- [[ Global Settings ]]--
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.description = ""
local current_node = luci.sys.exec(string.format("[ -f '/tmp/etc/%s/id/TCP' ] && echo -n $(cat /tmp/etc/%s/id/TCP)", appname, appname))
if current_node and current_node ~= "" and current_node ~= "nil" then
local n = uci:get_all(appname, current_node)
if n then
if tonumber(m:get("@auto_switch[0]", "enable") or 0) == 1 then
local remarks = api.get_full_node_remarks(n)
local url = api.url("node_config", current_node)
node.description = node.description .. translatef("Current node: %s", string.format('<a href="%s">%s</a>', url, remarks)) .. "<br />"
end
end
end
node:value("nil", translate("Close"))
-- 分流
if (has_v2ray or has_xray) and #nodes_table > 0 then
local normal_list = {}
local shunt_list = {}
for k, v in pairs(nodes_table) do
if v.node_type == "normal" then
normal_list[#normal_list + 1] = v
end
if v.protocol and v.protocol == "_shunt" then
shunt_list[#shunt_list + 1] = v
end
end
for k, v in pairs(shunt_list) do
uci:foreach(appname, "shunt_rules", function(e)
local id = e[".name"]
if id and e.remarks then
o = s:taboption("Main", ListValue, v.id .. "." .. id .. "_node", string.format('* <a href="%s" target="_blank">%s</a>', api.url("shunt_rules", id), e.remarks))
o:depends("node", v.id)
o:value("nil", translate("Close"))
o:value("_default", translate("Default"))
o:value("_direct", translate("Direct Connection"))
o:value("_blackhole", translate("Blackhole"))
for k1, v1 in pairs(normal_list) do
o:value(v1.id, v1["remark"])
end
o.cfgvalue = function(self, section)
return m:get(v.id, id) or "nil"
end
o.write = function(self, section, value)
m:set(v.id, id, value)
end
end
end)
local id = "default_node"
o = s:taboption("Main", ListValue, v.id .. "." .. id, string.format('* <a style="color:red">%s</a>', translate("Default")))
o:depends("node", v.id)
o:value("_direct", translate("Direct Connection"))
o:value("_blackhole", translate("Blackhole"))
for k1, v1 in pairs(normal_list) do
o:value(v1.id, v1["remark"])
end
o.cfgvalue = function(self, section)
return m:get(v.id, id) or "nil"
end
o.write = function(self, section, value)
m:set(v.id, id, value)
end
local id = "main_node"
o = s:taboption("Main", ListValue, v.id .. "." .. 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:depends("node", v.id)
o:value("nil", translate("Close"))
for k1, v1 in pairs(normal_list) do
o:value(v1.id, v1["remark"])
end
o.cfgvalue = function(self, section)
return m:get(v.id, id) or "nil"
end
o.write = function(self, section, value)
m:set(v.id, id, value)
end
end
end
s:tab("DNS", translate("DNS"))
o = s:taboption("DNS", ListValue, "dns_protocol", translate("DNS Protocol"))
o:value("tcp", "TCP")
o:value("doh", "DoH")
o:value("fakedns", "FakeDNS")
---- DoH
o = s:taboption("DNS", Value, "up_trust_doh", translate("DoH request address"))
o:value("https://cloudflare-dns.com/dns-query,1.1.1.1", "CloudFlare")
o:value("https://security.cloudflare-dns.com/dns-query,1.1.1.2", "CloudFlare-Security")
o:value("https://doh.opendns.com/dns-query,208.67.222.222", "OpenDNS")
o:value("https://dns.google/dns-query,8.8.8.8", "Google")
o:value("https://doh.libredns.gr/dns-query,116.202.176.26", "LibreDNS")
o:value("https://doh.libredns.gr/ads,116.202.176.26", "LibreDNS (No Ads)")
o:value("https://dns.quad9.net/dns-query,9.9.9.9", "Quad9-Recommended")
o:value("https://dns.adguard.com/dns-query,176.103.130.130", "AdGuard")
o.default = "https://cloudflare-dns.com/dns-query,1.1.1.1"
o.validate = doh_validate
o:depends("dns_protocol", "doh")
---- DNS Forward
o = s:taboption("DNS", Value, "dns_forward", translate("Remote DNS"))
--o.description = translate("IP:Port mode acceptable, multi value split with english comma.") .. " " .. translate("If you use dns2socks, only the first one is valid.")
o.datatype = "or(ipaddr,ipaddrport)"
o.default = "1.1.1.1"
o:value("1.1.1.1", "1.1.1.1 (CloudFlare DNS)")
o:value("1.1.1.2", "1.1.1.2 (CloudFlare DNS)")
o:value("8.8.8.8", "8.8.8.8 (Google DNS)")
o:value("8.8.4.4", "8.8.4.4 (Google DNS)")
o:value("208.67.222.222", "208.67.222.222 (Open DNS)")
o:value("208.67.220.220", "208.67.220.220 (Open DNS)")
o:depends("dns_protocol", "tcp")
o = s:taboption("DNS", Value, "dns_client_ip", translate("EDNS Client Subnet"))
o.description = translate("Notify the DNS server when the DNS query is notified, the location of the client (cannot be a private IP address).") .. "<br />" ..
translate("This feature requires the DNS server to support the Edns Client Subnet (RFC7871).")
o.datatype = "ipaddr"
o:depends("dns_protocol", "tcp")
o:depends("dns_protocol", "doh")
s:tab("log", translate("Log"))
o = s:taboption("log", Flag, "close_log", translate("Close Node Log"))
o.rmempty = false
loglevel = s:taboption("log", ListValue, "loglevel", translate("Log Level"))
loglevel.default = "warning"
loglevel:value("debug")
loglevel:value("info")
loglevel:value("warning")
loglevel:value("error")
s:tab("faq", "FAQ")
o = s:taboption("faq", DummyValue, "")
o.template = appname .. "/global/faq"
-- [[ Socks Server ]]--
o = s:taboption("Main", Flag, "socks_enabled", "Socks " .. translate("Main switch"))
o.rmempty = false
s = m:section(TypedSection, "socks", translate("Socks Config"))
s.anonymous = true
s.addremove = true
s.template = "cbi/tblsection"
function s.create(e, t)
TypedSection.create(e, api.gen_uuid())
end
o = s: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.default = 1
o.rmempty = false
socks_node = s:option(ListValue, "node", translate("Socks Node"))
local n = 0
uci:foreach(appname, "socks", function(s)
if s[".name"] == section then
return false
end
n = n + 1
end)
o = s:option(Value, "port", "Socks " .. translate("Listen Port"))
o.default = n + 1080
o.datatype = "port"
o.rmempty = false
if has_v2ray or has_xray then
o = s: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_v2ray or has_xray then
socks_node:value(v.id, v["remark"])
end
else
socks_node:value(v.id, v["remark"])
end
end
m:append(Template(appname .. "/global/footer"))
return m

View File

@@ -1,4 +1,4 @@
local api = require "luci.model.cbi.passwall.api.api"
local api = require "luci.model.cbi.passwall2.api.api"
local appname = api.appname
f = SimpleForm(appname)

View File

@@ -1,4 +1,4 @@
local api = require "luci.model.cbi.passwall.api.api"
local api = require "luci.model.cbi.passwall2.api.api"
local appname = api.appname
local uci = api.uci
@@ -63,9 +63,9 @@ s = m:section(NamedSection, arg[1], "nodes", "")
s.addremove = false
s.dynamic = false
share = s:option(DummyValue, "passwall", " ")
share = s:option(DummyValue, "passwall2", " ")
share.rawhtml = true
share.template = "passwall/node_list/link_share_man"
share.template = "passwall2/node_list/link_share_man"
share.value = arg[1]
remarks = s:option(Value, "remarks", translate("Node Remarks"))
@@ -73,9 +73,6 @@ remarks.default = translate("Remarks")
remarks.rmempty = false
type = s:option(ListValue, "type", translate("Type"))
if api.is_finded("ipt2socks") then
type:value("Socks", translate("Socks"))
end
if api.is_finded("ss-redir") then
type:value("SS", translate("Shadowsocks Libev"))
end
@@ -94,17 +91,6 @@ end
if api.is_finded("brook") then
type:value("Brook", translate("Brook"))
end
--[[
if api.is_finded("trojan-plus") or api.is_finded("trojan") then
type:value("Trojan", translate("Trojan"))
end
]]--
if api.is_finded("trojan-plus") then
type:value("Trojan-Plus", translate("Trojan-Plus"))
end
if api.is_finded("trojan-go") then
type:value("Trojan-Go", translate("Trojan-Go"))
end
if api.is_finded("naive") then
type:value("Naiveproxy", translate("NaiveProxy"))
end
@@ -141,23 +127,25 @@ balancing_node:depends("protocol", "_balancing")
-- 分流
uci:foreach(appname, "shunt_rules", function(e)
o = s:option(ListValue, e[".name"], string.format('* <a href="%s" target="_blank">%s</a>', api.url("shunt_rules", e[".name"]), translate(e.remarks)))
o:value("nil", translate("Close"))
o:value("_default", translate("Default"))
o:value("_direct", translate("Direct Connection"))
o:value("_blackhole", translate("Blackhole"))
o:depends("protocol", "_shunt")
if e[".name"] and e.remarks then
o = s:option(ListValue, e[".name"], string.format('* <a href="%s" target="_blank">%s</a>', api.url("shunt_rules", e[".name"]), e.remarks))
o:value("nil", translate("Close"))
o:value("_default", translate("Default"))
o:value("_direct", translate("Direct Connection"))
o:value("_blackhole", translate("Blackhole"))
o:depends("protocol", "_shunt")
if #nodes_table > 0 then
_proxy_tag = s:option(ListValue, e[".name"] .. "_proxy_tag", string.format('* <a style="color:red">%s</a>', translate(e.remarks) .. " " .. translate("Preproxy")))
_proxy_tag:value("nil", translate("Close"))
_proxy_tag:value("default", translate("Default"))
_proxy_tag:value("main", translate("Default Preproxy"))
_proxy_tag.default = "nil"
if #nodes_table > 0 then
_proxy_tag = s:option(ListValue, e[".name"] .. "_proxy_tag", string.format('* <a style="color:red">%s</a>', e.remarks .. " " .. translate("Preproxy")))
_proxy_tag:value("nil", translate("Close"))
_proxy_tag:value("default", translate("Default"))
_proxy_tag:value("main", translate("Default Preproxy"))
_proxy_tag.default = "nil"
for k, v in pairs(nodes_table) do
o:value(v.id, v.remarks)
_proxy_tag:depends(e[".name"], v.id)
for k, v in pairs(nodes_table) do
o:value(v.id, v.remarks)
_proxy_tag:depends(e[".name"], v.id)
end
end
end
end)
@@ -232,14 +220,10 @@ end
address = s:option(Value, "address", translate("Address (Support Domain Name)"))
address.rmempty = false
address:depends("type", "Socks")
address:depends("type", "SS")
address:depends("type", "SS-Rust")
address:depends("type", "SSR")
address:depends("type", "Brook")
address:depends("type", "Trojan")
address:depends("type", "Trojan-Plus")
address:depends("type", "Trojan-Go")
address:depends("type", "Naiveproxy")
address:depends("type", "Hysteria")
address:depends({ type = "V2ray", protocol = "vmess" })
@@ -258,14 +242,10 @@ address:depends({ type = "Xray", protocol = "trojan" })
--[[
use_ipv6 = s:option(Flag, "use_ipv6", translate("Use IPv6"))
use_ipv6.default = 0
use_ipv6:depends("type", "Socks")
use_ipv6:depends("type", "SS")
use_ipv6:depends("type", "SS-Rust")
use_ipv6:depends("type", "SSR")
use_ipv6:depends("type", "Brook")
use_ipv6:depends("type", "Trojan")
use_ipv6:depends("type", "Trojan-Plus")
use_ipv6:depends("type", "Trojan-Go")
use_ipv6:depends("type", "Hysteria")
use_ipv6:depends({ type = "V2ray", protocol = "vmess" })
use_ipv6:depends({ type = "V2ray", protocol = "vless" })
@@ -284,14 +264,10 @@ use_ipv6:depends({ type = "Xray", protocol = "trojan" })
port = s:option(Value, "port", translate("Port"))
port.datatype = "port"
port.rmempty = false
port:depends("type", "Socks")
port:depends("type", "SS")
port:depends("type", "SS-Rust")
port:depends("type", "SSR")
port:depends("type", "Brook")
port:depends("type", "Trojan")
port:depends("type", "Trojan-Plus")
port:depends("type", "Trojan-Go")
port:depends("type", "Naiveproxy")
port:depends("type", "Hysteria")
port:depends({ type = "V2ray", protocol = "vmess" })
@@ -308,7 +284,6 @@ port:depends({ type = "Xray", protocol = "shadowsocks" })
port:depends({ type = "Xray", protocol = "trojan" })
username = s:option(Value, "username", translate("Username"))
username:depends("type", "Socks")
username:depends("type", "Naiveproxy")
username:depends({ type = "V2ray", protocol = "http" })
username:depends({ type = "V2ray", protocol = "socks" })
@@ -317,14 +292,10 @@ username:depends({ type = "Xray", protocol = "socks" })
password = s:option(Value, "password", translate("Password"))
password.password = true
password:depends("type", "Socks")
password:depends("type", "SS")
password:depends("type", "SS-Rust")
password:depends("type", "SSR")
password:depends("type", "Brook")
password:depends("type", "Trojan")
password:depends("type", "Trojan-Plus")
password:depends("type", "Trojan-Go")
password:depends("type", "Naiveproxy")
password:depends({ type = "V2ray", protocol = "http" })
password:depends({ type = "V2ray", protocol = "socks" })
@@ -462,9 +433,6 @@ tcp_fast_open:value("true")
tcp_fast_open:depends("type", "SS")
tcp_fast_open:depends("type", "SS-Rust")
tcp_fast_open:depends("type", "SSR")
tcp_fast_open:depends("type", "Trojan")
tcp_fast_open:depends("type", "Trojan-Plus")
tcp_fast_open:depends("type", "Trojan-Go")
ss_plugin = s:option(ListValue, "ss_plugin", translate("plugin"))
ss_plugin:value("none", translate("none"))
@@ -500,15 +468,6 @@ uuid:depends({ type = "Xray", protocol = "vless" })
tls = s:option(Flag, "tls", translate("TLS"))
tls.default = 0
tls.validate = function(self, value, t)
if value then
local type = type:formvalue(t) or ""
if value == "0" and (type == "Trojan" or type == "Trojan-Plus") then
return nil, translate("Original Trojan only supported 'tls', please choose 'tls'.")
end
return value
end
end
tls:depends({ type = "V2ray", protocol = "vmess" })
tls:depends({ type = "V2ray", protocol = "vless" })
tls:depends({ type = "V2ray", protocol = "socks" })
@@ -519,9 +478,6 @@ tls:depends({ type = "Xray", protocol = "vless" })
tls:depends({ type = "Xray", protocol = "socks" })
tls:depends({ type = "Xray", protocol = "trojan" })
tls:depends({ type = "Xray", protocol = "shadowsocks" })
tls:depends("type", "Trojan")
tls:depends("type", "Trojan-Plus")
tls:depends("type", "Trojan-Go")
xtls = s:option(Flag, "xtls", translate("XTLS"))
xtls.default = 0
@@ -547,27 +503,6 @@ alpn:value("http/1.1")
alpn:depends({ type = "V2ray", tls = true })
alpn:depends({ type = "Xray", tls = true })
-- [[ TLS部分 ]] --
tls_sessionTicket = s:option(Flag, "tls_sessionTicket", translate("Session Ticket"))
tls_sessionTicket.default = "0"
tls_sessionTicket:depends({ type = "Trojan", tls = true })
tls_sessionTicket:depends({ type = "Trojan-Plus", tls = true })
tls_sessionTicket:depends({ type = "Trojan-Go", tls = true })
trojan_go_fingerprint = s:option(ListValue, "trojan_go_fingerprint", translate("Finger Print"))
trojan_go_fingerprint:value("disable", translate("Disable"))
trojan_go_fingerprint:value("firefox")
trojan_go_fingerprint:value("chrome")
trojan_go_fingerprint:value("ios")
trojan_go_fingerprint.default = "disable"
trojan_go_fingerprint:depends({ type = "Trojan-Go", tls = true })
function trojan_go_fingerprint.cfgvalue(self, section)
return m:get(section, "fingerprint")
end
function trojan_go_fingerprint.write(self, section, value)
m:set(section, "fingerprint", value)
end
tls_serverName = s:option(Value, "tls_serverName", translate("Domain"))
tls_serverName:depends("tls", true)
tls_serverName:depends("type", "Hysteria")
@@ -592,34 +527,6 @@ function xray_fingerprint.write(self, section, value)
m:set(section, "fingerprint", value)
end
trojan_transport = s:option(ListValue, "trojan_transport", translate("Transport"))
trojan_transport:value("original", translate("Original"))
trojan_transport:value("ws", "WebSocket")
trojan_transport.default = "original"
trojan_transport:depends("type", "Trojan-Go")
trojan_plugin = s:option(ListValue, "plugin_type", translate("Transport Plugin"))
trojan_plugin:value("plaintext", "Plain Text")
trojan_plugin:value("shadowsocks", "ShadowSocks")
trojan_plugin:value("other", "Other")
trojan_plugin.default = "plaintext"
trojan_plugin:depends({ tls = false, trojan_transport = "original" })
trojan_plugin_cmd = s:option(Value, "plugin_cmd", translate("Plugin Binary"))
trojan_plugin_cmd.placeholder = "eg: /usr/bin/v2ray-plugin"
trojan_plugin_cmd:depends({ plugin_type = "shadowsocks" })
trojan_plugin_cmd:depends({ plugin_type = "other" })
trojan_plugin_op = s:option(Value, "plugin_option", translate("Plugin Option"))
trojan_plugin_op.placeholder = "eg: obfs=http;obfs-host=www.baidu.com"
trojan_plugin_op:depends({ plugin_type = "shadowsocks" })
trojan_plugin_op:depends({ plugin_type = "other" })
trojan_plugin_arg = s:option(DynamicList, "plugin_arg", translate("Plugin Option Args"))
trojan_plugin_arg.placeholder = "eg: [\"-config\", \"test.json\"]"
trojan_plugin_arg:depends({ plugin_type = "shadowsocks" })
trojan_plugin_arg:depends({ plugin_type = "other" })
transport = s:option(ListValue, "transport", translate("Transport"))
transport:value("tcp", "TCP")
transport:value("mkcp", "mKCP")
@@ -704,12 +611,10 @@ mkcp_seed:depends("transport", "mkcp")
ws_host = s:option(Value, "ws_host", translate("WebSocket Host"))
ws_host:depends("transport", "ws")
ws_host:depends("ss_transport", "ws")
ws_host:depends("trojan_transport", "ws")
ws_path = s:option(Value, "ws_path", translate("WebSocket Path"))
ws_path:depends("transport", "ws")
ws_path:depends("ss_transport", "ws")
ws_path:depends("trojan_transport", "ws")
ws_path:depends({ type = "Brook", brook_protocol = "wsclient" })
ws_enableEarlyData = s:option(Flag, "ws_enableEarlyData", translate("Enable early data"))
@@ -791,24 +696,6 @@ grpc_initial_windows_size = s:option(Value, "grpc_initial_windows_size", transla
grpc_initial_windows_size.default = "0"
grpc_initial_windows_size:depends({ type = "Xray", transport = "grpc"})
-- [[ Trojan-Go Shadowsocks2 ]] --
ss_aead = s:option(Flag, "ss_aead", translate("Shadowsocks secondary encryption"))
ss_aead:depends("type", "Trojan-Go")
ss_aead.default = "0"
ss_aead_method = s:option(ListValue, "ss_aead_method", translate("Encrypt Method"))
for _, v in ipairs(encrypt_methods_ss_aead) do ss_aead_method:value(v, v) end
ss_aead_method.default = "aes-128-gcm"
ss_aead_method:depends("ss_aead", "1")
ss_aead_pwd = s:option(Value, "ss_aead_pwd", translate("Password"))
ss_aead_pwd.password = true
ss_aead_pwd:depends("ss_aead", "1")
-- [[ Trojan-Go Mux ]]--
mux = s:option(Flag, "smux", translate("Smux"))
mux:depends("type", "Trojan-Go")
-- [[ Mux ]]--
mux = s:option(Flag, "mux", translate("Mux"))
mux:depends({ type = "V2ray", protocol = "vmess" })

View File

@@ -1,4 +1,4 @@
local api = require "luci.model.cbi.passwall.api.api"
local api = require "luci.model.cbi.passwall2.api.api"
local appname = api.appname
local sys = api.sys
local datatypes = api.datatypes
@@ -38,22 +38,14 @@ function s.remove(e, t)
m:del(s[".name"])
end
end)
m.uci:foreach(appname, "haproxy_config", function(s)
if s["lbss"] and s["lbss"] == t then
m:del(s[".name"])
end
end)
m.uci:foreach(appname, "acl_rule", function(s)
if s["tcp_node"] and s["tcp_node"] == t then
m:set(s[".name"], "tcp_node", "default")
end
if s["udp_node"] and s["udp_node"] == t then
m:set(s[".name"], "udp_node", "default")
if s["node"] and s["node"] == t then
m:set(s[".name"], "node", "default")
end
end)
for k, v in ipairs(m:get("@auto_switch[0]", "tcp_node") or {}) do
for k, v in ipairs(m:get("@auto_switch[0]", "node") or {}) do
if v and v == t then
sys.call(string.format("uci -q del_list %s.@auto_switch[0].tcp_node='%s'", appname, v))
sys.call(string.format("uci -q del_list %s.@auto_switch[0].node='%s'", appname, v))
end
end
TypedSection.remove(e, t)
@@ -62,11 +54,8 @@ function s.remove(e, t)
if node0 then
new_node = node0[".name"]
end
if (m:get("@global[0]", "tcp_node") or "nil") == t then
m:set('@global[0]', "tcp_node", new_node)
end
if (m:get("@global[0]", "udp_node") or "nil") == t then
m:set('@global[0]', "udp_node", new_node)
if (m:get("@global[0]", "node") or "nil") == t then
m:set('@global[0]', "node", new_node)
end
end

View File

@@ -1,33 +1,22 @@
local api = require "luci.model.cbi.passwall.api.api"
local api = require "luci.model.cbi.passwall2.api.api"
local appname = api.appname
local has_ss = api.is_finded("ss-redir")
local has_ss_rust = api.is_finded("sslocal")
local has_trojan_plus = api.is_finded("trojan-plus")
local has_v2ray = api.is_finded("v2ray")
local has_xray = api.is_finded("xray")
local has_trojan_go = api.is_finded("trojan-go")
local ss_aead_type = {}
local trojan_type = {}
if has_ss then
ss_aead_type[#ss_aead_type + 1] = "shadowsocks-libev"
end
if has_ss_rust then
ss_aead_type[#ss_aead_type + 1] = "shadowsocks-rust"
end
if has_trojan_plus then
trojan_type[#trojan_type + 1] = "trojan-plus"
end
if has_v2ray then
trojan_type[#trojan_type + 1] = "v2ray"
ss_aead_type[#ss_aead_type + 1] = "v2ray"
end
if has_xray then
trojan_type[#trojan_type + 1] = "xray"
ss_aead_type[#ss_aead_type + 1] = "xray"
end
if has_trojan_go then
trojan_type[#trojan_type + 1] = "trojan-go"
end
m = Map(appname)
@@ -58,13 +47,6 @@ if #ss_aead_type > 0 then
end
end
if #trojan_type > 0 then
o = s:option(ListValue, "trojan_type", translate("Trojan Node Use Type"))
for key, value in pairs(trojan_type) do
o:value(value, translate(value:gsub("^%l",string.upper)))
end
end
---- Subscribe Delete All
o = s:option(Button, "_stop", translate("Delete All Subscribe Node"))
o.inputstyle = "remove"

View File

@@ -1,34 +1,23 @@
local api = require "luci.model.cbi.passwall.api.api"
local api = require "luci.model.cbi.passwall2.api.api"
local appname = api.appname
local sys = api.sys
local has_ss = api.is_finded("ss-redir")
local has_ss_rust = api.is_finded("sslocal")
local has_trojan_plus = api.is_finded("trojan-plus")
local has_v2ray = api.is_finded("v2ray")
local has_xray = api.is_finded("xray")
local has_trojan_go = api.is_finded("trojan-go")
local ss_aead_type = {}
local trojan_type = {}
if has_ss then
ss_aead_type[#ss_aead_type + 1] = "shadowsocks-libev"
end
if has_ss_rust then
ss_aead_type[#ss_aead_type + 1] = "shadowsocks-rust"
end
if has_trojan_plus then
trojan_type[#trojan_type + 1] = "trojan-plus"
end
if has_v2ray then
trojan_type[#trojan_type + 1] = "v2ray"
ss_aead_type[#ss_aead_type + 1] = "v2ray"
end
if has_xray then
trojan_type[#trojan_type + 1] = "xray"
ss_aead_type[#ss_aead_type + 1] = "xray"
end
if has_trojan_go then
trojan_type[#trojan_type + 1] = "trojan-go"
end
m = Map(appname)
m.redirect = api.url("node_subscribe")
@@ -76,15 +65,6 @@ if #ss_aead_type > 0 then
end
end
if #trojan_type > 0 then
o = s:option(ListValue, "trojan_type", translate("Trojan Node Use Type"))
o.default = "global"
o:value("global", translate("Use global config"))
for key, value in pairs(trojan_type) do
o:value(value, translate(value:gsub("^%l",string.upper)))
end
end
---- Enable auto update subscribe
o = s:option(Flag, "auto_update", translate("Enable auto update subscribe"))
o.default = 0

View File

@@ -1,4 +1,4 @@
local api = require "luci.model.cbi.passwall.api.api"
local api = require "luci.model.cbi.passwall2.api.api"
local appname = api.appname
m = Map(appname)
@@ -68,32 +68,6 @@ o.default = "disable"
o:value("disable", translate("No patterns are used"))
o:value("1:65535", translate("All"))
---- TCP Proxy Drop Ports
o = s:option(Value, "tcp_proxy_drop_ports", translate("TCP Proxy Drop Ports"))
o.default = "disable"
o:value("disable", translate("No patterns are used"))
---- UDP Proxy Drop Ports
o = s:option(Value, "udp_proxy_drop_ports", translate("UDP Proxy Drop Ports"))
o.default = "80,443"
o:value("disable", translate("No patterns are used"))
o:value("80,443", translate("QUIC"))
---- TCP Redir Ports
o = s:option(Value, "tcp_redir_ports", translate("TCP Redir Ports"))
o.default = "22,25,53,143,465,587,853,993,995,80,443"
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", translate("Only Web"))
o:value("80:65535", "80 " .. translate("or more"))
o:value("1:443", "443 " .. translate("or less"))
---- UDP Redir Ports
o = s:option(Value, "udp_redir_ports", translate("UDP Redir Ports"))
o.default = "1:65535"
o:value("1:65535", translate("All"))
o:value("53", "DNS")
if os.execute("lsmod | grep -i REDIRECT >/dev/null") == 0 and os.execute("lsmod | grep -i TPROXY >/dev/null") == 0 then
o = s:option(ListValue, "tcp_proxy_way", translate("TCP Proxy Way"))
o.default = "redirect"

View File

@@ -0,0 +1,55 @@
local api = require "luci.model.cbi.passwall2.api.api"
local appname = api.appname
m = Map(appname)
-- [[ Rule Settings ]]--
s = m:section(TypedSection, "global_rules", translate("Rule status"))
s.anonymous = true
s:append(Template(appname .. "/rule/rule_version"))
---- Auto Update
o = s:option(Flag, "auto_update", translate("Enable auto update rules"))
o.default = 0
o.rmempty = false
---- Week Update
o = s:option(ListValue, "week_update", translate("Week update rules"))
o:value(7, translate("Every day"))
for e = 1, 6 do o:value(e, translate("Week") .. e) end
o:value(0, translate("Week") .. translate("day"))
o.default = 0
o:depends("auto_update", true)
---- Time Update
o = s:option(ListValue, "time_update", translate("Day update rules"))
for e = 0, 23 do o:value(e, e .. translate("oclock")) end
o.default = 0
o:depends("auto_update", true)
o = s:option(Value, "v2ray_location_asset", translate("Location of V2ray/Xray asset"), translate("This variable specifies a directory where geoip.dat and geosite.dat files are."))
o.default = "/usr/share/v2ray/"
o.rmempty = false
s = m:section(TypedSection, "shunt_rules", "V2ray/Xray " .. translate("Shunt Rule"), "<a style='color: red'>" .. translate("Please note attention to the priority, the higher the order, the higher the priority.") .. "</a>")
s.template = "cbi/tblsection"
s.anonymous = false
s.addremove = true
s.sortable = true
s.extedit = api.url("shunt_rules", "%s")
function s.create(e, t)
TypedSection.create(e, t)
luci.http.redirect(e.extedit:format(t))
end
function s.remove(e, t)
m.uci:foreach(appname, "nodes", function(s)
if s["protocol"] and s["protocol"] == "_shunt" then
m:del(s[".name"], t)
end
end)
TypedSection.remove(e, t)
end
o = s:option(DummyValue, "remarks", translate("Remarks"))
return m

View File

@@ -1,4 +1,4 @@
local api = require "luci.model.cbi.passwall.api.api"
local api = require "luci.model.cbi.passwall2.api.api"
local appname = api.appname
local datatypes = api.datatypes
@@ -18,6 +18,18 @@ protocol:value("http")
protocol:value("tls")
protocol:value("bittorrent")
network = s:option(ListValue, "network", translate("Network"))
network:value("tcp,udp", "TCP UDP")
network:value("tcp", "TCP")
network:value("udp", "UDP")
source = s:option(TextValue, "source", translate("Source"))
source.wrap = "off"
sourcePort = s:option(Value, "sourcePort", translate("Source port"))
port = s:option(Value, "port", translate("port"))
domain_list = s:option(TextValue, "domain_list", translate("Domain"))
domain_list.rows = 10
domain_list.wrap = "off"

View File

@@ -1,19 +1,19 @@
#!/usr/bin/lua
local action = arg[1]
local api = require "luci.model.cbi.passwall.api.api"
local api = require "luci.model.cbi.passwall2.api.api"
local sys = api.sys
local uci = api.uci
local jsonc = api.jsonc
local CONFIG = "passwall_server"
local CONFIG = "passwall2_server"
local CONFIG_PATH = "/tmp/etc/" .. CONFIG
local LOG_APP_FILE = "/tmp/log/" .. CONFIG .. ".log"
local TMP_BIN_PATH = CONFIG_PATH .. "/bin"
local require_dir = "luci.model.cbi.passwall.server.api."
local require_dir = "luci.model.cbi.passwall2.server.api."
local ipt_bin = sys.exec("echo -n $(/usr/share/passwall/iptables.sh get_ipt_bin)")
local ip6t_bin = sys.exec("echo -n $(/usr/share/passwall/iptables.sh get_ip6t_bin)")
local ipt_bin = sys.exec("echo -n $(/usr/share/passwall2/iptables.sh get_ipt_bin)")
local ip6t_bin = sys.exec("echo -n $(/usr/share/passwall2/iptables.sh get_ip6t_bin)")
local function log(...)
local f, err = io.open(LOG_APP_FILE, "a")
@@ -53,17 +53,17 @@ local function gen_include()
_ipt = ip6t_bin
end
local result = "*" .. a
result = result .. "\n" .. sys.exec(_ipt .. '-save -t ' .. a .. ' | grep "PSW-SERVER" | sed -e "s/^-A \\(INPUT\\)/-I \\1 1/"')
result = result .. "\n" .. sys.exec(_ipt .. '-save -t ' .. a .. ' | grep "PSW2-SERVER" | sed -e "s/^-A \\(INPUT\\)/-I \\1 1/"')
result = result .. "COMMIT"
return result
end
local f, err = io.open("/tmp/etc/" .. CONFIG .. ".include", "a")
if f and err == nil then
f:write(ipt_bin .. '-save -c | grep -v "PSW-SERVER" | ' .. ipt_bin .. '-restore -c' .. "\n")
f:write(ipt_bin .. '-save -c | grep -v "PSW2-SERVER" | ' .. ipt_bin .. '-restore -c' .. "\n")
f:write(ipt_bin .. '-restore -n <<-EOT' .. "\n")
f:write(extract_rules("4", "filter") .. "\n")
f:write("EOT" .. "\n")
f:write(ip6t_bin .. '-save -c | grep -v "PSW-SERVER" | ' .. ip6t_bin .. '-restore -c' .. "\n")
f:write(ip6t_bin .. '-save -c | grep -v "PSW2-SERVER" | ' .. ip6t_bin .. '-restore -c' .. "\n")
f:write(ip6t_bin .. '-restore -n <<-EOT' .. "\n")
f:write(extract_rules("6", "filter") .. "\n")
f:write("EOT" .. "\n")
@@ -78,10 +78,10 @@ local function start()
end
cmd(string.format("mkdir -p %s %s", CONFIG_PATH, TMP_BIN_PATH))
cmd(string.format("touch %s", LOG_APP_FILE))
ipt("-N PSW-SERVER")
ipt("-I INPUT -j PSW-SERVER")
ip6t("-N PSW-SERVER")
ip6t("-I INPUT -j PSW-SERVER")
ipt("-N PSW2-SERVER")
ipt("-I INPUT -j PSW2-SERVER")
ip6t("-N PSW2-SERVER")
ip6t("-I INPUT -j PSW2-SERVER")
uci:foreach(CONFIG, "user", function(user)
local id = user[".name"]
local enable = user.enable
@@ -127,15 +127,6 @@ local function start()
elseif type == "Xray" then
config = require(require_dir .. "v2ray").gen_config(user)
bin = ln_run(api.get_xray_path(), "xray", "-config=" .. config_file, log_path)
elseif type == "Trojan" then
config = require(require_dir .. "trojan").gen_config(user)
bin = ln_run("/usr/sbin/trojan", "trojan", "-c " .. config_file, log_path)
elseif type == "Trojan-Plus" then
config = require(require_dir .. "trojan").gen_config(user)
bin = ln_run("/usr/sbin/trojan-plus", "trojan-plus", "-c " .. config_file, log_path)
elseif type == "Trojan-Go" then
config = require(require_dir .. "trojan").gen_config(user)
bin = ln_run(api.get_trojan_go_path(), "trojan-go", "-config " .. config_file, log_path)
elseif type == "Brook" then
local brook_protocol = user.protocol
local brook_password = user.password
@@ -165,11 +156,11 @@ local function start()
local bind_local = user.bind_local or 0
if bind_local and tonumber(bind_local) ~= 1 then
ipt(string.format('-A PSW-SERVER -p tcp --dport %s -m comment --comment "%s" -j ACCEPT', port, remarks))
ip6t(string.format('-A PSW-SERVER -p tcp --dport %s -m comment --comment "%s" -j ACCEPT', port, remarks))
ipt(string.format('-A PSW2-SERVER -p tcp --dport %s -m comment --comment "%s" -j ACCEPT', port, remarks))
ip6t(string.format('-A PSW2-SERVER -p tcp --dport %s -m comment --comment "%s" -j ACCEPT', port, remarks))
if udp_forward == 1 then
ipt(string.format('-A PSW-SERVER -p udp --dport %s -m comment --comment "%s" -j ACCEPT', port, remarks))
ip6t(string.format('-A PSW-SERVER -p udp --dport %s -m comment --comment "%s" -j ACCEPT', port, remarks))
ipt(string.format('-A PSW2-SERVER -p udp --dport %s -m comment --comment "%s" -j ACCEPT', port, remarks))
ip6t(string.format('-A PSW2-SERVER -p udp --dport %s -m comment --comment "%s" -j ACCEPT', port, remarks))
end
end
end
@@ -179,12 +170,12 @@ end
local function stop()
cmd(string.format("top -bn1 | grep -v 'grep' | grep '%s/' | awk '{print $1}' | xargs kill -9 >/dev/null 2>&1", CONFIG_PATH))
ipt("-D INPUT -j PSW-SERVER 2>/dev/null")
ipt("-F PSW-SERVER 2>/dev/null")
ipt("-X PSW-SERVER 2>/dev/null")
ip6t("-D INPUT -j PSW-SERVER 2>/dev/null")
ip6t("-F PSW-SERVER 2>/dev/null")
ip6t("-X PSW-SERVER 2>/dev/null")
ipt("-D INPUT -j PSW2-SERVER 2>/dev/null")
ipt("-F PSW2-SERVER 2>/dev/null")
ipt("-X PSW2-SERVER 2>/dev/null")
ip6t("-D INPUT -j PSW2-SERVER 2>/dev/null")
ip6t("-F PSW2-SERVER 2>/dev/null")
ip6t("-X PSW2-SERVER 2>/dev/null")
cmd(string.format("rm -rf %s %s /tmp/etc/%s.include", CONFIG_PATH, LOG_APP_FILE, CONFIG))
end

View File

@@ -1,4 +1,4 @@
module("luci.model.cbi.passwall.server.api.hysteria", package.seeall)
module("luci.model.cbi.passwall2.server.api.hysteria", package.seeall)
function gen_config(user)
local config = {
listen = ":" .. user.port,

View File

@@ -1,4 +1,4 @@
module("luci.model.cbi.passwall.server.api.shadowsocks", package.seeall)
module("luci.model.cbi.passwall2.server.api.shadowsocks", package.seeall)
function gen_config(user)
local config = {}
config.server = {"[::0]", "0.0.0.0"}

View File

@@ -1,4 +1,4 @@
module("luci.model.cbi.passwall.server.api.v2ray", package.seeall)
module("luci.model.cbi.passwall2.server.api.v2ray", package.seeall)
local uci = require"luci.model.uci".cursor()
function gen_config(user)
@@ -118,7 +118,7 @@ function gen_config(user)
}
if user.transit_node and user.transit_node ~= "nil" then
local transit_node_t = uci:get_all("passwall", user.transit_node)
local transit_node_t = uci:get_all("passwall2", user.transit_node)
if user.transit_node == "_socks" or user.transit_node == "_http" then
transit_node_t = {
type = user.type,
@@ -130,7 +130,7 @@ function gen_config(user)
password = (user.transit_node_password and user.transit_node_password ~= "") and user.transit_node_password or nil,
}
end
local outbound = require("luci.model.cbi.passwall.api.gen_v2ray").gen_outbound(transit_node_t, "transit")
local outbound = require("luci.model.cbi.passwall2.api.gen_v2ray").gen_outbound(transit_node_t, "transit")
if outbound then
table.insert(outbounds, 1, outbound)
end
@@ -138,7 +138,7 @@ function gen_config(user)
local config = {
log = {
-- error = "/tmp/etc/passwall_server/log/" .. user[".name"] .. ".log",
-- error = "/tmp/etc/passwall2_server/log/" .. user[".name"] .. ".log",
loglevel = ("1" == user.log) and user.loglevel or "none"
},
-- 传入连接

View File

@@ -1,6 +1,6 @@
local api = require "luci.model.cbi.passwall.api.api"
local api = require "luci.model.cbi.passwall2.api.api"
m = Map("passwall_server", translate("Server-Side"))
m = Map("passwall2_server", translate("Server-Side"))
t = m:section(NamedSection, "global", "global")
t.anonymous = true
@@ -66,8 +66,8 @@ e = t:option(Flag, "log", translate("Log"))
e.default = "1"
e.rmempty = false
m:append(Template("passwall/server/log"))
m:append(Template("passwall2/server/log"))
m:append(Template("passwall/server/users_list_status"))
m:append(Template("passwall2/server/users_list_status"))
return m

View File

@@ -1,4 +1,4 @@
local api = require "luci.model.cbi.passwall.api.api"
local api = require "luci.model.cbi.passwall2.api.api"
local ss_encrypt_method_list = {
"rc4-md5", "aes-128-cfb", "aes-192-cfb", "aes-256-cfb", "aes-128-ctr",
@@ -46,7 +46,7 @@ local encrypt_methods_ss_aead = {
"aes-256-gcm",
}
m = Map("passwall_server", translate("Server Config"))
m = Map("passwall2_server", translate("Server Config"))
m.redirect = api.url("server")
s = m:section(NamedSection, arg[1], "user", "")
@@ -62,9 +62,6 @@ remarks.default = translate("Remarks")
remarks.rmempty = false
type = s:option(ListValue, "type", translate("Type"))
if api.is_finded("microsocks") then
type:value("Socks", translate("Socks"))
end
if api.is_finded("ss-server") then
type:value("SS", translate("Shadowsocks"))
end
@@ -80,17 +77,6 @@ end
if api.is_finded("brook") then
type:value("Brook", translate("Brook"))
end
--[[
if api.is_finded("trojan-plus") or api.is_finded("trojan") then
type:value("Trojan", translate("Trojan"))
end
]]--
if api.is_finded("trojan-plus") then
type:value("Trojan-Plus", translate("Trojan-Plus"))
end
if api.is_finded("trojan-go") then
type:value("Trojan-Go", translate("Trojan-Go"))
end
if api.is_finded("hysteria") then
type:value("Hysteria", translate("Hysteria"))
end
@@ -137,7 +123,6 @@ auth.validate = function(self, value, t)
end
return value
end
auth:depends("type", "Socks")
auth:depends({ type = "V2ray", protocol = "socks" })
auth:depends({ type = "V2ray", protocol = "http" })
auth:depends({ type = "Xray", protocol = "socks" })
@@ -330,18 +315,12 @@ uuid:depends({ type = "V2ray", protocol = "trojan" })
uuid:depends({ type = "Xray", protocol = "vmess" })
uuid:depends({ type = "Xray", protocol = "vless" })
uuid:depends({ type = "Xray", protocol = "trojan" })
uuid:depends("type", "Trojan")
uuid:depends("type", "Trojan-Go")
uuid:depends("type", "Trojan-Plus")
tls = s:option(Flag, "tls", translate("TLS"))
tls.default = 0
tls.validate = function(self, value, t)
if value then
local type = type:formvalue(t) or ""
if value == "0" and (type == "Trojan" or type == "Trojan-Plus") then
return nil, translate("Original Trojan only supported 'tls', please choose 'tls'.")
end
if value == "1" then
local ca = tls_certificateFile:formvalue(t) or ""
local key = tls_keyFile:formvalue(t) or ""
@@ -362,9 +341,6 @@ tls:depends({ type = "Xray", protocol = "vless" })
tls:depends({ type = "Xray", protocol = "socks" })
tls:depends({ type = "Xray", protocol = "shadowsocks" })
tls:depends({ type = "Xray", protocol = "trojan" })
tls:depends("type", "Trojan")
tls:depends("type", "Trojan-Plus")
tls:depends("type", "Trojan-Go")
xtls = s:option(Flag, "xtls", translate("XTLS"))
xtls.default = 0
@@ -417,12 +393,6 @@ tls_keyFile.default = "/etc/config/ssl/" .. arg[1] .. ".key"
tls_keyFile:depends("tls", true)
tls_keyFile:depends("type", "Hysteria")
tls_sessionTicket = s:option(Flag, "tls_sessionTicket", translate("Session Ticket"))
tls_sessionTicket.default = "0"
tls_sessionTicket:depends({ type = "Trojan", tls = true })
tls_sessionTicket:depends({ type = "Trojan-Plus", tls = true })
tls_sessionTicket:depends({ type = "Trojan-Go", tls = true })
transport = s:option(ListValue, "transport", translate("Transport"))
transport:value("tcp", "TCP")
transport:value("mkcp", "mKCP")
@@ -442,45 +412,15 @@ transport:depends({ type = "Xray", protocol = "socks" })
transport:depends({ type = "Xray", protocol = "shadowsocks" })
transport:depends({ type = "Xray", protocol = "trojan" })
trojan_transport = s:option(ListValue, "trojan_transport", translate("Transport"))
trojan_transport:value("original", translate("Original"))
trojan_transport:value("ws", "WebSocket")
trojan_transport.default = "original"
trojan_transport:depends("type", "Trojan-Go")
trojan_plugin = s:option(ListValue, "plugin_type", translate("Transport Plugin"))
trojan_plugin:value("plaintext", "Plain Text")
trojan_plugin:value("shadowsocks", "ShadowSocks")
trojan_plugin:value("other", "Other")
trojan_plugin.default = "plaintext"
trojan_plugin:depends({ tls = false, trojan_transport = "original" })
trojan_plugin_cmd = s:option(Value, "plugin_cmd", translate("Plugin Binary"))
trojan_plugin_cmd.placeholder = "eg: /usr/bin/v2ray-plugin"
trojan_plugin_cmd:depends({ plugin_type = "shadowsocks" })
trojan_plugin_cmd:depends({ plugin_type = "other" })
trojan_plugin_op = s:option(Value, "plugin_option", translate("Plugin Option"))
trojan_plugin_op.placeholder = "eg: obfs=http;obfs-host=www.baidu.com"
trojan_plugin_op:depends({ plugin_type = "shadowsocks" })
trojan_plugin_op:depends({ plugin_type = "other" })
trojan_plugin_arg = s:option(DynamicList, "plugin_arg", translate("Plugin Option Args"))
trojan_plugin_arg.placeholder = "eg: [\"-config\", \"test.json\"]"
trojan_plugin_arg:depends({ plugin_type = "shadowsocks" })
trojan_plugin_arg:depends({ plugin_type = "other" })
-- [[ WebSocket部分 ]]--
ws_host = s:option(Value, "ws_host", translate("WebSocket Host"))
ws_host:depends("transport", "ws")
ws_host:depends("ss_transport", "ws")
ws_host:depends("trojan_transport", "ws")
ws_path = s:option(Value, "ws_path", translate("WebSocket Path"))
ws_path:depends("transport", "ws")
ws_path:depends("ss_transport", "ws")
ws_path:depends("trojan_transport", "ws")
ws_path:depends({ type = "Brook", brook_protocol = "wsserver" })
-- [[ HTTP/2部分 ]]--
@@ -488,12 +428,10 @@ ws_path:depends({ type = "Brook", brook_protocol = "wsserver" })
h2_host = s:option(Value, "h2_host", translate("HTTP/2 Host"))
h2_host:depends("transport", "h2")
h2_host:depends("ss_transport", "h2")
h2_host:depends("trojan_transport", "h2")
h2_path = s:option(Value, "h2_path", translate("HTTP/2 Path"))
h2_path:depends("transport", "h2")
h2_path:depends("ss_transport", "h2")
h2_path:depends("trojan_transport", "h2")
-- [[ TCP部分 ]]--
@@ -601,33 +539,10 @@ fallback_xver:depends("fallback", true)
fallback_list = s:option(DynamicList, "fallback_list", "Fallback", translate("dest,path"))
fallback_list:depends("fallback", true)
ss_aead = s:option(Flag, "ss_aead", translate("Shadowsocks secondary encryption"))
ss_aead:depends("type", "Trojan-Go")
ss_aead.default = "0"
ss_aead_method = s:option(ListValue, "ss_aead_method", translate("Encrypt Method"))
for _, v in ipairs(encrypt_methods_ss_aead) do ss_aead_method:value(v, v) end
ss_aead_method.default = "aes-128-gcm"
ss_aead_method:depends("ss_aead", true)
ss_aead_pwd = s:option(Value, "ss_aead_pwd", translate("Password"))
ss_aead_pwd.password = true
ss_aead_pwd:depends("ss_aead", true)
tcp_fast_open = s:option(Flag, "tcp_fast_open", translate("TCP Fast Open"))
tcp_fast_open.default = "0"
tcp_fast_open:depends("type", "SS")
tcp_fast_open:depends("type", "SSR")
tcp_fast_open:depends("type", "Trojan")
tcp_fast_open:depends("type", "Trojan-Plus")
tcp_fast_open:depends("type", "Trojan-Go")
remote_enable = s:option(Flag, "remote_enable", translate("Enable Remote"), translate("You can forward to Nginx/Caddy/V2ray/Xray WebSocket and more."))
remote_enable.default = "1"
remote_enable.rmempty = false
remote_enable:depends("type", "Trojan")
remote_enable:depends("type", "Trojan-Plus")
remote_enable:depends("type", "Trojan-Go")
remote_address = s:option(Value, "remote_address", translate("Remote Address"))
remote_address.default = "127.0.0.1"
@@ -708,21 +623,4 @@ loglevel:value("error")
loglevel:depends({ type = "V2ray", log = true })
loglevel:depends({ type = "Xray", log = true })
trojan_loglevel = s:option(ListValue, "trojan_loglevel", translate("Log Level"))
trojan_loglevel.default = "2"
trojan_loglevel:value("0", "all")
trojan_loglevel:value("1", "info")
trojan_loglevel:value("2", "warn")
trojan_loglevel:value("3", "error")
trojan_loglevel:value("4", "fatal")
function trojan_loglevel.cfgvalue(self, section)
return m:get(section, "loglevel")
end
function trojan_loglevel.write(self, section, value)
m:set(section, "loglevel", value)
end
trojan_loglevel:depends({ type = "Trojan", log = true })
trojan_loglevel:depends({ type = "Trojan-Plus", log = true })
trojan_loglevel:depends({ type = "Trojan-Go", log = true })
return m

View File

@@ -1,5 +1,5 @@
<%
local api = require "luci.model.cbi.passwall.api.api"
local api = require "luci.model.cbi.passwall2.api.api"
local brook_version = api.get_brook_version()
-%>

View File

@@ -1,5 +1,5 @@
<%
local api = require "luci.model.cbi.passwall.api.api"
local api = require "luci.model.cbi.passwall2.api.api"
local hysteria_version = api.get_hysteria_version()
-%>

View File

@@ -1,5 +1,5 @@
<%
local api = require "luci.model.cbi.passwall.api.api"
local api = require "luci.model.cbi.passwall2.api.api"
local v2ray_version = api.get_v2ray_version()
-%>

View File

@@ -1,5 +1,5 @@
<%
local api = require "luci.model.cbi.passwall.api.api"
local api = require "luci.model.cbi.passwall2.api.api"
local xray_version = api.get_xray_version()
-%>

View File

@@ -1,5 +1,5 @@
<%
local api = require "luci.model.cbi.passwall.api.api"
local api = require "luci.model.cbi.passwall2.api.api"
-%>
<script type="text/javascript">

View File

@@ -1,13 +1,12 @@
<%
local api = require "luci.model.cbi.passwall.api.api"
local api = require "luci.model.cbi.passwall2.api.api"
-%>
<div class="cbi-section cbi-tblsection">
<div id="dns_div">
<ul><b style="color:red"><%:About DNS issues:%></b>
<li style="color:red">1. <span><%:Some browsers may have built-in DNS, be sure to close. Example: Chrome. Settings - Security and Privacy - Security - Use secure DNS disabled.%></span></li>
<li style="color:red">2. <span><%:Sometimes after restart, you can not internet, especially the GFW mode. At this time, close all browsers (important), Windows Client, please `ipconfig / flushdns`. Please close the WiFi on the phone, cut the flight mode and then cut back.%></span></li>
<li style="color:red">2. <span><%:Sometimes after restart, you can not internet. At this time, close all browsers (important), Windows Client, please `ipconfig / flushdns`. Please close the WiFi on the phone, cut the flight mode and then cut back.%></span></li>
<li style="color:red">3. <span><%:The client DNS and the default gateway must point to this router.%></span></li>
<li style="color:red">4. <span><%:If you have a wrong DNS process, the consequences are at your own risk!%></span></li>
</ul>
</div>
<div id="div2"></div>
@@ -34,7 +33,6 @@ local api = require "luci.model.cbi.passwall.api.api"
var dom = document.getElementById("div2");
if (dom) {
var li = "";
li += "<%:You can use load balancing for failover.%>" + "<br />";
li += "<%:Restore the default configuration method. Input example in the address bar:%>" + "<a href='#' onclick='reset()'>" + reset_url + "</a>" + "<br />";
li += "<%:Hide menu method, input example in the address bar:%>" + "<a href='#' onclick='hide()'>" + hide_url + "</a>" + "<br />";
li += "<%:After the hidden to the display, input example in the address bar:%>" + "<a href='#'>" + show_url + "</a>" + "<br />";

View File

@@ -1,5 +1,5 @@
<%
local api = require "luci.model.cbi.passwall.api.api"
local api = require "luci.model.cbi.passwall2.api.api"
local auto_switch = api.uci_get_type("auto_switch", "enable", 0)
-%>
<script type="text/javascript">
@@ -36,12 +36,12 @@ local auto_switch = api.uci_get_type("auto_switch", "enable", 0)
}
var global_id = null;
var global = document.getElementById("cbi-passwall-global");
var global = document.getElementById("cbi-passwall2-global");
if (global) {
var node = global.getElementsByClassName("cbi-section-node")[0];
var node_id = node.getAttribute("id");
global_id = node_id;
var reg1 = new RegExp("(?<=" + node_id + "-).*?(?=(_node))")
var reg1 = new RegExp("(?<=" + node_id + "-).*?(?=(node))")
for (var i = 0; i < node.childNodes.length; i++) {
if (node.childNodes[i].childNodes && node.childNodes[i].childNodes.length > 0) {
for (var k = 0; k < node.childNodes[i].childNodes.length; k++) {
@@ -53,15 +53,6 @@ local auto_switch = api.uci_get_type("auto_switch", "enable", 0)
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 (global_id != null && node_select_value.indexOf("tcp") == 0) {
var d = global_id + "-tcp_node";
d = d.replace("cbi-", "cbid-").replace(new RegExp("-", 'g'), ".");
var dom = document.getElementsByName(d)[0];
var _node_select_value = dom.value;
if (_node_select_value && _node_select_value != "nil") {
node_select_value = _node_select_value;
}
}
var v = document.getElementById(dom_id + "-" + node_select_value);
if (v) {
node_select.title = v.text;
@@ -77,11 +68,11 @@ local auto_switch = api.uci_get_type("auto_switch", "enable", 0)
new_a.setAttribute("onclick", "location.href='" + '<%=api.url("node_config")%>' + "/" + node_select_value + "'");
new_html = new_a.outerHTML;
if (s[0] == "tcp" || s[0] == "udp") {
if (s[0] == "") {
var log_a = document.createElement("a");
log_a.innerHTML = "<%:Log%>";
log_a.href = "#";
log_a.setAttribute("onclick", "window.open('" + '<%=api.url("get_redir_log")%>' + "?proto=" + s[0] + "', '_blank')");
log_a.setAttribute("onclick", "window.open('" + '<%=api.url("get_redir_log")%>' + "?id=" + "global" + "', '_blank')");
new_html += "&nbsp&nbsp" + log_a.outerHTML;
}
@@ -94,7 +85,7 @@ local auto_switch = api.uci_get_type("auto_switch", "enable", 0)
}
}
var socks = document.getElementById("cbi-passwall-socks");
var socks = document.getElementById("cbi-passwall2-socks");
if (socks) {
var socks_enabled_dom = document.getElementById(global_id + "-socks_enabled");
socks_enabled_dom.parentNode.removeChild(socks_enabled_dom);
@@ -111,15 +102,6 @@ local auto_switch = api.uci_get_type("auto_switch", "enable", 0)
var node_select = document.getElementsByName(dom_id)[0];
var node_select_value = node_select.value;
if (node_select_value && node_select_value != "nil") {
if (global_id != null && node_select_value.indexOf("tcp") == 0) {
var d = global_id + "-tcp_node";
d = d.replace("cbi-", "cbid-").replace(new RegExp("-", 'g'), ".");
var dom = document.getElementsByName(d)[0];
var _node_select_value = dom.value;
if (_node_select_value && _node_select_value != "nil") {
node_select_value = _node_select_value;
}
}
var v = document.getElementById(dom_id + "-" + node_select_value);
if (v) {
node_select.title = v.text;

File diff suppressed because one or more lines are too long

View File

@@ -1,5 +1,5 @@
<%
local api = require "luci.model.cbi.passwall.api.api"
local api = require "luci.model.cbi.passwall2.api.api"
-%>
<script type="text/javascript">
//<![CDATA[

View File

@@ -1,5 +1,5 @@
<%
local api = require "luci.model.cbi.passwall.api.api"
local api = require "luci.model.cbi.passwall2.api.api"
-%>
<style>
@@ -48,7 +48,7 @@ local api = require "luci.model.cbi.passwall.api.api"
function add_node() {
var nodes_link = document.getElementById("nodes_link").value;
if (nodes_link.trim() != "") {
var supports = "ss ssr vmess vless trojan trojan-go hysteria";
var supports = "ss ssr vmess vless trojan hysteria";
var itype = nodes_link.split('://')[0];
if (itype.trim() != "" && supports.indexOf(itype) >= 0) {
ajax_add_node(nodes_link);

View File

@@ -1,6 +1,6 @@
<%+cbi/valueheader%>
<%
local api = require "luci.model.cbi.passwall.api.api"
local api = require "luci.model.cbi.passwall2.api.api"
local has_v2ray = api.is_finded("v2ray")
local has_xray = api.is_finded("xray")
-%>
@@ -80,7 +80,7 @@ local has_xray = api.is_finded("xray")
function buildUrl(btn, urlname, sid) {
var opt = {
base: "cbid.passwall",
base: "cbid.passwall2",
client : true,
get: function(opt) {
var id = this.base + "." + opt;
@@ -274,11 +274,11 @@ local has_xray = api.is_finded("xray")
params = params.substring(1);
}
url += params;
} else if (((v_type === "V2ray" || v_type === "Xray") && opt.get("protocol").value === "trojan") || v_type === "Trojan" || v_type === "Trojan-Plus" || v_type === "Trojan-Go") {
if (((v_type === "V2ray" || v_type === "Xray") && opt.get("protocol").value === "trojan") || v_type === "Trojan-Plus") {
} else if (((v_type === "V2ray" || v_type === "Xray") && opt.get("protocol").value === "trojan")) {
if (((v_type === "V2ray" || v_type === "Xray") && opt.get("protocol").value === "trojan")) {
v_type = "trojan";
}
var v_password = opt.get(!opt.client && v_type === "Trojan-Go" ? "passwords" : "password");
var v_password = opt.get("password");
var v_server = opt.get("address");
var v_port = opt.get("port");
url = encodeURIComponent(v_password.value) +
@@ -287,39 +287,8 @@ local has_xray = api.is_finded("xray")
var params = "";
if (opt.get("tls").checked) {
params += opt.query("sni", "tls_serverName");
if (v_type !== "Trojan-Go") {
params += "&tls=1"
params += opt.query("allowinsecure", "tls_allowInsecure");
}
}
if (v_type === "Trojan-Go") {
if (!opt.get("tls").checked && opt.get("trojan_transport").value === "original") {
var plugin = {};
plugin.type = opt.get("plugin_type").value;
if (plugin.type !== "plaintext") {
plugin.command = opt.get("plugin_cmd").value;
plugin.option = opt.get("plugin_option").value;
plugin.arg = opt.getlist("plugin_arg");
}
params += "&plugin=" + encodeURIComponent(JSON.stringify(plugin));
}
params += opt.query("type", "trojan_transport");
var ws = (opt.get("trojan_transport").value.indexOf("ws") !== -1);
var h2 = (opt.get("trojan_transport").value.indexOf("h2") !== -1);
if (ws) {
params += opt.query("host", "ws_host");
params += opt.query("path", "ws_path");
} else if (h2) {
params += opt.query("host", "h2_host");
params += opt.query("path", "h2_path");
}
var enc = "none";
if (opt.get("ss_aead").checked === true) {
enc = "ss;" +
opt.get("ss_aead_method").value +
":" + opt.get("ss_aead_pwd").value;
}
params += "&encryption=" + encodeURIComponent(enc);
params += "&tls=1"
params += opt.query("allowinsecure", "tls_allowInsecure");
}
params += "#" + encodeURI(v_alias.value);
if (params[0] == "&") {
@@ -397,7 +366,7 @@ local has_xray = api.is_finded("xray")
function fromUrl(btn, urlname, sid) {
var opt = {
base: 'cbid.passwall',
base: 'cbid.passwall2',
client : true,
get: function(opt) {
var obj;
@@ -587,8 +556,7 @@ local has_xray = api.is_finded("xray")
opt.set('remarks', decodeURI(param));
}
}
} else if (ssu[0] === "trojan" || ssu[0] === "trojan-plus") {
var stype = "Trojan-Plus";
} else if (ssu[0] === "trojan") {
var m = parseNodeUrl(ssrurl);
var password = m.passwd;
if (password === "") {
@@ -606,135 +574,21 @@ local has_xray = api.is_finded("xray")
queryParam[decodeURIComponent(params[0]).toLowerCase()] = decodeURIComponent(params[1] || '');
}
}
if (queryParam.mux || queryParam.ws || queryParam.h2 || queryParam.ss || queryParam.plugin) {
stype = "Trojan-Go";
}
opt.set('type', stype);
opt.set('type', "V2ray");
opt.set('protocol', "trojan");
opt.set('address', m.hostname);
opt.set('port', m.port || "443");
opt.set(!opt.client && stype === "Trojan-Go" ? 'passwords' : 'password', decodeURIComponent(password));
opt.set('password', decodeURIComponent(password));
var tls = true;
if (stype === "Trojan-Go") {
tls = queryParam.plugin === undefined;
}
if (tls === false) { alert("TODO: plugin params for trojan-go."); }
opt.set('tls', tls);
if (tls) {
opt.set('tls_serverName', queryParam.peer || queryParam.sni || '');
opt.set('tls_allowInsecure', queryParam.allowinsecure === '1');
}
if (stype === "Trojan-Go") {
var tran = 'original';
var ws = null;
var h2 = null;
if (queryParam.type) {
ws = queryParam.type.indexOf('ws') !== -1;
h2 = queryParam.type.indexOf('h2') !== -1;
}
if (ws && h2) {
tran = 'h2+ws'
} else {
if (ws) tran = 'ws';
if (h2) tran = 'h2';
}
opt.set('trojan_transport', 'tran');
if (ws) {
opt.set('ws_host', queryParam.wshost || '');
opt.set('ws_path', queryParam.wspath || '/');
}
if (h2) {
opt.set('h2_host', queryParam.h2host || '');
opt.set('h2_path', queryParam.h2path || '/');
}
var ss = queryParam.ss === '1';
opt.set('ss_aead', ss);
if (ss) {
opt.set('ss_aead_method', queryParam.ssmethod.toLowerCase() || '');
opt.set('ss_aead_pwd', queryParam.sspasswd || '');
}
}
opt.set('mux', queryParam.mux === '1');
if (m.hash) {
opt.set('remarks', decodeURI(m.hash.substr(1)));
}
} else if (ssu[0] === "trojan-go") {
var m = parseNodeUrl(ssrurl);
var password = m.passwd;
if (password === "") {
s.innerHTML = "<font color='red'><%:Invalid Share URL Format%></font>";
return false;
}
var queryParam = {};
if (m.search.length > 1) {
var query = m.search.split('?');
var queryParams = query[1];
var queryArray = queryParams.split('&');
for (i = 0; i < queryArray.length; i++) {
var params = queryArray[i].split('=');
queryParam[decodeURIComponent(params[0]).toLowerCase()] = decodeURIComponent(params[1] || '');
}
}
opt.set('type', 'Trojan-Go');
opt.set('address', m.hostname);
opt.set('port', m.port || "443");
opt.set(opt.client ? 'password' : 'passwords', decodeURIComponent(password));
opt.set('tls', '1');
opt.set('tls_allowInsecure', '0');
opt.set('tls_serverName', queryParam.peer || queryParam.sni || '');
var plugin = queryParam.plugin !== undefined;
if (plugin) {
opt.set('trojan_transport', 'original');
var plugin = JSON.parse(queryParam.plugin);
if (plugin) {
opt.set('plugin_type', plugin.type);
if (plugin.type !== "plaintext") {
opt.set('plugin_cmd', plugin.command);
opt.set('plugin_option', plugin.option);
opt.setlist('plugin_arg', plugin.arg);
}
} else
alert(queryParam.plugin);
}
var tran = 'original';
var or = queryParam.type === undefined || queryParam.type === 'original';
var ws = null;
var h2 = null;
if (queryParam.type) {
ws = queryParam.type.indexOf('ws') !== -1;
h2 = queryParam.type.indexOf('h2') !== -1;
}
if (ws && h2) {
tran = 'h2+ws'
} else {
if (ws) tran = 'ws';
if (h2) tran = 'h2';
}
opt.set('trojan_transport', tran);
if (ws) {
opt.set('ws_host', queryParam.host || '');
opt.set('ws_path', queryParam.path || '/');
}
if (h2){
opt.set('h2_host', queryParam.host || '');
opt.set('h2_path', queryParam.path || '/');
}
var enc = {};
var ss = false;
if (queryParam.encryption) {
var r = queryParam.encryption.match(/^(ss);([^;:]*)[;:](.*)$/),
enc = {type: r[1], method: r[2], password: r[3]};
}
ss = enc.type === 'ss';
opt.set('ss_aead', ss);
if (ss) {
opt.set('ss_aead_method', enc.method.toLowerCase() || '');
opt.set('ss_aead_pwd', enc.password || '');
}
opt.set('mux', '1');
if (m.hash) {
opt.set('remarks', decodeURI(m.hash.substr(1)));
}
} else if (ssu[0] === "vmess") {
var sstr = b64DecodeUnicode(ssu[1]);
var ploc = sstr.indexOf("/?");

View File

@@ -1,7 +1,5 @@
<%
-- Copyright (C) 2018-2020 L-WRT Team
-- Copyright (C) 2021 xiaorouji
local api = require "luci.model.cbi.passwall.api.api"
local api = require "luci.model.cbi.passwall2.api.api"
-%>
<style>
@@ -100,7 +98,7 @@ table td, .table .td {
function open_set_node_div(cbi_id) {
section = cbi_id;
document.getElementById("set_node_div").style.display="block";
var node_name = document.getElementById("cbid.passwall." + cbi_id + ".remarks").value;
var node_name = document.getElementById("cbid.passwall2." + cbi_id + ".remarks").value;
document.getElementById("set_node_name").innerHTML = node_name;
}
@@ -110,14 +108,14 @@ table td, .table .td {
}
function _cbi_row_top(id) {
var dom = document.getElementById("cbi-passwall-" + id);
var dom = document.getElementById("cbi-passwall2-" + id);
if (dom) {
var trs = document.getElementById("cbi-passwall-nodes").getElementsByClassName("cbi-section-table-row");
var trs = document.getElementById("cbi-passwall2-nodes").getElementsByClassName("cbi-section-table-row");
if (trs && trs.length > 0) {
for (var i = 0; i < trs.length; i++) {
var up = dom.getElementsByClassName("cbi-button-up");
if (up) {
cbi_row_swap(up[0], true, 'cbi.sts.passwall.nodes');
cbi_row_swap(up[0], true, 'cbi.sts.passwall2.nodes');
}
}
}
@@ -125,7 +123,7 @@ table td, .table .td {
}
function checked_all_node(btn) {
var doms = document.getElementById("cbi-passwall-nodes").getElementsByClassName("nodes_select");
var doms = document.getElementById("cbi-passwall2-nodes").getElementsByClassName("nodes_select");
if (doms && doms.length > 0) {
for (var i = 0 ; i < doms.length; i++) {
doms[i].checked = true;
@@ -136,7 +134,7 @@ table td, .table .td {
}
function dechecked_all_node(btn) {
var doms = document.getElementById("cbi-passwall-nodes").getElementsByClassName("nodes_select");
var doms = document.getElementById("cbi-passwall2-nodes").getElementsByClassName("nodes_select");
if (doms && doms.length > 0) {
for (var i = 0 ; i < doms.length; i++) {
doms[i].checked = false;
@@ -148,7 +146,7 @@ table td, .table .td {
function delete_select_nodes() {
var ids = [];
var doms = document.getElementById("cbi-passwall-nodes").getElementsByClassName("nodes_select");
var doms = document.getElementById("cbi-passwall2-nodes").getElementsByClassName("nodes_select");
if (doms && doms.length > 0) {
for (var i = 0 ; i < doms.length; i++) {
if (doms[i].checked) {
@@ -164,7 +162,7 @@ table td, .table .td {
if (x && x.status == 200) {
/*
for (var i = 0 ; i < ids.length; i++) {
var box = document.getElementById("cbi-passwall-" + ids[i]);
var box = document.getElementById("cbi-passwall2-" + ids[i]);
box.remove();
}
*/
@@ -190,8 +188,8 @@ table td, .table .td {
function get_address_full(id) {
try {
var address = document.getElementById("cbid.passwall." + id + ".address").value;
var port = document.getElementById("cbid.passwall." + id + ".port").value;
var address = document.getElementById("cbid.passwall2." + id + ".address").value;
var port = document.getElementById("cbid.passwall2." + id + ".port").value;
}
catch(err){}
//判断是否含有汉字
@@ -209,17 +207,17 @@ table td, .table .td {
function(x, result) {
var id = result["TCP"];
if (id) {
var dom = document.getElementById("cbi-passwall-" + id);
var dom = document.getElementById("cbi-passwall2-" + id);
if (dom) {
dom.classList.add("_now_use");
dom.title = "当前TCP节点";
//var v = "<a style='color: red'>当前TCP节点</a>" + document.getElementById("cbid.passwall." + id + ".remarks").value;
//document.getElementById("cbi-passwall-" + id + "-remarks").innerHTML = v;
//var v = "<a style='color: red'>当前TCP节点</a>" + document.getElementById("cbid.passwall2." + id + ".remarks").value;
//document.getElementById("cbi-passwall2-" + id + "-remarks").innerHTML = v;
}
}
id = result["UDP"];
if (id) {
var dom = document.getElementById("cbi-passwall-" + id);
var dom = document.getElementById("cbi-passwall2-" + id);
if (dom) {
dom.classList.add("_now_use");
dom.title = "当前UDP节点";
@@ -410,7 +408,7 @@ table td, .table .td {
auto_ping();
*/
var edit_btn = document.getElementById("cbi-passwall-nodes").getElementsByClassName("cbi-button cbi-button-edit");
var edit_btn = document.getElementById("cbi-passwall2-nodes").getElementsByClassName("cbi-button cbi-button-edit");
for (var i = 0; i < edit_btn.length; i++) {
try {
var onclick_str = edit_btn[i].getAttribute("onclick");
@@ -429,16 +427,16 @@ table td, .table .td {
var obj = {};
obj.id = id;
obj.type = document.getElementById("cbid.passwall." + id + ".type").value;
var address_dom = document.getElementById("cbid.passwall." + id + ".address");
var port_dom = document.getElementById("cbid.passwall." + id + ".port");
obj.type = document.getElementById("cbid.passwall2." + id + ".type").value;
var address_dom = document.getElementById("cbid.passwall2." + id + ".address");
var port_dom = document.getElementById("cbid.passwall2." + id + ".port");
if (address_dom && port_dom) {
obj.address = address_dom.value;
obj.port = port_dom.value;
}
node_count++;
var add_from = document.getElementById("cbid.passwall." + id + ".add_from").value;
var add_from = document.getElementById("cbid.passwall2." + id + ".add_from").value;
if (node_list[add_from])
node_list[add_from].push(obj);
else

View File

@@ -1,10 +1,6 @@
<%
local api = require "luci.model.cbi.passwall.api.api"
local api = require "luci.model.cbi.passwall2.api.api"
local gfwlist_update = api.uci_get_type("global_rules", "gfwlist_update", "1") == "1" and "checked='checked'" or ""
local chnroute_update = api.uci_get_type("global_rules", "chnroute_update", "1") == "1" and "checked='checked'" or ""
local chnroute6_update = api.uci_get_type("global_rules", "chnroute6_update", "1") == "1" and "checked='checked'" or ""
local chnlist_update = api.uci_get_type("global_rules", "chnlist_update", "1") == "1" and "checked='checked'" or ""
local geoip_update = api.uci_get_type("global_rules", "geoip_update", "1") == "1" and "checked='checked'" or ""
local geosite_update = api.uci_get_type("global_rules", "geosite_update", "1") == "1" and "checked='checked'" or ""
-%>
@@ -46,22 +42,6 @@ local geosite_update = api.uci_get_type("global_rules", "geosite_update", "1") =
</label>
<div class="cbi-value-field">
<div>
<label>
<input class="cbi-input-checkbox" type="checkbox" name="gfwlist" value="1" <%=gfwlist_update%> />
gfwlist
</label>
<label>
<input class="cbi-input-checkbox" type="checkbox" name="chnroute" value="1" <%=chnroute_update%> />
chnroute
</label>
<label>
<input class="cbi-input-checkbox" type="checkbox" name="chnroute6" value="1" <%=chnroute6_update%> />
chnroute6
</label>
<label>
<input class="cbi-input-checkbox" type="checkbox" name="chnlist" value="1" <%=chnlist_update%> />
chnlist
</label>
<label>
<input class="cbi-input-checkbox" type="checkbox" name="geoip" value="1" <%=geoip_update%> />
geoip

View File

@@ -1,5 +1,5 @@
<%
local api = require "luci.model.cbi.passwall.api.api"
local api = require "luci.model.cbi.passwall2.api.api"
-%>
<script type="text/javascript">
//<![CDATA[

View File

@@ -1,5 +1,5 @@
<%
local api = require "luci.model.cbi.passwall.api.api"
local api = require "luci.model.cbi.passwall2.api.api"
-%>
<script type="text/javascript">
//<![CDATA[
@@ -19,7 +19,7 @@ local api = require "luci.model.cbi.passwall.api.api"
);
}
var edit_btn = document.getElementById("cbi-passwall_server-user").getElementsByClassName("cbi-button cbi-button-edit");
var edit_btn = document.getElementById("cbi-passwall2_server-user").getElementsByClassName("cbi-button cbi-button-edit");
for (var i = 0; i < edit_btn.length; i++) {
try {
var onclick_str = edit_btn[i].getAttribute("onclick");

View File

@@ -1,5 +1,5 @@
msgid "Pass Wall"
msgstr "PassWall"
msgid "PassWall 2"
msgstr "PassWall 2"
msgid "Auto"
msgstr "自动"
@@ -61,9 +61,6 @@ msgstr "节点列表"
msgid "Other Settings"
msgstr "高级设置"
msgid "Load Balancing"
msgstr "负载均衡"
msgid "Enter interface"
msgstr "进入界面"
@@ -142,53 +139,14 @@ msgstr "用于代理特定的列表。"
msgid "For proxy game network."
msgstr "用于代理游戏等。"
msgid "DNS Shunt"
msgstr "DNS分流"
msgid "Domestic group name"
msgstr "国内分组名"
msgid "You only need to configure domestic DNS packets in SmartDNS and set it redirect or as Dnsmasq upstream, and fill in the domestic DNS group name here."
msgstr "你只需要在SmartDNS配置好国内DNS分组并设置重定向或作为Dnsmasq上游此处填入国内DNS分组名。"
msgid "Filter Mode"
msgstr "过滤模式"
msgid "TCP node must be '%s' type to use FakeDNS."
msgstr "TCP节点必须是 '%s' 类型才能使用 FakeDNS。"
msgid "Remote DNS"
msgstr "远程DNS"
msgid "IP:Port mode acceptable, multi value split with english comma."
msgstr "接受 IP:Port 形式的输入,多个以英文逗号分隔。"
msgid "If you use dns2socks, only the first one is valid."
msgstr "如果使用dns2socks只有第一个生效。"
msgid "Ali"
msgstr "阿里"
msgid "Baidu"
msgstr "百度"
msgid "Resolver For The List Proxied"
msgstr "解析被代理的域名列表"
msgid "Requery DNS By %s"
msgstr "通过%s请求DNS"
msgid "Socks Server"
msgstr "Socks服务器"
msgid "Misconfigured"
msgstr "配置不当"
msgid "Make sure socks service is available on this address."
msgstr "请确保此Socks服务可用。"
msgid "Format must be:"
msgstr "格式必须为:"
msgid "DNS Protocol"
msgstr "DNS 协议"
msgid "DoH request address"
msgstr "DoH 请求地址"
@@ -196,9 +154,6 @@ msgstr "DoH 请求地址"
msgid "China list or gfwlist cannot be used together with outside China list!"
msgstr "中国列表不能和中国列表外或防火墙表一起使用!"
msgid "Cache Resolved"
msgstr "缓存解析结果"
msgid "Notify the DNS server when the DNS query is notified, the location of the client (cannot be a private IP address)."
msgstr "用于 DNS 查询时通知 DNS 服务器,客户端所在的地理位置(不能是私有 IP 地址)。"
@@ -208,21 +163,6 @@ msgstr "此功能需要 DNS 服务器支持 EDNS Client SubnetRFC7871。"
msgid "When the accessed domain name does not exist in the rule list, the default DNS used."
msgstr "当访问的域名不存在规则列表中使用的默认DNS。"
msgid "The effect is better, but will increase the memory."
msgstr "效果更好,但会增加内存使用。"
msgid "Filter Proxy Host IPv6"
msgstr "过滤代理域名 IPv6"
msgid "Experimental feature."
msgstr "实验性功能。"
msgid "Clear IPSET"
msgstr "清空 IPSET"
msgid "Try this feature if the rule modification does not take effect."
msgstr "如果修改规则后没有生效,请尝试此功能。"
msgid "The server client can also use this rule to scientifically surf the Internet."
msgstr "本机服务器的客户端也可以使用这个代理模式上网。"
@@ -232,8 +172,8 @@ msgstr "关于DNS问题"
msgid "Some browsers may have built-in DNS, be sure to close. Example: Chrome. Settings - Security and Privacy - Security - Use secure DNS disabled."
msgstr "部分浏览器可能有内置的DNS请务必关闭。如chrome。 设置 - 安全和隐私设置 - 使用安全 DNS 关闭。"
msgid "Sometimes after restart, you can not internet, especially the GFW mode. At this time, close all browsers (important), Windows Client, please `ipconfig / flushdns`. Please close the WiFi on the phone, cut the flight mode and then cut back."
msgstr "有时候重启后,上不了尤其是GFW模式。这时请先关闭所有浏览器重要Windows客户端请`ipconfig/flushdns`。手机端请关闭WIFI切一下飞行模式再切回来。"
msgid "Sometimes after restart, you can not internet. At this time, close all browsers (important), Windows Client, please `ipconfig / flushdns`. Please close the WiFi on the phone, cut the flight mode and then cut back."
msgstr "有时候重启后上不了。这时请先关闭所有浏览器重要Windows客户端请`ipconfig/flushdns`。手机端请关闭WIFI切一下飞行模式再切回来。"
msgid "The client DNS and the default gateway must point to this router."
msgstr "客户端DNS和默认网关必须指向本路由器。"
@@ -241,9 +181,6 @@ msgstr "客户端DNS和默认网关必须指向本路由器。"
msgid "If you have a wrong DNS process, the consequences are at your own risk!"
msgstr "如果你自行配置了错误的DNS流程后果自负"
msgid "You can use load balancing for failover."
msgstr "可以使用负载均衡实现故障切换功能。"
msgid "Restore the default configuration method. Input example in the address bar:"
msgstr "恢复默认配置方法,地址栏输入例:"
@@ -721,8 +658,8 @@ msgstr "恢复切换"
msgid "When detects main node is available, switch back to the main node."
msgstr "当检测到主节点可用时,切换回主节点。"
msgid "If the main node is V2ray/Xray shunt"
msgstr "如果主节点是V2ray/Xray分流"
msgid "If the main node is shunt"
msgstr "如果主节点是分流"
msgid "Switch it"
msgstr "切掉它"
@@ -742,60 +679,6 @@ msgstr "通过关键字删除备用节点列表的节点"
msgid "Please enter the node keyword, pay attention to distinguish between spaces, uppercase and lowercase."
msgstr "请输入节点关键字,注意区分空格、大写和小写。"
msgid "Configure this node with 127.0.0.1: this port"
msgstr "使用127.0.0.1和此端口配置节点"
msgid "Enable Load Balancing"
msgstr "开启负载均衡"
msgid "Console Username"
msgstr "控制台账号"
msgid "Console Password"
msgstr "控制台密码"
msgid "Console Port"
msgstr "控制台端口"
msgid "In the browser input routing IP plus port access, such as:192.168.1.1:1188"
msgstr "在浏览器输入路由IP加端口访问192.168.1.1:1188"
msgid "Haproxy Port"
msgstr "负载均衡端口"
msgid "Add a node, Export Of Multi WAN Only support Multi Wan. Load specific gravity range 1-256. Multiple primary servers can be load balanced, standby will only be enabled when the primary server is offline! Multiple groups can be set, Haproxy port same one for each group."
msgstr "添加节点指定出口功能是为多WAN用户准备的。负载比重范围1-256。多个主服务器可以负载均衡备用只有在主服务器离线时才会启用可以设置多个组负载均衡端口相同则为一组。"
msgid "Note that the node configuration parameters for load balancing must be consistent, otherwise problems can arise!"
msgstr "注意,负载均衡的节点配置参数必须一致,否则会出问题!"
msgid "Node"
msgstr "节点"
msgid "Node Address"
msgstr "节点地址"
msgid "Node Port"
msgstr "节点端口"
msgid "Node Weight"
msgstr "负载比重"
msgid "Export Of Multi WAN"
msgstr "多WAN指定出口"
msgid "Main"
msgstr "主要"
msgid "Mode"
msgstr "模式"
msgid "Primary"
msgstr "主要"
msgid "Standby"
msgstr "备用"
msgid "Manually update"
msgstr "手动更新"
@@ -1288,8 +1171,8 @@ msgstr "日志"
msgid "Log"
msgstr "日志"
msgid "%s Node Log Close"
msgstr "%s 节点日志关闭"
msgid "Close Node Log "
msgstr "关闭节点日志"
msgid "Log Level"
msgstr "日志等级"

View File

@@ -3,7 +3,7 @@
START=99
STOP=15
CONFIG=passwall
CONFIG=passwall2
APP_FILE=/usr/share/${CONFIG}/app.sh
LOCK_FILE_DIR=/var/lock
LOCK_FILE=${LOCK_FILE_DIR}/${CONFIG}.lock

View File

@@ -0,0 +1,16 @@
#!/bin/sh /etc/rc.common
START=99
start() {
lua /usr/lib/lua/luci/model/cbi/passwall2/server/api/app.lua start
}
stop() {
lua /usr/lib/lua/luci/model/cbi/passwall2/server/api/app.lua stop
}
restart() {
stop
start
}

View File

@@ -0,0 +1,35 @@
#!/bin/sh
uci -q batch <<-EOF >/dev/null
set dhcp.@dnsmasq[0].localuse=1
commit dhcp
delete ucitrack.@passwall2[-1]
add ucitrack passwall2
set ucitrack.@passwall2[-1].init=passwall2
commit ucitrack
delete firewall.passwall2
set firewall.passwall2=include
set firewall.passwall2.type=script
set firewall.passwall2.path=/var/etc/passwall2.include
set firewall.passwall2.reload=1
commit firewall
delete ucitrack.@passwall2_server[-1]
add ucitrack passwall2_server
set ucitrack.@passwall2_server[-1].init=passwall2_server
commit ucitrack
delete firewall.passwall2_server
set firewall.passwall2_server=include
set firewall.passwall2_server.type=script
set firewall.passwall2_server.path=/var/etc/passwall2_server.include
set firewall.passwall2_server.reload=1
commit firewall
set uhttpd.main.max_requests=50
commit uhttpd
EOF
[ ! -s "/etc/config/passwall2" ] && cp -f /usr/share/passwall2/0_default_config /etc/config/passwall2
touch /etc/config/passwall2_show >/dev/null 2>&1
rm -f /tmp/luci-indexcache
rm -rf /tmp/luci-modulecache/
killall -HUP rpcd 2>/dev/null
exit 0

View File

@@ -2,22 +2,11 @@
config global
option enabled '0'
option socks_enabled '0'
option tcp_node 'nil'
option udp_node 'nil'
option dns_mode 'pdnsd'
option node 'myshunt'
option dns_protocol 'tcp'
option dns_forward '1.1.1.1'
option filter_proxy_ipv6 '0'
option tcp_proxy_mode 'chnroute'
option udp_proxy_mode 'chnroute'
option localhost_tcp_proxy_mode 'default'
option localhost_udp_proxy_mode 'default'
option close_log_tcp '0'
option close_log_udp '0'
option close_log '0'
option loglevel 'error'
option trojan_loglevel '4'
config global_haproxy
option balancing_enable '0'
config global_delay
option auto_on '0'
@@ -28,10 +17,6 @@ config global_forwarding
option process '0'
option tcp_no_redir_ports 'disable'
option udp_no_redir_ports '53'
option tcp_proxy_drop_ports 'disable'
option udp_proxy_drop_ports '80,443'
option tcp_redir_ports '22,25,53,143,465,587,853,993,995,80,443'
option udp_redir_ports '1:65535'
option accept_icmp '0'
option tcp_proxy_way 'redirect'
option ipv6_tproxy '0'
@@ -43,24 +28,13 @@ config global_other
config global_rules
option auto_update '0'
option chnlist_update '1'
option chnroute_update '1'
option chnroute6_update '1'
option gfwlist_update '1'
option geosite_update '0'
option geoip_update '0'
list gfwlist_url 'https://cdn.jsdelivr.net/gh/YW5vbnltb3Vz/domain-list-community@release/gfwlist.txt'
list chnroute_url 'https://ispip.clang.cn/all_cn.txt'
list chnroute6_url 'https://ispip.clang.cn/all_cn_ipv6.txt'
list chnlist_url 'https://cdn.jsdelivr.net/gh/felixonmars/dnsmasq-china-list/accelerated-domains.china.conf'
list chnlist_url 'https://cdn.jsdelivr.net/gh/felixonmars/dnsmasq-china-list/apple.china.conf'
list chnlist_url 'https://cdn.jsdelivr.net/gh/felixonmars/dnsmasq-china-list/google.china.conf'
option geosite_update '1'
option geoip_update '1'
option v2ray_location_asset '/usr/share/v2ray/'
config global_app
option v2ray_file '/usr/bin/v2ray'
option xray_file '/usr/bin/xray'
option trojan_go_file '/usr/bin/trojan-go'
option brook_file '/usr/bin/brook'
option hysteria_file '/usr/bin/hysteria'
@@ -79,47 +53,77 @@ config auto_switch
option retry_num '3'
option shunt_logic '1'
config nodes '696cd32c1d5149ee95fd1b3accbad6df'
config nodes 'myshunt'
option remarks '分流总节点'
option type 'Xray'
option type 'V2ray'
option protocol '_shunt'
option AD 'nil'
option BT '_direct'
option Telegram 'nil'
option YouTube 'nil'
option Netflix 'nil'
option TVB 'nil'
option China 'nil'
option China '_direct'
option default_node 'nil'
option domainStrategy 'IPIfNonMatch'
option LAN '_direct'
option Direct '_direct'
option Proxy '_default'
option Netflix 'nil'
option domainStrategy 'IPOnDemand'
option domainStrategy 'hybrid'
config shunt_rules 'LAN'
option remarks 'LAN'
option network 'tcp,udp'
option ip_list '0.0.0.0/8
10.0.0.0/8
100.64.0.0/10
127.0.0.0/8
169.254.0.0/16
172.16.0.0/12
192.168.0.0/16
224.0.0.0/4
240.0.0.0/4
'
config shunt_rules 'Direct'
option network 'tcp,udp'
option domain_list 'apple.com
microsoft.com
dyndns.com
douyucdn.cn
douyucdn2.cn
steamcontent.com
dl.steam.clngaa.com
dl.steam.ksyna.com
st.dl.bscstorage.net
st.dl.eccdnx.com
st.dl.pinyuncloud.com
cdn.mileweb.cs.steampowered.com.8686c.com
cdn-ws.content.steamchina.com
cdn-qc.content.steamchina.com
cdn-ali.content.steamchina.com
epicgames-download1-1251447533.file.myqcloud.com'
option remarks 'Direct'
option ip_list '114.114.114.114
114.114.115.115
223.5.5.5
223.6.6.6
119.29.29.29
180.76.76.76
'
config shunt_rules 'AD'
option remarks 'AD'
option domain_list 'geosite:category-ads'
option network 'tcp,udp'
config shunt_rules 'BT'
option remarks 'BT'
option protocol 'bittorrent'
config shunt_rules 'Telegram'
option remarks 'Telegram'
option ip_list '149.154.160.0/20
91.108.4.0/22
91.108.56.0/24
109.239.140.0/24
67.198.55.0/24'
config shunt_rules 'YouTube'
option remarks 'YouTube'
option domain_list 'youtube
youtube.com
youtu.be
googlevideo.com
ytimg.com
gvt2.com'
option network 'tcp,udp'
config shunt_rules 'Netflix'
option remarks 'Netflix'
option network 'tcp,udp'
option domain_list 'fast.com
netflix
netflix.com
@@ -138,14 +142,56 @@ netflixdnstest5.com
netflixdnstest6.com
netflixdnstest7.com
netflixdnstest8.com
netflixdnstest9.com'
netflixdnstest9.com
geosite:netflix'
config shunt_rules 'TVB'
option remarks 'TVB'
option network 'tcp,udp'
option domain_list 'tvb.com
mytvsuper.com'
config shunt_rules 'Proxy'
option network 'tcp,udp'
option domain_list 'bing.com
sspanel.net
v2ex.com
googleapis.cn
googleapis.com
google.com.tw
google.com.hk
gstatic.com
xn--ngstr-lra8j.com
github.com
'
option remarks 'Proxy'
option ip_list '149.154.160.0/20
91.108.4.0/22
91.108.56.0/24
109.239.140.0/24
67.198.55.0/24
8.8.4.4
8.8.8.8
208.67.222.222
208.67.220.220
1.1.1.1
1.1.1.2
1.0.0.1
9.9.9.9
149.112.112.112
2001:67c:4e8::/48
2001:b28:f23c::/48
2001:b28:f23d::/48
2001:b28:f23f::/48
2001:b28:f242::/48
'
config shunt_rules 'China'
option remarks 'China'
option domain_list 'geosite:cn'
option network 'tcp,udp'
option ip_list 'geoip:cn'
option domain_list 'geosite:cn'

View File

@@ -0,0 +1,761 @@
#!/bin/sh
# Copyright (C) 2022 xiaorouji
. $IPKG_INSTROOT/lib/functions.sh
. $IPKG_INSTROOT/lib/functions/service.sh
CONFIG=passwall2
TMP_PATH=/tmp/etc/$CONFIG
TMP_BIN_PATH=$TMP_PATH/bin
TMP_SCRIPT_FUNC_PATH=$TMP_PATH/script_func
TMP_ID_PATH=$TMP_PATH/id
TMP_PORT_PATH=$TMP_PATH/port
TMP_ROUTE_PATH=$TMP_PATH/route
TMP_ACL_PATH=$TMP_PATH/acl
TMP_PATH2=/tmp/etc/${CONFIG}_tmp
DNSMASQ_PATH=/etc/dnsmasq.d
TMP_DNSMASQ_PATH=/tmp/dnsmasq.d/passwall2
LOG_FILE=/tmp/log/$CONFIG.log
APP_PATH=/usr/share/$CONFIG
RULES_PATH=/usr/share/${CONFIG}/rules
TUN_DNS_PORT=15353
TUN_DNS="127.0.0.1#${TUN_DNS_PORT}"
DEFAULT_DNS=
NO_PROXY=0
PROXY_IPV6=0
PROXY_IPV6_UDP=0
LUA_API_PATH=/usr/lib/lua/luci/model/cbi/$CONFIG/api
API_GEN_SS=$LUA_API_PATH/gen_shadowsocks.lua
API_GEN_V2RAY=$LUA_API_PATH/gen_v2ray.lua
API_GEN_V2RAY_PROTO=$LUA_API_PATH/gen_v2ray_proto.lua
API_GEN_NAIVE=$LUA_API_PATH/gen_naiveproxy.lua
API_GEN_HYSTERIA=$LUA_API_PATH/gen_hysteria.lua
V2RAY_ARGS=""
V2RAY_CONFIG=""
echolog() {
local d="$(date "+%Y-%m-%d %H:%M:%S")"
echo -e "$d: $*" >>$LOG_FILE
}
config_get_type() {
local ret=$(uci -q get "${CONFIG}.${1}" 2>/dev/null)
echo "${ret:=$2}"
}
config_n_get() {
local ret=$(uci -q get "${CONFIG}.${1}.${2}" 2>/dev/null)
echo "${ret:=$3}"
}
config_t_get() {
local index=${4:-0}
local ret=$(uci -q get "${CONFIG}.@${1}[${index}].${2}" 2>/dev/null)
echo "${ret:=${3}}"
}
get_enabled_anonymous_secs() {
uci -q show "${CONFIG}" | grep "${1}\[.*\.enabled='1'" | cut -d '.' -sf2
}
get_host_ip() {
local host=$2
local count=$3
[ -z "$count" ] && count=3
local isip=""
local ip=$host
if [ "$1" == "ipv6" ]; then
isip=$(echo $host | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}")
if [ -n "$isip" ]; then
isip=$(echo $host | cut -d '[' -f2 | cut -d ']' -f1)
else
isip=$(echo $host | grep -E "([0-9]{1,3}[\.]){3}[0-9]{1,3}")
fi
else
isip=$(echo $host | grep -E "([0-9]{1,3}[\.]){3}[0-9]{1,3}")
fi
[ -z "$isip" ] && {
local t=4
[ "$1" == "ipv6" ] && t=6
local vpsrip=$(resolveip -$t -t $count $host | awk 'NR==1{print}')
ip=$vpsrip
}
echo $ip
}
get_node_host_ip() {
local ip
local address=$(config_n_get $1 address)
[ -n "$address" ] && {
local use_ipv6=$(config_n_get $1 use_ipv6)
local network_type="ipv4"
[ "$use_ipv6" == "1" ] && network_type="ipv6"
ip=$(get_host_ip $network_type $address)
}
echo $ip
}
get_ip_port_from() {
local __host=${1}; shift 1
local __ipv=${1}; shift 1
local __portv=${1}; shift 1
local __ucipriority=${1}; shift 1
local val1 val2
if [ -n "${__ucipriority}" ]; then
val2=$(config_n_get ${__host} port $(echo $__host | sed -n 's/^.*[:#]\([0-9]*\)$/\1/p'))
val1=$(config_n_get ${__host} address "${__host%%${val2:+[:#]${val2}*}}")
else
val2=$(echo $__host | sed -n 's/^.*[:#]\([0-9]*\)$/\1/p')
val1="${__host%%${val2:+[:#]${val2}*}}"
fi
eval "${__ipv}=\"$val1\"; ${__portv}=\"$val2\""
}
host_from_url(){
local f=${1}
## Remove protocol part of url ##
f="${f##http://}"
f="${f##https://}"
f="${f##ftp://}"
f="${f##sftp://}"
## Remove username and/or username:password part of URL ##
f="${f##*:*@}"
f="${f##*@}"
## Remove rest of urls ##
f="${f%%/*}"
echo "${f%%:*}"
}
hosts_foreach() {
local __hosts
eval "__hosts=\$${1}"; shift 1
local __func=${1}; shift 1
local __default_port=${1}; shift 1
local __ret=1
[ -z "${__hosts}" ] && return 0
local __ip __port
for __host in $(echo $__hosts | sed 's/[ ,]/\n/g'); do
get_ip_port_from "$__host" "__ip" "__port"
eval "$__func \"${__host}\" \"\${__ip}\" \"\${__port:-${__default_port}}\" \"$@\""
__ret=$?
[ ${__ret} -ge ${ERROR_NO_CATCH:-1} ] && return ${__ret}
done
}
check_host() {
local f=${1}
a=$(echo $f | grep "\/")
[ -n "$a" ] && return 1
# 判断是否包含汉字~
local tmp=$(echo -n $f | awk '{print gensub(/[!-~]/,"","g",$0)}')
[ -n "$tmp" ] && return 1
return 0
}
get_first_dns() {
local __hosts_val=${1}; shift 1
__first() {
[ -z "${2}" ] && return 0
echo "${2}#${3}"
return 1
}
eval "hosts_foreach \"${__hosts_val}\" __first \"$@\""
}
get_last_dns() {
local __hosts_val=${1}; shift 1
local __first __last
__every() {
[ -z "${2}" ] && return 0
__last="${2}#${3}"
__first=${__first:-${__last}}
}
eval "hosts_foreach \"${__hosts_val}\" __every \"$@\""
[ "${__first}" == "${__last}" ] || echo "${__last}"
}
check_port_exists() {
port=$1
protocol=$2
[ -n "$protocol" ] || protocol="tcp,udp"
result=
if [ "$protocol" = "tcp" ]; then
result=$(netstat -tln | grep -c ":$port ")
elif [ "$protocol" = "udp" ]; then
result=$(netstat -uln | grep -c ":$port ")
elif [ "$protocol" = "tcp,udp" ]; then
result=$(netstat -tuln | grep -c ":$port ")
fi
echo "${result}"
}
get_new_port() {
port=$1
[ "$port" == "auto" ] && port=2082
protocol=$(echo $2 | tr 'A-Z' 'a-z')
result=$(check_port_exists $port $protocol)
if [ "$result" != 0 ]; then
temp=
if [ "$port" -lt 65535 ]; then
temp=$(expr $port + 1)
elif [ "$port" -gt 1 ]; then
temp=$(expr $port - 1)
fi
get_new_port $temp $protocol
else
echo $port
fi
}
first_type() {
local path_name=${1}
type -t -p "/bin/${path_name}" -p "${TMP_BIN_PATH}/${path_name}" -p "${path_name}" "$@" | head -n1
}
eval_set_val() {
for i in $@; do
for j in $i; do
eval $j
done
done
}
eval_unset_val() {
for i in $@; do
for j in $i; do
eval unset j
done
done
}
ln_run() {
local file_func=${1}
local ln_name=${2}
local output=${3}
shift 3;
if [ "${file_func%%/*}" != "${file_func}" ]; then
[ ! -L "${file_func}" ] && {
ln -s "${file_func}" "${TMP_BIN_PATH}/${ln_name}" >/dev/null 2>&1
file_func="${TMP_BIN_PATH}/${ln_name}"
}
[ -x "${file_func}" ] || echolog " - $(readlink ${file_func}) 没有执行权限,无法启动:${file_func} $*"
fi
#echo "${file_func} $*" >&2
[ -n "${file_func}" ] || echolog " - 找不到 ${ln_name},无法启动..."
${file_func:-echolog " - ${ln_name}"} "$@" >${output} 2>&1 &
process_count=$(ls $TMP_SCRIPT_FUNC_PATH | grep -v "^_" | wc -l)
process_count=$((process_count + 1))
echo "${file_func:-echolog " - ${ln_name}"} $@ >${output}" > $TMP_SCRIPT_FUNC_PATH/$process_count
}
lua_api() {
local func=${1}
[ -z "${func}" ] && {
echo "nil"
return
}
echo $(lua -e "local api = require 'luci.model.cbi.passwall2.api.api' print(api.${func})")
}
run_v2ray() {
local flag node redir_port socks_address socks_port socks_username socks_password http_address http_port http_username http_password dns_listen_port dns_local dns_proto dns_tcp_server doh dns_client_ip dns_query_strategy dns_cache loglevel log_file config_file
local _extra_param=""
eval_set_val $@
local type=$(echo $(config_n_get $node type) | tr 'A-Z' 'a-z')
if [ "$type" != "v2ray" ] && [ "$type" != "xray" ]; then
local bin=$(first_type $(config_t_get global_app v2ray_file) v2ray)
if [ -n "$bin" ]; then
type="v2ray"
else
bin=$(first_type $(config_t_get global_app xray_file) xray)
[ -n "$bin" ] && type="xray"
fi
fi
[ -z "$type" ] && return 1
[ -n "$log_file" ] || local log_file="/dev/null"
[ -z "$loglevel" ] && local loglevel=$(config_t_get global loglevel "warning")
[ -n "$flag" ] && pgrep -af "$TMP_BIN_PATH" | awk -v P1="${flag}" 'BEGIN{IGNORECASE=1}$0~P1{print $1}' | xargs kill -9 >/dev/null 2>&1
[ -n "$flag" ] && _extra_param="${_extra_param} -flag $flag"
[ -n "$socks_address" ] && _extra_param="${_extra_param} -local_socks_address $socks_address"
[ -n "$socks_port" ] && _extra_param="${_extra_param} -local_socks_port $socks_port"
[ -n "$socks_username" ] && [ -n "$socks_password" ] && _extra_param="${_extra_param} -local_socks_username $socks_username -local_socks_password $socks_password"
[ -n "$http_address" ] && _extra_param="${_extra_param} -local_http_address $http_address"
[ -n "$http_port" ] && _extra_param="${_extra_param} -local_http_port $http_port"
[ -n "$http_username" ] && [ -n "$http_password" ] && _extra_param="${_extra_param} -local_http_username $http_username -local_http_password $http_password"
[ -n "$dns_listen_port" ] && _extra_param="${_extra_param} -dns_listen_port ${dns_listen_port}"
[ -n "$dns_query_strategy" ] && _extra_param="${_extra_param} -dns_query_strategy ${dns_query_strategy}"
[ -n "$dns_client_ip" ] && _extra_param="${_extra_param} -dns_client_ip ${dns_client_ip}"
[ -n "$dns_cache" ] && _extra_param="${_extra_param} -dns_cache ${dns_cache}"
local sniffing=$(config_t_get global_forwarding sniffing 1)
[ "${sniffing}" = "1" ] && {
_extra_param="${_extra_param} -sniffing 1"
local route_only=$(config_t_get global_forwarding route_only 0)
[ "${route_only}" = "1" ] && _extra_param="${_extra_param} -route_only 1"
}
[ -n "$dns_local" ] && {
local local_dns=$(echo $dns_local | awk -F ',' '{print $1}')
local local_dns_ip=$(echo $local_dns | sed 's/#/:/g' | awk -F ':' '{print $1}')
local local_dns_port=$(echo $local_dns | sed 's/#/:/g' | awk -F ':' '{print $2}')
[ -n "${local_dns_ip}" ] && _extra_param="${_extra_param} -local_dns_ip ${local_dns_ip} -local_dns_address ${local_dns_ip} -local_dns_port ${local_dns_port:-53}"
}
case "$dns_proto" in
tcp)
local _dns_forward=$(get_first_dns dns_tcp_server 53 | sed 's/#/:/g')
local _dns_address=$(echo ${_dns_forward} | awk -F ':' '{print $1}')
_extra_param="${_extra_param} -dns_server ${_dns_address} -dns_tcp_server tcp://${_dns_forward}"
;;
doh)
local _doh_url=$(echo $doh | awk -F ',' '{print $1}')
local _doh_host_port=$(echo $_doh_url | sed "s/https:\/\///g" | awk -F '/' '{print $1}')
local _doh_host=$(echo $_doh_host_port | awk -F ':' '{print $1}')
local _doh_port=$(echo $_doh_host_port | awk -F ':' '{print $2}')
local _doh_bootstrap=$(echo $doh | cut -d ',' -sf 2-)
_extra_param="${_extra_param} -dns_server ${_doh_bootstrap} -doh_url ${_doh_url} -doh_host ${_doh_host}"
;;
fakedns)
_extra_param="${_extra_param} -dns_fakedns 1"
;;
esac
lua $API_GEN_V2RAY -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 -config="$config_file"
}
run_socks() {
local flag node bind socks_port config_file http_port http_config_file relay_port log_file
eval_set_val $@
[ -n "$config_file" ] && config_file=$TMP_PATH/$config_file
[ -n "$http_port" ] || http_port=0
[ -n "$http_config_file" ] && http_config_file=$TMP_PATH/$http_config_file
if [ -n "$log_file" ]; then
log_file=$TMP_PATH/$log_file
else
log_file="/dev/null"
fi
local type=$(echo $(config_n_get $node type) | tr 'A-Z' 'a-z')
local remarks=$(config_n_get $node remarks)
local server_host=$(config_n_get $node address)
local port=$(config_n_get $node port)
[ -n "$relay_port" ] && {
server_host="127.0.0.1"
port=$relay_port
}
local error_msg tmp
if [ -n "$server_host" ] && [ -n "$port" ]; then
check_host $server_host
[ $? != 0 ] && {
echolog " - Socks节点[$remarks]${server_host} 是非法的服务器地址,无法启动!"
return 1
}
tmp="${server_host}:${port}"
else
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
fi
[ -n "${error_msg}" ] && {
[ "$bind" != "127.0.0.1" ] && echolog " - Socks节点[$remarks]${tmp},启动中止 ${bind}:${socks_port} ${error_msg}"
return 1
}
[ "$bind" != "127.0.0.1" ] && echolog " - Socks节点[$remarks]${tmp},启动 ${bind}:${socks_port}"
case "$type" in
v2ray|\
xray)
[ "$http_port" != "0" ] && {
local _extra_param="-local_http_port $http_port"
config_file=$(echo $config_file | sed "s/SOCKS/HTTP_SOCKS/g")
}
lua $API_GEN_V2RAY -node $node -local_socks_port $socks_port ${_extra_param} > $config_file
ln_run "$(first_type $(config_t_get global_app ${type}_file) ${type})" ${type} $log_file -config="$config_file"
;;
naiveproxy)
lua $API_GEN_NAIVE -node $node -run_type socks -local_addr $bind -local_port $socks_port -server_host $server_host -server_port $port > $config_file
ln_run "$(first_type naive)" naive $log_file "$config_file"
;;
brook)
local protocol=$(config_n_get $node protocol client)
local prefix=""
[ "$protocol" == "wsclient" ] && {
prefix="ws://"
local brook_tls=$(config_n_get $node brook_tls 0)
[ "$brook_tls" == "1" ] && {
prefix="wss://"
protocol="wssclient"
}
local ws_path=$(config_n_get $node ws_path "/ws")
}
server_host=${prefix}${server_host}
ln_run "$(first_type $(config_t_get global_app brook_file) brook)" "brook_SOCKS_${flag}" $log_file "$protocol" --socks5 "$bind:$socks_port" -s "${server_host}:${port}${ws_path}" -p "$(config_n_get $node password)"
;;
ssr)
lua $API_GEN_SS -node $node -local_addr "0.0.0.0" -local_port $socks_port -server_host $server_host -server_port $port > $config_file
ln_run "$(first_type ssr-local)" "ssr-local" $log_file -c "$config_file" -v -u
;;
ss)
lua $API_GEN_SS -node $node -local_addr "0.0.0.0" -local_port $socks_port -server_host $server_host -server_port $port -mode tcp_and_udp > $config_file
ln_run "$(first_type ss-local)" "ss-local" $log_file -c "$config_file" -v
;;
ss-rust)
lua $API_GEN_SS -node $node -local_addr "0.0.0.0" -local_port $socks_port -server_host $server_host -server_port $port -protocol socks -mode tcp_and_udp > $config_file
ln_run "$(first_type sslocal)" "sslocal" $log_file -c "$config_file" -v
;;
hysteria)
lua $API_GEN_HYSTERIA -node $node -local_socks_port $socks_port > $config_file
ln_run "$(first_type $(config_t_get global_app hysteria_file))" "hysteria" $log_file -c "$config_file" client
;;
esac
# http to socks
[ "$type" != "v2ray" ] && [ "$type" != "xray" ] && [ "$type" != "socks" ] && [ "$http_port" != "0" ] && [ -n "$http_config_file" ] && {
local bin=$(first_type $(config_t_get global_app v2ray_file) v2ray)
if [ -n "$bin" ]; then
type="v2ray"
else
bin=$(first_type $(config_t_get global_app xray_file) xray)
[ -n "$bin" ] && type="xray"
fi
[ -z "$type" ] && return 1
lua $API_GEN_V2RAY_PROTO -local_http_port $http_port -server_proto socks -server_address "127.0.0.1" -server_port $socks_port -server_username $_username -server_password $_password > $http_config_file
ln_run "$bin" ${type} /dev/null -config="$http_config_file"
}
}
node_switch() {
local flag new_node shunt_logic log_output
eval_set_val $@
[ -n "$flag" ] && [ -n "$new_node" ] && {
[ -n "$log_output" ] || LOG_FILE="/dev/null"
pgrep -af "$TMP_BIN_PATH" | awk -v P1="${flag}" 'BEGIN{IGNORECASE=1}$0~P1 && !/acl\/|acl_/{print $1}' | xargs kill -9 >/dev/null 2>&1
rm -rf $TMP_PATH/${flag}*
local config_file=$TMP_PATH/${flag}.json
local log_file=$TMP_PATH/${flag}.log
local port=$(cat $TMP_PORT_PATH/${flag})
[ "$shunt_logic" != "0" ] && {
local node=$(config_t_get global node nil)
[ "$(config_n_get $node protocol nil)" = "_shunt" ] && {
if [ "$shunt_logic" = "1" ]; then
uci set $CONFIG.$node.default_node="$new_node"
elif [ "$shunt_logic" = "2" ]; then
uci set $CONFIG.$node.main_node="$new_node"
fi
uci commit $CONFIG
}
new_node=$node
}
[ -s "$TMP_SCRIPT_FUNC_PATH/_${flag}" ] && {
for filename in $(ls ${TMP_SCRIPT_FUNC_PATH} | grep -v "^_"); do
cmd=$(cat ${TMP_SCRIPT_FUNC_PATH}/${filename})
[ -n "$(echo $cmd | grep "${flag}")" ] && rm -f ${TMP_SCRIPT_FUNC_PATH}/${filename}
done
local script_func=$(cat $TMP_SCRIPT_FUNC_PATH/_${flag})
local now_node_arg=$(echo $script_func | grep -o -E "node=.*" | awk -F ' ' '{print $1}')
new_script_func=$(echo $script_func | sed "s#${now_node_arg}#node=${new_node}#g")
${new_script_func}
echo $new_node > $TMP_ID_PATH/${flag}
[ "$shunt_logic" != "0" ] && [ "$(config_n_get $new_node protocol nil)" = "_shunt" ] && {
echo $(config_n_get $new_node default_node nil) > $TMP_ID_PATH/${flag}_default
echo $(config_n_get $new_node main_node nil) > $TMP_ID_PATH/${flag}_main
uci commit $CONFIG
}
#uci set $CONFIG.@global[0].node=$node
#uci commit $CONFIG
source $APP_PATH/helper_dnsmasq.sh logic_restart no_log=1
}
}
}
run_global() {
[ "$NODE" = "nil" ] && return 1
TYPE=$(echo $(config_n_get $NODE type nil) | tr 'A-Z' 'a-z')
[ "$TYPE" = "nil" ] && return 1
echo $REDIR_PORT > $TMP_PORT_PATH/global
echo $NODE > $TMP_ID_PATH/global
[ "$(config_n_get $NODE protocol nil)" = "_shunt" ] && {
local default_node=$(config_n_get $NODE default_node nil)
local main_node=$(config_n_get $NODE main_node nil)
echo $default_node > $TMP_ID_PATH/global_default
echo $main_node > $TMP_ID_PATH/global_main
}
if [ $PROXY_IPV6 == "1" ]; then
echolog "开启实验性IPv6透明代理(TProxy)请确认您的节点及类型支持IPv6"
PROXY_IPV6_UDP=1
fi
V2RAY_ARGS="flag=global node=$NODE redir_port=$REDIR_PORT"
[ -n "$DNS_PROTOCOL" ] && {
V2RAY_ARGS="${V2RAY_ARGS} dns_local=${DEFAULT_DNS} dns_listen_port=${TUN_DNS_PORT} dns_proto=${DNS_PROTOCOL} dns_query_strategy=${DNS_QUERY_STRATEGY} dns_cache=${DNS_CACHE}"
case "$DNS_PROTOCOL" in
tcp)
V2RAY_ARGS="${V2RAY_ARGS} dns_tcp_server=${DNS_FORWARD}"
echolog " - 域名解析 DNS Over TCP..."
;;
doh)
up_trust_doh=$(config_t_get global up_trust_doh "https://cloudflare-dns.com/dns-query,1.1.1.1")
V2RAY_ARGS="${V2RAY_ARGS} doh=${up_trust_doh}"
echolog " - 域名解析 DNS Over HTTPS..."
;;
fakedns)
echolog " - 域名解析 Fake DNS..."
;;
esac
local _dns_client_ip=$(config_t_get global dns_client_ip)
[ -n "${_dns_client_ip}" ] && V2RAY_ARGS="${V2RAY_ARGS} dns_client_ip=${_dns_client_ip}"
}
source $APP_PATH/helper_dnsmasq.sh stretch
source $APP_PATH/helper_dnsmasq.sh add TMP_DNSMASQ_PATH=$TMP_DNSMASQ_PATH DNSMASQ_CONF_FILE=/tmp/dnsmasq.d/dnsmasq-passwall2.conf DEFAULT_DNS=$DEFAULT_DNS TUN_DNS=$TUN_DNS
V2RAY_CONFIG=$TMP_PATH/global.json
V2RAY_LOG=$TMP_PATH/global.log
[ "$(config_t_get global close_log 1)" = "1" ] && V2RAY_LOG="/dev/null"
V2RAY_ARGS="${V2RAY_ARGS} log_file=${V2RAY_LOG} config_file=${V2RAY_CONFIG}"
run_v2ray $V2RAY_ARGS
echo "run_v2ray $V2RAY_ARGS" > $TMP_SCRIPT_FUNC_PATH/_global
}
start_socks() {
[ "$SOCKS_ENABLED" = "1" ] && {
local ids=$(uci show $CONFIG | grep "=socks" | awk -F '.' '{print $2}' | awk -F '=' '{print $1}')
[ -n "$ids" ] && {
echolog "分析 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 port=$(config_n_get $id port)
local config_file="SOCKS_${id}.json"
local log_file="SOCKS_${id}.log"
local http_port=$(config_n_get $id http_port 0)
local http_config_file="HTTP2SOCKS_${id}.json"
run_socks flag=$id node=$node bind=0.0.0.0 socks_port=$port config_file=$config_file http_port=$http_port http_config_file=$http_config_file
echo $node > $TMP_ID_PATH/SOCKS_${id}
done
}
}
}
clean_log() {
logsnum=$(cat $LOG_FILE 2>/dev/null | wc -l)
[ "$logsnum" -gt 1000 ] && {
echo "" > $LOG_FILE
echolog "日志文件过长,清空处理!"
}
}
clean_crontab() {
touch /etc/crontabs/root
#sed -i "/${CONFIG}/d" /etc/crontabs/root >/dev/null 2>&1
sed -i "/$(echo "/etc/init.d/${CONFIG}" | sed 's#\/#\\\/#g')/d" /etc/crontabs/root >/dev/null 2>&1
sed -i "/$(echo "lua ${APP_PATH}/rule_update.lua log" | sed 's#\/#\\\/#g')/d" /etc/crontabs/root >/dev/null 2>&1
sed -i "/$(echo "lua ${APP_PATH}/subscribe.lua start" | sed 's#\/#\\\/#g')/d" /etc/crontabs/root >/dev/null 2>&1
}
start_crontab() {
clean_crontab
[ "$ENABLED" != 1 ] && {
/etc/init.d/cron restart
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 点重启服务。"
}
fi
autoupdate=$(config_t_get global_rules auto_update)
weekupdate=$(config_t_get global_rules week_update)
dayupdate=$(config_t_get global_rules time_update)
if [ "$autoupdate" = "1" ]; then
local t="0 $dayupdate * * $weekupdate"
[ "$weekupdate" = "7" ] && t="0 $dayupdate * * *"
echo "$t lua $APP_PATH/rule_update.lua log > /dev/null 2>&1 &" >>/etc/crontabs/root
echolog "配置定时任务:自动更新规则。"
fi
TMP_SUB_PATH=$TMP_PATH/sub_crontabs
mkdir -p $TMP_SUB_PATH
for item in $(uci show ${CONFIG} | grep "=subscribe_list" | cut -d '.' -sf 2 | cut -d '=' -sf 1); do
if [ "$(config_n_get $item auto_update 0)" = "1" ]; then
cfgid=$(uci show ${CONFIG}.$item | head -n 1 | cut -d '.' -sf 2 | cut -d '=' -sf 1)
remark=$(config_n_get $item remark)
week_update=$(config_n_get $item week_update)
time_update=$(config_n_get $item time_update)
echo "$cfgid" >> $TMP_SUB_PATH/${week_update}_${time_update}
echolog "配置定时任务:自动更新【$remark】订阅。"
fi
done
[ -d "${TMP_SUB_PATH}" ] && {
for name in $(ls ${TMP_SUB_PATH}); do
week_update=$(echo $name | awk -F '_' '{print $1}')
time_update=$(echo $name | awk -F '_' '{print $2}')
local t="0 $time_update * * $week_update"
[ "$week_update" = "7" ] && t="0 $time_update * * *"
cfgids=$(echo -n $(cat ${TMP_SUB_PATH}/${name}) | sed 's# #,#g')
echo "$t lua $APP_PATH/subscribe.lua start $cfgids > /dev/null 2>&1 &" >>/etc/crontabs/root
done
rm -rf $TMP_SUB_PATH
}
if [ "$NO_PROXY" == 0 ]; then
start_daemon=$(config_t_get global_delay start_daemon 0)
[ "$start_daemon" = "1" ] && $APP_PATH/monitor.sh > /dev/null 2>&1 &
AUTO_SWITCH_ENABLE=$(config_t_get auto_switch enable 0)
[ "$AUTO_SWITCH_ENABLE" = "1" ] && $APP_PATH/test.sh > /dev/null 2>&1 &
else
echolog "运行于非代理模式,仅允许服务启停的定时任务。"
fi
/etc/init.d/cron restart
}
stop_crontab() {
clean_crontab
/etc/init.d/cron restart
#echolog "清除定时执行命令。"
}
kill_all() {
kill -9 $(pidof "$@") >/dev/null 2>&1
}
boot() {
[ "$ENABLED" == 1 ] && {
local delay=$(config_t_get global_delay start_delay 1)
if [ "$delay" -gt 0 ]; then
echolog "执行启动延时 $delay 秒后再启动!"
sleep $delay && start >/dev/null 2>&1 &
else
start
fi
}
return 0
}
start() {
ulimit -n 65535
start_socks
[ "$NO_PROXY" == 1 ] || {
if [ -z "$(command -v iptables-legacy || command -v iptables)" ] || [ -z "$(command -v ipset)" ]; then
echolog "系统未安装iptables或ipset无法透明代理"
else
run_global
source $APP_PATH/iptables.sh start
source $APP_PATH/helper_dnsmasq.sh logic_restart
fi
}
start_crontab
echolog "运行完成!\n"
}
stop() {
clean_log
source $APP_PATH/iptables.sh stop
kill_all v2ray-plugin obfs-local
pgrep -f "sleep.*(6s|9s|58s)" | xargs kill -9 >/dev/null 2>&1
pgrep -af "${CONFIG}/" | awk '! /app\.sh|subscribe\.lua|rule_update\.lua/{print $1}' | xargs kill -9 >/dev/null 2>&1
unset V2RAY_LOCATION_ASSET
unset XRAY_LOCATION_ASSET
stop_crontab
source $APP_PATH/helper_dnsmasq.sh del
source $APP_PATH/helper_dnsmasq.sh restart no_log=1
rm -rf ${TMP_PATH}
rm -rf /tmp/lock/${CONFIG}_script.lock
echolog "清空并关闭相关程序和缓存完成。"
exit 0
}
ENABLED=$(config_t_get global enabled 0)
SOCKS_ENABLED=$(config_t_get global socks_enabled 0)
REDIR_PORT=$(echo $(get_new_port 1041 tcp,udp))
[ "$ENABLED" != 1 ] && NO_PROXY=1
NODE=$(config_t_get global node nil)
[ "$NODE" == "nil" ] && NO_PROXY=1
[ "$(config_get_type $NODE nil)" == "nil" ] && NO_PROXY=1
tcp_proxy_way=$(config_t_get global_forwarding tcp_proxy_way redirect)
RESOLVFILE=/tmp/resolv.conf.d/resolv.conf.auto
[ -f "${RESOLVFILE}" ] && [ -s "${RESOLVFILE}" ] || RESOLVFILE=/tmp/resolv.conf.auto
TCP_NO_REDIR_PORTS=$(config_t_get global_forwarding tcp_no_redir_ports 'disable')
UDP_NO_REDIR_PORTS=$(config_t_get global_forwarding udp_no_redir_ports 'disable')
TCP_REDIR_PORTS="1:65535"
UDP_REDIR_PORTS="1:65535"
TCP_PROXY_MODE="global"
UDP_PROXY_MODE="global"
LOCALHOST_TCP_PROXY_MODE="global"
LOCALHOST_UDP_PROXY_MODE="global"
DNS_PROTOCOL=$(config_t_get global dns_protocol tcp)
DNS_FORWARD=$(config_t_get global dns_forward 1.1.1.1:53 | sed 's/#/:/g' | sed -E 's/\:([^:]+)$/#\1/g')
DNS_CACHE=$(config_t_get global dns_cache 0)
DEFAULT_DNS=$(uci show dhcp | grep "@dnsmasq" | grep "\.server=" | awk -F '=' '{print $2}' | sed "s/'//g" | tr ' ' '\n' | grep -v "\/" | head -2 | sed ':label;N;s/\n/,/;b label')
[ -z "${DEFAULT_DNS}" ] && DEFAULT_DNS=$(echo -n $(sed -n 's/^nameserver[ \t]*\([^ ]*\)$/\1/p' "${RESOLVFILE}" | grep -v -E "0.0.0.0|127.0.0.1|::" | head -2) | tr ' ' ',')
PROXY_IPV6=$(config_t_get global_forwarding ipv6_tproxy 0)
DNS_QUERY_STRATEGY="UseIPv4"
[ "$PROXY_IPV6" = "1" ] && DNS_QUERY_STRATEGY="UseIP"
export V2RAY_LOCATION_ASSET=$(config_t_get global_rules v2ray_location_asset "/usr/share/v2ray/")
export XRAY_LOCATION_ASSET=$V2RAY_LOCATION_ASSET
mkdir -p /tmp/etc $TMP_PATH $TMP_BIN_PATH $TMP_SCRIPT_FUNC_PATH $TMP_ID_PATH $TMP_PORT_PATH $TMP_ROUTE_PATH $TMP_ACL_PATH $TMP_PATH2
arg1=$1
shift
case $arg1 in
get_new_port)
get_new_port $@
;;
run_v2ray)
run_v2ray $@
;;
run_socks)
run_socks $@
;;
node_switch)
node_switch $@
;;
echolog)
echolog $@
;;
stop)
stop
;;
start)
start
;;
boot)
boot
;;
esac

View File

@@ -0,0 +1,138 @@
#!/bin/sh
stretch() {
#zhenduiluanshezhiDNSderen
local dnsmasq_server=$(uci -q get dhcp.@dnsmasq[0].server)
local dnsmasq_noresolv=$(uci -q get dhcp.@dnsmasq[0].noresolv)
local _flag
for server in $dnsmasq_server; do
[ -z "$(echo $server | grep '\/')" ] && _flag=1
done
[ -z "$_flag" ] && [ "$dnsmasq_noresolv" = "1" ] && {
uci -q delete dhcp.@dnsmasq[0].noresolv
uci -q set dhcp.@dnsmasq[0].resolvfile="$RESOLVFILE"
uci commit dhcp
}
}
backup_servers() {
DNSMASQ_DNS=$(uci show dhcp | grep "@dnsmasq" | grep ".server=" | awk -F '=' '{print $2}' | sed "s/'//g" | tr ' ' ',')
if [ -n "${DNSMASQ_DNS}" ]; then
uci -q set $CONFIG.@global[0].dnsmasq_servers="${DNSMASQ_DNS}"
uci commit $CONFIG
fi
}
restore_servers() {
OLD_SERVER=$(uci -q get $CONFIG.@global[0].dnsmasq_servers | tr "," " ")
for server in $OLD_SERVER; do
uci -q del_list dhcp.@dnsmasq[0].server=$server
uci -q add_list dhcp.@dnsmasq[0].server=$server
done
uci commit dhcp
uci -q delete $CONFIG.@global[0].dnsmasq_servers
uci commit $CONFIG
}
logic_restart() {
local no_log
eval_set_val $@
_LOG_FILE=$LOG_FILE
[ -n "$no_log" ] && LOG_FILE="/dev/null"
if [ -f "$TMP_PATH/default_DNS" ]; then
backup_servers
#sed -i "/list server/d" /etc/config/dhcp >/dev/null 2>&1
for server in $(uci -q get dhcp.@dnsmasq[0].server); do
[ -n "$(echo $server | grep '\/')" ] || uci -q del_list dhcp.@dnsmasq[0].server="$server"
done
/etc/init.d/dnsmasq restart >/dev/null 2>&1
restore_servers
else
/etc/init.d/dnsmasq restart >/dev/null 2>&1
fi
echolog "重启 dnsmasq 服务"
LOG_FILE=${_LOG_FILE}
}
restart() {
local no_log
eval_set_val $@
_LOG_FILE=$LOG_FILE
[ -n "$no_log" ] && LOG_FILE="/dev/null"
/etc/init.d/dnsmasq restart >/dev/null 2>&1
echolog "重启 dnsmasq 服务"
LOG_FILE=${_LOG_FILE}
}
gen_items() {
local ipsets dnss outf ipsetoutf
eval_set_val $@
awk -v ipsets="${ipsets}" -v dnss="${dnss}" -v outf="${outf}" -v ipsetoutf="${ipsetoutf}" '
BEGIN {
if(outf == "") outf="/dev/stdout";
if(ipsetoutf == "") ipsetoutf=outf;
split(dnss, dns, ","); setdns=length(dns)>0; setlist=length(ipsets)>0;
if(setdns) for(i in dns) if(length(dns[i])==0) delete dns[i];
fail=1;
}
! /^$/&&!/^#/ {
fail=0
if(setdns) for(i in dns) printf("server=/.%s/%s\n", $0, dns[i]) >>outf;
if(setlist) printf("ipset=/.%s/%s\n", $0, ipsets) >>ipsetoutf;
}
END {fflush(outf); close(outf); fflush(ipsetoutf); close(ipsetoutf); exit(fail);}
'
}
add() {
local TMP_DNSMASQ_PATH DNSMASQ_CONF_FILE DEFAULT_DNS TUN_DNS NO_LOGIC_LOG
eval_set_val $@
_LOG_FILE=$LOG_FILE
[ -n "$NO_LOGIC_LOG" ] && LOG_FILE="/dev/null"
mkdir -p "${TMP_DNSMASQ_PATH}" "${DNSMASQ_PATH}" "/tmp/dnsmasq.d"
#始终用国内DNS解析节点域名
servers=$(uci show "${CONFIG}" | grep ".address=" | cut -d "'" -f 2)
hosts_foreach "servers" host_from_url | grep '[a-zA-Z]$' | sort -u | gen_items ipsets="vpsiplist,vpsiplist6" dnss="${DEFAULT_DNS}" outf="${TMP_DNSMASQ_PATH}/10-vpsiplist_host.conf" ipsetoutf="${TMP_DNSMASQ_PATH}/ipset.conf"
echolog " - [$?]节点列表中的域名(vpsiplist)${DEFAULT_DNS:-默认}"
echo "conf-dir=${TMP_DNSMASQ_PATH}" > $DNSMASQ_CONF_FILE
[ -n "${TUN_DNS}" ] && {
echo "${DEFAULT_DNS}" > $TMP_PATH/default_DNS
cat <<-EOF >> $DNSMASQ_CONF_FILE
server=${TUN_DNS}
all-servers
no-poll
no-resolv
EOF
echolog " - [$?]默认:${TUN_DNS}"
}
LOG_FILE=${_LOG_FILE}
}
del() {
rm -rf /tmp/dnsmasq.d/dnsmasq-$CONFIG.conf
rm -rf $DNSMASQ_PATH/dnsmasq-$CONFIG.conf
}
arg1=$1
shift
case $arg1 in
stretch)
stretch $@
;;
add)
add $@
;;
del)
del $@
;;
restart)
restart $@
;;
logic_restart)
logic_restart $@
;;
*) ;;
esac

View File

@@ -0,0 +1,946 @@
#!/bin/sh
DIR="$(cd "$(dirname "$0")" && pwd)"
MY_PATH=$DIR/iptables.sh
IPSET_LANIPLIST="laniplist"
IPSET_VPSIPLIST="vpsiplist"
IPSET_LANIPLIST6="laniplist6"
IPSET_VPSIPLIST6="vpsiplist6"
FORCE_INDEX=2
. /lib/functions/network.sh
ipt=$(command -v iptables-legacy || command -v iptables)
ip6t=$(command -v ip6tables-legacy || command -v ip6tables)
ipt_n="$ipt -t nat -w"
ipt_m="$ipt -t mangle -w"
ip6t_n="$ip6t -t nat -w"
ip6t_m="$ip6t -t mangle -w"
[ -z "$ip6t" -o -z "$(lsmod | grep 'ip6table_nat')" ] && ip6t_n="eval #$ip6t_n"
[ -z "$ip6t" -o -z "$(lsmod | grep 'ip6table_mangle')" ] && ip6t_m="eval #$ip6t_m"
FWI=$(uci -q get firewall.passwall2.path 2>/dev/null)
FAKE_IP="198.18.0.0/16"
factor() {
if [ -z "$1" ] || [ -z "$2" ]; then
echo ""
elif [ "$1" == "1:65535" ]; then
echo ""
else
echo "$2 $1"
fi
}
dst() {
echo "-m set $2 --match-set $1 dst"
}
comment() {
local name=$(echo $1 | sed 's/ /_/g')
echo "-m comment --comment '$name'"
}
destroy_ipset() {
for i in "$@"; do
ipset -q -F $i
ipset -q -X $i
done
}
insert_rule_before() {
[ $# -ge 3 ] || {
return 1
}
local ipt_tmp="${1}"; shift
local chain="${1}"; shift
local keyword="${1}"; shift
local rule="${1}"; shift
local _index=$($ipt_tmp -n -L $chain --line-numbers 2>/dev/null | grep "$keyword" | head -n 1 | awk '{print $1}')
$ipt_tmp -I $chain $_index $rule
}
insert_rule_after() {
[ $# -ge 3 ] || {
return 1
}
local ipt_tmp="${1}"; shift
local chain="${1}"; shift
local keyword="${1}"; shift
local rule="${1}"; shift
local _index=$($ipt_tmp -n -L $chain --line-numbers 2>/dev/null | grep "$keyword" | awk 'END {print}' | awk '{print $1}')
_index=${_index:-0}
_index=$((_index + 1))
$ipt_tmp -I $chain $_index $rule
}
RULE_LAST_INDEX() {
[ $# -ge 3 ] || {
echolog "索引列举方式不正确iptables终止执行"
return 1
}
local ipt_tmp="${1}"; shift
local chain="${1}"; shift
local list="${1}"; shift
local default="${1:-0}"; shift
local _index=$($ipt_tmp -n -L $chain --line-numbers 2>/dev/null | grep "$list" | head -n 1 | awk '{print $1}')
echo "${_index:-${default}}"
}
REDIRECT() {
local s="-j REDIRECT"
[ -n "$1" ] && {
local s="$s --to-ports $1"
[ "$2" == "TPROXY" ] && s="-j TPROXY --tproxy-mark 0x1/0x1 --on-port $1"
[ "$2" == "MARK" ] && s="-j MARK --set-mark $1"
}
echo $s
}
get_redirect_ipt() {
echo "$(REDIRECT $2 $3)"
}
get_redirect_ip6t() {
echo "$(REDIRECT $2 $3)"
}
get_action_chain_name() {
echo "全局代理"
}
gen_laniplist() {
cat <<-EOF
0.0.0.0/8
10.0.0.0/8
100.64.0.0/10
127.0.0.0/8
169.254.0.0/16
172.16.0.0/12
192.168.0.0/16
224.0.0.0/4
240.0.0.0/4
EOF
}
gen_laniplist_6() {
cat <<-EOF
::/128
::1/128
::ffff:0:0/96
::ffff:0:0:0/96
64:ff9b::/96
100::/64
2001::/32
2001:20::/28
2001:db8::/32
2002::/16
fc00::/7
fe80::/10
ff00::/8
EOF
}
get_wan_ip() {
local NET_IF
local NET_ADDR
network_flush_cache
network_find_wan NET_IF
network_get_ipaddr NET_ADDR "${NET_IF}"
echo $NET_ADDR
}
get_wan6_ip() {
local NET_IF
local NET_ADDR
network_flush_cache
network_find_wan6 NET_IF
network_get_ipaddr6 NET_ADDR "${NET_IF}"
echo $NET_ADDR
}
load_acl() {
local items=$(uci show ${CONFIG} | grep "=acl_rule" | cut -d '.' -sf 2 | cut -d '=' -sf 1)
[ -n "$items" ] && {
local item
local redir_port dns_port dnsmasq_port
local ipt_tmp msg msg2
redir_port=11200
dns_port=11300
dnsmasq_port=11400
echolog "访问控制:"
for item in $items; do
local enabled sid remarks sources tcp_no_redir_ports udp_no_redir_ports node dns_protocol dns_forward dns_doh dns_client_ip
local _ip _mac _iprange _ipset _ip_or_mac rule_list redir_port node_remark 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-)
[ "$enabled" = "1" ] || continue
[ -z "${sources}" ] && continue
for s in $sources; do
is_iprange=$(lua_api "iprange(\"${s}\")")
if [ "${is_iprange}" = "true" ]; then
rule_list="${rule_list}\niprange:${s}"
elif [ -n "$(echo ${s} | grep '^ipset:')" ]; then
rule_list="${rule_list}\nipset:${s}"
else
_ip_or_mac=$(lua_api "ip_or_mac(\"${s}\")")
if [ "${_ip_or_mac}" = "ip" ]; then
rule_list="${rule_list}\nip:${s}"
elif [ "${_ip_or_mac}" = "mac" ]; then
rule_list="${rule_list}\nmac:${s}"
fi
fi
done
[ -z "${rule_list}" ] && continue
tcp_no_redir_ports=${tcp_no_redir_ports:-default}
udp_no_redir_ports=${udp_no_redir_ports:-default}
tcp_proxy_mode="global"
udp_proxy_mode="global"
node=${node:-default}
dns_protocol=${dns_protocol:-tcp}
dns_forward=${dns_forward:-1.1.1.1}
[ "$dns_forward" = "doh" ] && dns_forward=${dns_doh:-https://cloudflare-dns.com/dns-query,1.1.1.1}
[ "$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" != "nil" ] && {
if [ "$node" = "default" ]; then
node=$NODE
redir_port=$REDIR_PORT
else
[ "$(config_get_type $node nil)" = "nodes" ] && {
if [ "$node" = "$NODE" ]; then
redir_port=$REDIR_PORT
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}" ] && ([ "${type}" = "v2ray" ] || [ "${type}" = "xray" ]); then
config_file=$TMP_ACL_PATH/${node}_TCP_UDP_DNS_${redir_port}.json
dns_port=$(get_new_port $(expr $dns_port + 1))
run_v2ray flag=acl_$sid node=$node redir_port=$redir_port dns_local=${DEFAULT_DNS} dns_listen_port=${dns_port} dns_proto=${dns_protocol} dns_tcp_server=${dns_forward} doh="${dns_forward}" dns_client_ip=${dns_client_ip} dns_query_strategy=${DNS_QUERY_STRATEGY} config_file=${config_file}
fi
dnsmasq_port=$(get_new_port $(expr $dnsmasq_port + 1))
redirect_dns_port=$dnsmasq_port
mkdir -p $TMP_ACL_PATH/$sid
echo "port=${dnsmasq_port}" >> $TMP_ACL_PATH/$sid/dnsmasq.conf
#echo "conf-dir=${TMP_ACL_PATH}/${sid}/dnsmasq.d" >> $TMP_ACL_PATH/$sid/dnsmasq.conf
echo "server=127.0.0.1#${dns_port}" >> $TMP_ACL_PATH/$sid/dnsmasq.conf
#source $APP_PATH/helper_dnsmasq.sh add TMP_DNSMASQ_PATH=$TMP_ACL_PATH/$sid/dnsmasq.d DNSMASQ_CONF_FILE=/dev/null TUN_DNS=127.0.0.1#${dns_port} NO_LOGIC_LOG=1
ln_run "$(first_type dnsmasq)" "dnsmasq_${sid}" "/dev/null" -C $TMP_ACL_PATH/$sid/dnsmasq.conf -x $TMP_ACL_PATH/$sid/dnsmasq.pid
eval node_${node}_$(echo -n "${tcp_proxy_mode}${dns_forward}" | md5sum | cut -d " " -f1)=${dnsmasq_port}
filter_node $node TCP > /dev/null 2>&1 &
filter_node $node UDP > /dev/null 2>&1 &
fi
}
fi
node_remark=$(config_n_get $node remarks)
}
for i in $(echo -e ${rule_list}); do
if [ -n "$(echo ${i} | grep '^iprange:')" ]; then
_iprange=$(echo ${i} | sed 's#iprange:##g')
_ipt_source=$(factor ${_iprange} "-m iprange --src-range")
msg="备注【$remarksIP range【${_iprange}】,"
elif [ -n "$(echo ${i} | grep '^ipset:')" ]; then
_ipset=$(echo ${i} | sed 's#ipset:##g')
_ipt_source="-m set --match-set ${_ipset} src"
msg="备注【$remarksIPset【${_ipset}】,"
elif [ -n "$(echo ${i} | grep '^ip:')" ]; then
_ip=$(echo ${i} | sed 's#ip:##g')
_ipt_source=$(factor ${_ip} "-s")
msg="备注【$remarksIP【${_ip}】,"
elif [ -n "$(echo ${i} | grep '^mac:')" ]; then
_mac=$(echo ${i} | sed 's#mac:##g')
_ipt_source=$(factor ${_mac} "-m mac --mac-source")
msg="备注【$remarksMAC【${_mac}】,"
else
continue
fi
ipt_tmp=$ipt_n
[ -n "${is_tproxy}" ] && ipt_tmp=$ipt_m
[ -n "$redir_port" ] && {
if [ "$tcp_proxy_mode" != "disable" ]; then
[ -n "$redirect_dns_port" ] && $ipt_n -A PSW2_REDIRECT $(comment "$remarks") -p udp ${_ipt_source} --dport 53 -j REDIRECT --to-ports $redirect_dns_port
msg2="${msg}使用TCP节点[$node_remark] [$(get_action_chain_name $tcp_proxy_mode)]"
if [ -n "${is_tproxy}" ]; then
msg2="${msg2}(TPROXY:${redir_port})代理"
ipt_tmp=$ipt_m
else
msg2="${msg2}(REDIRECT:${redir_port})代理"
fi
[ "$tcp_no_redir_ports" != "disable" ] && {
$ipt_tmp -A PSW2 $(comment "$remarks") ${_ipt_source} -p tcp -m multiport --dport $tcp_no_redir_ports -j RETURN
$ip6t_m -A PSW2 $(comment "$remarks") ${_ipt_source} -p tcp -m multiport --dport $tcp_no_redir_ports -j RETURN 2>/dev/null
msg2="${msg2}[$?]除${tcp_no_redir_ports}外的"
}
msg2="${msg2}所有端口"
$ipt_tmp -A PSW2 $(comment "$remarks") -p tcp ${_ipt_source} -d $FAKE_IP $(REDIRECT $redir_port $is_tproxy)
$ipt_tmp -A PSW2 $(comment "$remarks") -p tcp ${_ipt_source} $(factor $tcp_redir_ports "-m multiport --dport") $(REDIRECT $redir_port $is_tproxy)
[ "$accept_icmp" = "1" ] && {
$ipt_n -A PSW2 $(comment "$remarks") -p icmp ${_ipt_source} -d $FAKE_IP $(REDIRECT)
$ipt_n -A PSW2 $(comment "$remarks") -p icmp ${_ipt_source} $(REDIRECT)
}
if [ "$PROXY_IPV6" == "1" ]; then
$ip6t_m -A PSW2 $(comment "$remarks") -p tcp ${_ipt_source} $(factor $tcp_redir_ports "-m multiport --dport") $(REDIRECT $redir_port TPROXY) 2>/dev/null
[ "$accept_icmpv6" = "1" ] && {
$ip6t_n -A PSW2 $(comment "$remarks") -p ipv6-icmp ${_ipt_source} $(REDIRECT) 2>/dev/null
}
fi
else
msg2="${msg}不代理TCP"
fi
echolog " - ${msg2}"
}
$ipt_tmp -A PSW2 $(comment "$remarks") ${_ipt_source} -p tcp -j RETURN
$ip6t_m -A PSW2 $(comment "$remarks") ${_ipt_source} -p tcp -j RETURN 2>/dev/null
[ -n "$redir_port" ] && {
if [ "$udp_proxy_mode" != "disable" ]; then
msg2="${msg}使用UDP节点[$node_remark] [$(get_action_chain_name $udp_proxy_mode)]"
msg2="${msg2}(TPROXY:${redir_port})代理"
[ "$udp_no_redir_ports" != "disable" ] && {
$ipt_m -A PSW2 $(comment "$remarks") ${_ipt_source} -p udp -m multiport --dport $udp_no_redir_ports -j RETURN
$ip6t_m -A PSW2 $(comment "$remarks") ${_ipt_source} -p udp -m multiport --dport $udp_no_redir_ports -j RETURN 2>/dev/null
msg2="${msg2}[$?]除${udp_no_redir_ports}外的"
}
msg2="${msg2}所有端口"
$ipt_m -A PSW2 $(comment "$remarks") -p udp ${_ipt_source} -d $FAKE_IP $(REDIRECT $redir_port TPROXY)
$ipt_m -A PSW2 $(comment "$remarks") -p udp ${_ipt_source} $(factor $udp_redir_ports "-m multiport --dport") $(REDIRECT $redir_port TPROXY)
if [ "$PROXY_IPV6_UDP" == "1" ]; then
$ip6t_m -A PSW2 $(comment "$remarks") -p udp ${_ipt_source} $(factor $udp_redir_ports "-m multiport --dport") $(REDIRECT $redir_port TPROXY) 2>/dev/null
fi
else
msg2="${msg}不代理UDP"
fi
echolog " - ${msg2}"
}
$ipt_m -A PSW2 $(comment "$remarks") ${_ipt_source} -p udp -j RETURN
$ip6t_m -A PSW2 $(comment "$remarks") ${_ipt_source} -p udp -j RETURN 2>/dev/null
done
unset enabled sid remarks sources tcp_no_redir_ports udp_no_redir_ports node dns_protocol dns_forward dns_doh dns_client_ip
unset _ip _mac _iprange _ipset _ip_or_mac rule_list redir_port node_remark config_file
unset ipt_tmp msg msg2
unset redirect_dns_port
done
unset redir_port dns_port dnsmasq_port
unset ipt_tmp msg msg2
}
# 加载默认代理模式
local ipt_tmp=$ipt_n
if [ "$TCP_PROXY_MODE" != "disable" ]; then
[ "$TCP_NO_REDIR_PORTS" != "disable" ] && {
$ipt_tmp -A PSW2 $(comment "默认") -p tcp -m multiport --dport $TCP_NO_REDIR_PORTS -j RETURN
$ip6t_m -A PSW2 $(comment "默认") -p tcp -m multiport --dport $TCP_NO_REDIR_PORTS -j RETURN
}
ipt_tmp=$ipt_n
[ "$NODE" != "nil" ] && {
msg="TCP默认代理使用节点[$(config_n_get $NODE remarks)] [$(get_action_chain_name $TCP_PROXY_MODE)]"
if [ -n "${is_tproxy}" ]; then
ipt_tmp=$ipt_m
msg="${msg}(TPROXY:${REDIR_PORT})代理"
else
msg="${msg}(REDIRECT:${REDIR_PORT})代理"
fi
[ "$TCP_NO_REDIR_PORTS" != "disable" ] && msg="${msg}${TCP_NO_REDIR_PORTS}外的"
msg="${msg}所有端口"
$ipt_tmp -A PSW2 $(comment "默认") -p tcp -d $FAKE_IP $(REDIRECT $REDIR_PORT $is_tproxy)
$ipt_tmp -A PSW2 $(comment "默认") -p tcp $(factor $TCP_REDIR_PORTS "-m multiport --dport") $(REDIRECT $REDIR_PORT $is_tproxy)
[ "$accept_icmp" = "1" ] && {
$ipt_n -A PSW2 $(comment "默认") -p icmp -d $FAKE_IP $(REDIRECT)
$ipt_n -A PSW2 $(comment "默认") -p icmp $(REDIRECT)
}
if [ "$PROXY_IPV6" == "1" ]; then
$ip6t_m -A PSW2 $(comment "默认") -p tcp $(factor $TCP_REDIR_PORTS "-m multiport --dport") $(REDIRECT $REDIR_PORT TPROXY)
[ "$accept_icmpv6" = "1" ] && {
$ip6t_n -A PSW2 $(comment "默认") -p ipv6-icmp $(REDIRECT)
}
fi
echolog "${msg}"
}
fi
$ipt_n -A PSW2 $(comment "默认") -p tcp -j RETURN
$ipt_m -A PSW2 $(comment "默认") -p tcp -j RETURN
$ip6t_m -A PSW2 $(comment "默认") -p tcp -j RETURN
# 加载UDP默认代理模式
if [ "$UDP_PROXY_MODE" != "disable" ]; then
[ "$UDP_NO_REDIR_PORTS" != "disable" ] && {
$ipt_m -A PSW2 $(comment "默认") -p udp -m multiport --dport $UDP_NO_REDIR_PORTS -j RETURN
$ip6t_m -A PSW2 $(comment "默认") -p udp -m multiport --dport $UDP_NO_REDIR_PORTS -j RETURN
}
[ -n "1" ] && {
msg="UDP默认代理使用节点[$(config_n_get $NODE remarks)] [$(get_action_chain_name $UDP_PROXY_MODE)](TPROXY:${REDIR_PORT})代理"
[ "$UDP_NO_REDIR_PORTS" != "disable" ] && msg="${msg}${UDP_NO_REDIR_PORTS}外的"
msg="${msg}所有端口"
$ipt_m -A PSW2 $(comment "默认") -p udp -d $FAKE_IP $(REDIRECT $REDIR_PORT TPROXY)
$ipt_m -A PSW2 $(comment "默认") -p udp $(factor $UDP_REDIR_PORTS "-m multiport --dport") $(REDIRECT $REDIR_PORT TPROXY)
if [ "$PROXY_IPV6_UDP" == "1" ]; then
$ip6t_m -A PSW2 $(comment "默认") -p udp $(factor $UDP_REDIR_PORTS "-m multiport --dport") $(REDIRECT $REDIR_PORT TPROXY)
fi
echolog "${msg}"
}
fi
$ipt_m -A PSW2 $(comment "默认") -p udp -j RETURN
$ip6t_m -A PSW2 $(comment "默认") -p udp -j RETURN
}
filter_vpsip() {
uci show $CONFIG | grep ".address=" | cut -d "'" -f 2 | grep -E "([0-9]{1,3}[\.]){3}[0-9]{1,3}" | sed -e "/^$/d" | sed -e "s/^/add $IPSET_VPSIPLIST &/g" | awk '{print $0} END{print "COMMIT"}' | ipset -! -R
uci show $CONFIG | grep ".address=" | cut -d "'" -f 2 | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}" | sed -e "/^$/d" | sed -e "s/^/add $IPSET_VPSIPLIST6 &/g" | awk '{print $0} END{print "COMMIT"}' | ipset -! -R
echolog "加入所有节点到ipset[$IPSET_VPSIPLIST]直连完成"
}
filter_node() {
local proxy_node=${1}
local stream=$(echo ${2} | tr 'A-Z' 'a-z')
local proxy_port=${3}
filter_rules() {
local node=${1}
local stream=${2}
local _proxy=${3}
local _port=${4}
local _is_tproxy ipt_tmp msg msg2
if [ -n "$node" ] && [ "$node" != "nil" ]; then
local type=$(echo $(config_n_get $node type) | tr 'A-Z' 'a-z')
local address=$(config_n_get $node address)
local port=$(config_n_get $node port)
ipt_tmp=$ipt_n
_is_tproxy=${is_tproxy}
[ "$stream" == "udp" ] && _is_tproxy="TPROXY"
if [ -n "${_is_tproxy}" ]; then
ipt_tmp=$ipt_m
msg="TPROXY"
else
msg="REDIRECT"
fi
else
echolog " - 节点配置不正常,略过"
return 0
fi
local ADD_INDEX=$FORCE_INDEX
for _ipt in 4 6; do
[ "$_ipt" == "4" ] && _ipt=$ipt_tmp
[ "$_ipt" == "6" ] && _ipt=$ip6t_m
$_ipt -n -L PSW2_OUTPUT | grep -q "${address}:${port}"
if [ $? -ne 0 ]; then
unset dst_rule
local dst_rule=$(REDIRECT 1 MARK)
msg2="按规则路由(${msg})"
[ "$_ipt" == "$ipt_m" -o "$_ipt" == "$ip6t_m" ] || {
dst_rule=$(REDIRECT $_port)
msg2="套娃使用(${msg}:${port} -> ${_port})"
}
[ -n "$_proxy" ] && [ "$_proxy" == "1" ] && [ -n "$_port" ] || {
ADD_INDEX=$(RULE_LAST_INDEX "$_ipt" PSW2_OUT_PUT "$IPSET_VPSIPLIST" $FORCE_INDEX)
dst_rule=" -j RETURN"
msg2="直连代理"
}
$_ipt -I PSW2_OUTPUT $ADD_INDEX $(comment "${address}:${port}") -p $stream -d $address --dport $port $dst_rule 2>/dev/null
else
msg2="已配置过的节点,"
fi
done
msg="[$?]$(echo ${2} | tr 'a-z' 'A-Z')${msg2}使用链${ADD_INDEX},节点(${type}${address}:${port}"
#echolog " - ${msg}"
}
local proxy_protocol=$(config_n_get $proxy_node protocol)
local proxy_type=$(echo $(config_n_get $proxy_node type nil) | tr 'A-Z' 'a-z')
[ "$proxy_type" == "nil" ] && echolog " - 节点配置不正常,略过!:${proxy_node}" && return 0
if [ "$proxy_protocol" == "_balancing" ]; then
#echolog " - 多节点负载均衡(${proxy_type}..."
proxy_node=$(config_n_get $proxy_node balancing_node)
for _node in $proxy_node; do
filter_rules "$_node" "$stream"
done
elif [ "$proxy_protocol" == "_shunt" ]; then
#echolog " - 按请求目的地址分流(${proxy_type}..."
local default_node=$(config_n_get $proxy_node default_node _direct)
local main_node=$(config_n_get $proxy_node main_node nil)
if [ "$main_node" != "nil" ]; then
filter_rules $main_node $stream
else
if [ "$default_node" != "_direct" ] && [ "$default_node" != "_blackhole" ]; then
filter_rules $default_node $stream
fi
fi
:<<!
local default_node_address=$(get_host_ip ipv4 $(config_n_get $default_node address) 1)
local default_node_port=$(config_n_get $default_node port)
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_proxy=$(config_n_get $proxy_node "${shunt_id}_proxy" 0)
local shunt_proxy=0
local shunt_node=$(config_n_get $proxy_node "${shunt_id}" nil)
[ "$shunt_node" != "nil" ] && {
[ "$shunt_proxy" == 1 ] && {
local shunt_node_address=$(get_host_ip ipv4 $(config_n_get $shunt_node address) 1)
local shunt_node_port=$(config_n_get $shunt_node port)
[ "$shunt_node_address" == "$default_node_address" ] && [ "$shunt_node_port" == "$default_node_port" ] && {
shunt_proxy=0
}
}
filter_rules "$(config_n_get $proxy_node $shunt_id)" "$stream" "$shunt_proxy" "$proxy_port"
}
done
!
else
#echolog " - 普通节点(${proxy_type}..."
filter_rules "$proxy_node" "$stream"
fi
}
dns_hijack() {
$ipt_n -I PSW2 -p udp --dport 53 -j REDIRECT --to-ports 53
echolog "强制转发本机DNS端口 UDP/53 的请求[$?]"
}
add_firewall_rule() {
echolog "开始加载防火墙规则..."
ipset -! create $IPSET_LANIPLIST nethash maxelem 1048576
ipset -! create $IPSET_VPSIPLIST nethash maxelem 1048576
ipset -! create $IPSET_LANIPLIST6 nethash family inet6 maxelem 1048576
ipset -! create $IPSET_VPSIPLIST6 nethash family inet6 maxelem 1048576
ipset -! -R <<-EOF
$(gen_laniplist | sed -e "s/^/add $IPSET_LANIPLIST /")
EOF
ipset -! -R <<-EOF
$(gen_laniplist_6 | sed -e "s/^/add $IPSET_LANIPLIST6 /")
EOF
# 忽略特殊IP段
local lan_ifname lan_ip
lan_ifname=$(uci -q -p /tmp/state get network.lan.ifname)
[ -n "$lan_ifname" ] && {
lan_ip=$(ip address show $lan_ifname | grep -w "inet" | awk '{print $2}')
lan_ip6=$(ip address show $lan_ifname | grep -w "inet6" | awk '{print $2}')
#echolog "本机IPv4网段互访直连${lan_ip}"
#echolog "本机IPv6网段互访直连${lan_ip6}"
[ -n "$lan_ip" ] && ipset -! -R <<-EOF
$(echo $lan_ip | sed -e "s/ /\n/g" | sed -e "s/^/add $IPSET_LANIPLIST /")
EOF
[ -n "$lan_ip6" ] && ipset -! -R <<-EOF
$(echo $lan_ip6 | sed -e "s/ /\n/g" | sed -e "s/^/add $IPSET_LANIPLIST6 /")
EOF
}
local ISP_DNS=$(cat $RESOLVFILE 2>/dev/null | grep -E -o "[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+" | sort -u | grep -v 0.0.0.0 | grep -v 127.0.0.1)
[ -n "$ISP_DNS" ] && {
#echolog "处理 ISP DNS 例外..."
for ispip in $ISP_DNS; do
ipset -! add $IPSET_LANIPLIST $ispip >/dev/null 2>&1 &
#echolog " - 追加到白名单:${ispip}"
done
}
local ISP_DNS6=$(cat $RESOLVFILE 2>/dev/null | grep -E "([A-Fa-f0-9]{1,4}::?){1,7}[A-Fa-f0-9]{1,4}" | awk -F % '{print $1}' | awk -F " " '{print $2}'| sort -u | grep -v -Fx ::1 | grep -v -Fx ::)
[ -n "$ISP_DNS" ] && {
#echolog "处理 ISP IPv6 DNS 例外..."
for ispip6 in $ISP_DNS; do
ipset -! add $IPSET_LANIPLIST6 $ispip6 >/dev/null 2>&1 &
#echolog " - 追加到白名单:${ispip6}"
done
}
# 过滤所有节点IP
filter_vpsip > /dev/null 2>&1 &
accept_icmp=$(config_t_get global_forwarding accept_icmp 0)
accept_icmpv6=$(config_t_get global_forwarding accept_icmpv6 0)
local tcp_proxy_way=$(config_t_get global_forwarding tcp_proxy_way redirect)
if [ "$tcp_proxy_way" = "redirect" ]; then
unset is_tproxy
elif [ "$tcp_proxy_way" = "tproxy" ]; then
is_tproxy="TPROXY"
fi
$ipt_n -N PSW2
$ipt_n -A PSW2 $(dst $IPSET_LANIPLIST) -j RETURN
$ipt_n -A PSW2 $(dst $IPSET_VPSIPLIST) -j RETURN
$ipt_n -A PSW2 -m mark --mark 0xff -j RETURN
WAN_IP=$(get_wan_ip)
[ ! -z "${WAN_IP}" ] && $ipt_n -A PSW2 $(comment "WAN_IP_RETURN") -d "${WAN_IP}" -j RETURN
[ "$accept_icmp" = "1" ] && insert_rule_after "$ipt_n" "PREROUTING" "prerouting_rule" "-p icmp -j PSW2"
[ -z "${is_tproxy}" ] && insert_rule_after "$ipt_n" "PREROUTING" "prerouting_rule" "-p tcp -j PSW2"
$ipt_n -N PSW2_OUTPUT
$ipt_n -A PSW2_OUTPUT $(dst $IPSET_LANIPLIST) -j RETURN
$ipt_n -A PSW2_OUTPUT $(dst $IPSET_VPSIPLIST) -j RETURN
$ipt_n -A PSW2_OUTPUT -m mark --mark 0xff -j RETURN
$ipt_n -N PSW2_REDIRECT
$ipt_n -I PREROUTING 1 -j PSW2_REDIRECT
$ipt_m -N PSW2_DIVERT
$ipt_m -A PSW2_DIVERT -j MARK --set-mark 1
$ipt_m -A PSW2_DIVERT -j ACCEPT
$ipt_m -N PSW2
$ipt_m -A PSW2 $(dst $IPSET_LANIPLIST) -j RETURN
$ipt_m -A PSW2 $(dst $IPSET_VPSIPLIST) -j RETURN
$ipt_m -A PSW2 -m mark --mark 0xff -j RETURN
[ ! -z "${WAN_IP}" ] && $ipt_m -A PSW2 $(comment "WAN_IP_RETURN") -d "${WAN_IP}" -j RETURN
unset WAN_IP
insert_rule_after "$ipt_m" "PREROUTING" "mwan3" "-j PSW2"
insert_rule_before "$ipt_m" "PREROUTING" "PSW2" "-p tcp -m socket -j PSW2_DIVERT"
$ipt_m -N PSW2_OUTPUT
$ipt_m -A PSW2_OUTPUT $(dst $IPSET_LANIPLIST) -j RETURN
$ipt_m -A PSW2_OUTPUT $(dst $IPSET_VPSIPLIST) -j RETURN
$ipt_m -A PSW2_OUTPUT -m mark --mark 0xff -j RETURN
$ipt_m -A OUTPUT -j PSW2_OUTPUT
ip rule add fwmark 1 lookup 100
ip route add local 0.0.0.0/0 dev lo table 100
[ "$accept_icmpv6" = "1" ] && {
$ip6t_n -N PSW2
$ip6t_n -A PSW2 $(dst $IPSET_LANIPLIST6) -j RETURN
$ip6t_n -A PSW2 $(dst $IPSET_VPSIPLIST6) -j RETURN
$ip6t_n -A PSW2 -m mark --mark 0xff -j RETURN
$ip6t_n -A PREROUTING -p ipv6-icmp -j PSW2
$ip6t_n -N PSW2_OUTPUT
$ip6t_n -A PSW2_OUTPUT $(dst $IPSET_LANIPLIST6) -j RETURN
$ip6t_n -A PSW2_OUTPUT $(dst $IPSET_VPSIPLIST6) -j RETURN
$ip6t_n -A PSW2_OUTPUT -m mark --mark 0xff -j RETURN
}
$ip6t_m -N PSW2_DIVERT
$ip6t_m -A PSW2_DIVERT -j MARK --set-mark 1
$ip6t_m -A PSW2_DIVERT -j ACCEPT
$ip6t_m -N PSW2
$ip6t_m -A PSW2 $(dst $IPSET_LANIPLIST6) -j RETURN
$ip6t_m -A PSW2 $(dst $IPSET_VPSIPLIST6) -j RETURN
$ip6t_m -A PSW2 -m mark --mark 0xff -j RETURN
WAN6_IP=$(get_wan6_ip)
[ ! -z "${WAN6_IP}" ] && $ip6t_m -A PSW2 $(comment "WAN6_IP_RETURN") -d ${WAN6_IP} -j RETURN
unset WAN6_IP
insert_rule_after "$ip6t_m" "PREROUTING" "mwan3" "-j PSW2"
insert_rule_before "$ip6t_m" "PREROUTING" "PSW2" "-p tcp -m socket -j PSW2_DIVERT"
$ip6t_m -N PSW2_OUTPUT
$ip6t_m -A PSW2_OUTPUT $(dst $IPSET_LANIPLIST6) -j RETURN
$ip6t_m -A PSW2_OUTPUT $(dst $IPSET_VPSIPLIST6) -j RETURN
$ip6t_m -A PSW2_OUTPUT -m mark --mark 0xff -j RETURN
$ip6t_m -A OUTPUT -j PSW2_OUTPUT
ip -6 rule add fwmark 1 table 100
ip -6 route add local ::/0 dev lo table 100
# 加载路由器自身代理 TCP
if [ "$NODE" != "nil" ]; then
local ipt_tmp=$ipt_n
local blist_r=$(REDIRECT $REDIR_PORT)
local p_r=$(get_redirect_ipt $LOCALHOST_TCP_PROXY_MODE $REDIR_PORT)
echolog "加载路由器自身 TCP 代理..."
if [ -n "${is_tproxy}" ]; then
echolog " - 启用 TPROXY 模式"
ipt_tmp=$ipt_m
blist_r=$(REDIRECT 1 MARK)
p_r=$(get_redirect_ipt $LOCALHOST_TCP_PROXY_MODE 1 MARK)
else
$ipt_n -A OUTPUT -p tcp -j PSW2_OUTPUT
fi
[ "$accept_icmp" = "1" ] && {
$ipt_n -A OUTPUT -p icmp -j PSW2_OUTPUT
$ipt_n -A PSW2_OUTPUT -p icmp -d $FAKE_IP $(REDIRECT)
$ipt_n -A PSW2_OUTPUT -p icmp $(REDIRECT)
}
[ "$accept_icmpv6" = "1" ] && {
$ip6t_n -A OUTPUT -p ipv6-icmp -j PSW2_OUTPUT
$ip6t_n -A PSW2_OUTPUT -p ipv6-icmp $(REDIRECT)
}
[ "$TCP_NO_REDIR_PORTS" != "disable" ] && {
$ipt_tmp -A PSW2_OUTPUT -p tcp -m multiport --dport $TCP_NO_REDIR_PORTS -j RETURN
$ipt_tmp -A PSW2_OUTPUT -p tcp -m multiport --sport $TCP_NO_REDIR_PORTS -j RETURN
$ip6t_m -A PSW2_OUTPUT -p tcp -m multiport --dport $TCP_NO_REDIR_PORTS -j RETURN
$ip6t_m -A PSW2_OUTPUT -p tcp -m multiport --sport $TCP_NO_REDIR_PORTS -j RETURN
echolog " - [$?]不代理TCP 端口:$TCP_NO_REDIR_PORTS"
}
$ipt_tmp -A PSW2_OUTPUT -p tcp -d $FAKE_IP $blist_r
$ipt_tmp -A PSW2_OUTPUT -p tcp $(factor $TCP_REDIR_PORTS "-m multiport --dport") $blist_r
$ipt_tmp -A PSW2_OUTPUT -p tcp $(factor $TCP_REDIR_PORTS "-m multiport --dport") $p_r
if [ -n "${is_tproxy}" ]; then
$ipt_m -A PSW2 $(comment "本机") -p tcp -i lo -d $FAKE_IP $(REDIRECT $REDIR_PORT TPROXY)
$ipt_m -A PSW2 $(comment "本机") -p tcp -i lo $(factor $TCP_REDIR_PORTS "-m multiport --dport") $(REDIRECT $REDIR_PORT TPROXY)
$ipt_m -A PSW2 $(comment "本机") -p tcp -i lo -j RETURN
fi
if [ "$PROXY_IPV6" == "1" ]; then
$ip6t_m -A PSW2_OUTPUT -p tcp $(factor $TCP_REDIR_PORTS "-m multiport --dport") $(REDIRECT 1 MARK)
$ip6t_m -A PSW2 $(comment "本机") -p tcp -i lo $(factor $TCP_REDIR_PORTS "-m multiport --dport") $(REDIRECT $REDIR_PORT TPROXY)
$ip6t_m -A PSW2 $(comment "本机") -p tcp -i lo -j RETURN
fi
fi
# 过滤Socks节点
[ "$SOCKS_ENABLED" = "1" ] && {
local ids=$(uci show $CONFIG | grep "=socks" | awk -F '.' '{print $2}' | awk -F '=' '{print $1}')
#echolog "分析 Socks 服务所使用节点..."
local id enabled node port msg num
for id in $ids; do
enabled=$(config_n_get $id enabled 0)
[ "$enabled" == "1" ] || continue
node=$(config_n_get $id node nil)
port=$(config_n_get $id port 0)
msg="Socks 服务 [:${port}]"
if [ "$node" == "nil" ] || [ "$port" == "0" ]; then
msg="${msg} 未配置完全,略过"
else
filter_node $node TCP > /dev/null 2>&1 &
filter_node $node UDP > /dev/null 2>&1 &
fi
#echolog " - ${msg}"
done
}
# 处理轮换节点的分流或套娃
filter_node $NODE TCP > /dev/null 2>&1 &
filter_node $NODE UDP > /dev/null 2>&1 &
# 加载路由器自身代理 UDP
if [ "$NODE" != "nil" ]; then
echolog "加载路由器自身 UDP 代理..."
[ "$UDP_NO_REDIR_PORTS" != "disable" ] && {
$ipt_m -A PSW2_OUTPUT -p udp -m multiport --dport $UDP_NO_REDIR_PORTS -j RETURN
$ipt_m -A PSW2_OUTPUT -p udp -m multiport --sport $UDP_NO_REDIR_PORTS -j RETURN
$ip6t_m -A PSW2_OUTPUT -p udp -m multiport --dport $UDP_NO_REDIR_PORTS -j RETURN
$ip6t_m -A PSW2_OUTPUT -p udp -m multiport --sport $UDP_NO_REDIR_PORTS -j RETURN
echolog " - [$?]不代理 UDP 端口:$UDP_NO_REDIR_PORTS"
}
$ipt_m -A PSW2_OUTPUT -p udp -d $FAKE_IP $(REDIRECT 1 MARK)
$ipt_m -A PSW2_OUTPUT -p udp $(factor $UDP_REDIR_PORTS "-m multiport --dport") $(REDIRECT 1 MARK)
$ipt_m -A PSW2 $(comment "本机") -p udp -i lo -d $FAKE_IP $(REDIRECT $REDIR_PORT TPROXY)
$ipt_m -A PSW2 $(comment "本机") -p udp -i lo $(factor $UDP_REDIR_PORTS "-m multiport --dport") $(REDIRECT $REDIR_PORT TPROXY)
$ipt_m -A PSW2 $(comment "本机") -p udp -i lo -j RETURN
if [ "$PROXY_IPV6_UDP" == "1" ]; then
$ip6t_m -A PSW2_OUTPUT -p udp $(factor $UDP_REDIR_PORTS "-m multiport --dport") $(REDIRECT 1 MARK)
$ip6t_m -A PSW2 $(comment "本机") -p udp -i lo $(factor $UDP_REDIR_PORTS "-m multiport --dport") $(REDIRECT $REDIR_PORT TPROXY)
$ip6t_m -A PSW2 $(comment "本机") -p udp -i lo -j RETURN
fi
fi
# 加载ACLS
load_acl
# dns_hijack "force"
echolog "防火墙规则加载完成!"
}
del_firewall_rule() {
for ipt in "$ipt_n" "$ipt_m" "$ip6t_n" "$ip6t_m"; do
for chain in "PREROUTING" "OUTPUT"; do
for i in $(seq 1 $($ipt -nL $chain | grep -c PSW2)); do
local index=$($ipt --line-number -nL $chain | grep PSW2 | head -1 | awk '{print $1}')
$ipt -D $chain $index 2>/dev/null
done
done
for chain in "PSW2" "PSW2_OUTPUT" "PSW2_DIVERT" "PSW2_REDIRECT"; do
$ipt -F $chain 2>/dev/null
$ipt -X $chain 2>/dev/null
done
done
ip rule del fwmark 1 lookup 100 2>/dev/null
ip route del local 0.0.0.0/0 dev lo table 100 2>/dev/null
ip -6 rule del fwmark 1 table 100 2>/dev/null
ip -6 route del local ::/0 dev lo table 100 2>/dev/null
echolog "删除相关防火墙规则完成。"
}
flush_ipset() {
del_firewall_rule
/etc/init.d/passwall2 reload
}
flush_include() {
echo '#!/bin/sh' >$FWI
}
gen_include() {
flush_include
extract_rules() {
local _ipt="${ipt}"
[ "$1" == "6" ] && _ipt="${ip6t}"
[ -z "${_ipt}" ] && return
echo "*$2"
${_ipt}-save -t $2 | grep "PSW2" | grep -v "\-j PSW2$" | grep -v "socket \-j PSW2_DIVERT$" | sed -e "s/^-A \(OUTPUT\|PREROUTING\)/-I \1 1/"
echo 'COMMIT'
}
local __ipt=""
[ -n "${ipt}" ] && {
__ipt=$(cat <<- EOF
$ipt-save -c | grep -v "PSW2" | $ipt-restore -c
$ipt-restore -n <<-EOT
$(extract_rules 4 nat)
$(extract_rules 4 mangle)
EOT
[ "$accept_icmp" = "1" ] && \$(${MY_PATH} insert_rule_after "$ipt_n" "PREROUTING" "prerouting_rule" "-p icmp -j PSW2")
[ -z "${is_tproxy}" ] && \$(${MY_PATH} insert_rule_after "$ipt_n" "PREROUTING" "prerouting_rule" "-p tcp -j PSW2")
\$(${MY_PATH} insert_rule_after "$ipt_m" "PREROUTING" "mwan3" "-j PSW2")
\$(${MY_PATH} insert_rule_before "$ipt_m" "PREROUTING" "PSW2" "-p tcp -m socket -j PSW2_DIVERT")
WAN_IP=\$(${MY_PATH} get_wan_ip)
PR_INDEX=\$(${MY_PATH} RULE_LAST_INDEX "$ipt_n" PSW2 WAN_IP_RETURN -1)
if [ \$PR_INDEX -ge 0 ]; then
[ ! -z "\${WAN_IP}" ] && $ipt_n -R PSW2 \$PR_INDEX $(comment "WAN_IP_RETURN") -d "\${WAN_IP}" -j RETURN
fi
PR_INDEX=\$(${MY_PATH} RULE_LAST_INDEX "$ipt_m" PSW2 WAN_IP_RETURN -1)
if [ \$PR_INDEX -ge 0 ]; then
[ ! -z "\${WAN_IP}" ] && $ipt_m -R PSW2 \$PR_INDEX $(comment "WAN_IP_RETURN") -d "\${WAN_IP}" -j RETURN
fi
EOF
)
}
local __ip6t=""
[ -n "${ip6t}" ] && {
__ip6t=$(cat <<- EOF
$ip6t-save -c | grep -v "PSW2" | $ip6t-restore -c
$ip6t-restore -n <<-EOT
$(extract_rules 6 nat)
$(extract_rules 6 mangle)
EOT
[ "$accept_icmpv6" = "1" ] && $ip6t_n -A PREROUTING -p ipv6-icmp -j PSW2
\$(${MY_PATH} insert_rule_after "$ip6t_m" "PREROUTING" "mwan3" "-j PSW2")
\$(${MY_PATH} insert_rule_before "$ip6t_m" "PREROUTING" "PSW2" "-p tcp -m socket -j PSW2_DIVERT")
PR_INDEX=\$(${MY_PATH} RULE_LAST_INDEX "$ip6t_m" PSW2 WAN6_IP_RETURN -1)
if [ \$PR_INDEX -ge 0 ]; then
WAN6_IP=\$(${MY_PATH} get_wan6_ip)
[ ! -z "\${WAN6_IP}" ] && $ip6t_m -R PSW2 \$PR_INDEX $(comment "WAN6_IP_RETURN") -d "\${WAN6_IP}" -j RETURN
fi
EOF
)
}
cat <<-EOF >> $FWI
${__ipt}
${__ip6t}
EOF
return 0
}
get_ipt_bin() {
echo $ipt
}
get_ip6t_bin() {
echo $ip6t
}
start() {
add_firewall_rule
gen_include
}
stop() {
del_firewall_rule
flush_include
}
arg1=$1
shift
case $arg1 in
RULE_LAST_INDEX)
RULE_LAST_INDEX "$@"
;;
insert_rule_before)
insert_rule_before "$@"
;;
insert_rule_after)
insert_rule_after "$@"
;;
flush_ipset)
flush_ipset
;;
get_ipt_bin)
get_ipt_bin
;;
get_ip6t_bin)
get_ip6t_bin
;;
get_wan_ip)
get_wan_ip
;;
get_wan6_ip)
get_wan6_ip
;;
stop)
stop
;;
start)
start
;;
*) ;;
esac

View File

@@ -0,0 +1,47 @@
#!/bin/sh
CONFIG=passwall2
TMP_PATH=/tmp/etc/$CONFIG
TMP_SCRIPT_FUNC_PATH=$TMP_PATH/script_func
LOCK_FILE_DIR=/tmp/lock
LOCK_FILE=${LOCK_FILE_DIR}/${CONFIG}_script.lock
config_n_get() {
local ret=$(uci -q get $CONFIG.$1.$2 2>/dev/null)
echo ${ret:=$3}
}
config_t_get() {
local index=0
[ -n "$4" ] && index=$4
local ret=$(uci -q get $CONFIG.@$1[$index].$2 2>/dev/null)
echo ${ret:=$3}
}
ENABLED=$(config_t_get global enabled 0)
[ "$ENABLED" != 1 ] && return 1
ENABLED=$(config_t_get global_delay start_daemon 0)
[ "$ENABLED" != 1 ] && return 1
sleep 58s
while [ "$ENABLED" -eq 1 ]; do
[ -f "$LOCK_FILE" ] && {
sleep 6s
continue
}
touch $LOCK_FILE
[ -d ${TMP_SCRIPT_FUNC_PATH} ] && {
for filename in $(ls ${TMP_SCRIPT_FUNC_PATH} | grep -v "^_"); do
cmd=$(cat ${TMP_SCRIPT_FUNC_PATH}/${filename})
cmd_check=$(echo $cmd | awk -F '>' '{print $1}')
[ -n "$(echo $cmd_check | grep "dns2socks")" ] && cmd_check=$(echo $cmd_check | sed "s#:# #g")
icount=$(pgrep -f "$(echo $cmd_check)" | wc -l)
if [ $icount = 0 ]; then
#echo "${cmd} 进程挂掉,重启" >> /tmp/log/passwall2.log
eval $(echo "nohup ${cmd} 2>&1 &") >/dev/null 2>&1 &
fi
done
}
rm -f $LOCK_FILE
sleep 58s
done

View File

@@ -0,0 +1,196 @@
#!/usr/bin/lua
require 'nixio'
require 'luci.sys'
local luci = luci
local ucic = luci.model.uci.cursor()
local jsonc = require "luci.jsonc"
local name = 'passwall2'
local arg1 = arg[1]
local reboot = 0
local geoip_update = 0
local geosite_update = 0
local geoip_api = "https://api.github.com/repos/Loyalsoldier/v2ray-rules-dat/releases/latest"
local geosite_api = "https://api.github.com/repos/Loyalsoldier/v2ray-rules-dat/releases/latest"
local v2ray_asset_location = ucic:get_first(name, 'global_rules', "v2ray_location_asset", "/usr/share/v2ray/")
local log = function(...)
if arg1 then
local result = os.date("%Y-%m-%d %H:%M:%S: ") .. table.concat({...}, " ")
if arg1 == "log" then
local f, err = io.open("/tmp/log/passwall2.log", "a")
if f and err == nil then
f:write(result .. "\n")
f:close()
end
elseif arg1 == "print" then
print(result)
end
end
end
-- trim
local function trim(text)
if not text or text == "" then return "" end
return (string.gsub(text, "^%s*(.-)%s*$", "%1"))
end
-- curl
local function curl(url, file)
local cmd = "curl -skL -w %{http_code} --retry 3 --connect-timeout 3 '" .. url .. "'"
if file then
cmd = cmd .. " -o " .. file
end
local stdout = luci.sys.exec(cmd)
if file then
return tonumber(trim(stdout))
else
return trim(stdout)
end
end
--获取geoip
local function fetch_geoip()
--请求geoip
xpcall(function()
local json_str = curl(geoip_api)
local json = jsonc.parse(json_str)
if json.tag_name and json.assets then
for _, v in ipairs(json.assets) do
if v.name and v.name == "geoip.dat.sha256sum" then
local sret = curl(v.browser_download_url, "/tmp/geoip.dat.sha256sum")
if sret == 200 then
local f = io.open("/tmp/geoip.dat.sha256sum", "r")
local content = f:read()
f:close()
f = io.open("/tmp/geoip.dat.sha256sum", "w")
f:write(content:gsub("geoip.dat", "/tmp/geoip.dat"), "")
f:close()
if nixio.fs.access(v2ray_asset_location .. "geoip.dat") then
luci.sys.call(string.format("cp -f %s %s", v2ray_asset_location .. "geoip.dat", "/tmp/geoip.dat"))
if luci.sys.call('sha256sum -c /tmp/geoip.dat.sha256sum > /dev/null 2>&1') == 0 then
log("geoip 版本一致,无需更新。")
return 1
end
end
for _2, v2 in ipairs(json.assets) do
if v2.name and v2.name == "geoip.dat" then
sret = curl(v2.browser_download_url, "/tmp/geoip.dat")
if luci.sys.call('sha256sum -c /tmp/geoip.dat.sha256sum > /dev/null 2>&1') == 0 then
luci.sys.call(string.format("mkdir -p %s && cp -f %s %s", v2ray_asset_location, "/tmp/geoip.dat", v2ray_asset_location .. "geoip.dat"))
reboot = 1
log("geoip 更新成功。")
return 1
else
log("geoip 更新失败,请稍后再试。")
end
break
end
end
end
break
end
end
end
end,
function(e)
end)
return 0
end
--获取geosite
local function fetch_geosite()
--请求geosite
xpcall(function()
local json_str = curl(geosite_api)
local json = jsonc.parse(json_str)
if json.tag_name and json.assets then
for _, v in ipairs(json.assets) do
if v.name and v.name == "geosite.dat.sha256sum" then
local sret = curl(v.browser_download_url, "/tmp/geosite.dat.sha256sum")
if sret == 200 then
local f = io.open("/tmp/geosite.dat.sha256sum", "r")
local content = f:read()
f:close()
f = io.open("/tmp/geosite.dat.sha256sum", "w")
f:write(content:gsub("geosite.dat", "/tmp/geosite.dat"), "")
f:close()
if nixio.fs.access(v2ray_asset_location .. "geosite.dat") then
luci.sys.call(string.format("cp -f %s %s", v2ray_asset_location .. "geosite.dat", "/tmp/geosite.dat"))
if luci.sys.call('sha256sum -c /tmp/geosite.dat.sha256sum > /dev/null 2>&1') == 0 then
log("geosite 版本一致,无需更新。")
return 1
end
end
for _2, v2 in ipairs(json.assets) do
if v2.name and v2.name == "geosite.dat" then
sret = curl(v2.browser_download_url, "/tmp/geosite.dat")
if luci.sys.call('sha256sum -c /tmp/geosite.dat.sha256sum > /dev/null 2>&1') == 0 then
luci.sys.call(string.format("mkdir -p %s && cp -f %s %s", v2ray_asset_location, "/tmp/geosite.dat", v2ray_asset_location .. "geosite.dat"))
reboot = 1
log("geosite 更新成功。")
return 1
else
log("geosite 更新失败,请稍后再试。")
end
break
end
end
end
break
end
end
end
end,
function(e)
end)
return 0
end
if arg[2] then
if arg[2]:find("geoip") then
geoip_update = 1
end
if arg[2]:find("geosite") then
geosite_update = 1
end
else
geoip_update = ucic:get_first(name, 'global_rules', "geoip_update", 1)
geosite_update = ucic:get_first(name, 'global_rules', "geosite_update", 1)
end
if geoip_update == 0 and geosite_update == 0 then
os.exit(0)
end
log("开始更新规则...")
if tonumber(geoip_update) == 1 then
log("geoip 开始更新...")
local status = fetch_geoip()
os.remove("/tmp/geoip.dat")
os.remove("/tmp/geoip.dat.sha256sum")
end
if tonumber(geosite_update) == 1 then
log("geosite 开始更新...")
local status = fetch_geosite()
os.remove("/tmp/geosite.dat")
os.remove("/tmp/geosite.dat.sha256sum")
end
ucic:set(name, ucic:get_first(name, 'global_rules'), "geoip_update", geoip_update)
ucic:set(name, ucic:get_first(name, 'global_rules'), "geosite_update", geosite_update)
ucic:save(name)
luci.sys.call("uci commit " .. name)
if reboot == 1 then
log("重启服务,应用新的规则。")
luci.sys.call("/usr/share/" .. name .. "/iptables.sh flush_ipset > /dev/null 2>&1 &")
end
log("规则更新完毕...")

View File

@@ -8,7 +8,7 @@ require 'luci.model.uci'
require 'luci.util'
require 'luci.jsonc'
require 'luci.sys'
local appname = 'passwall'
local appname = 'passwall2'
local api = require ("luci.model.cbi." .. appname .. ".api.api")
local datatypes = require "luci.cbi.datatypes"
@@ -23,13 +23,10 @@ uci:revert(appname)
local has_ss = api.is_finded("ss-redir")
local has_ss_rust = api.is_finded("sslocal")
local has_trojan_plus = api.is_finded("trojan-plus")
local has_v2ray = api.is_finded("v2ray")
local has_xray = api.is_finded("xray")
local has_trojan_go = api.is_finded("trojan-go")
local allowInsecure_default = true
local ss_aead_type_default = uci:get(appname, "@global_subscribe[0]", "ss_aead_type") or "shadowsocks-libev"
local trojan_type_default = uci:get(appname, "@global_subscribe[0]", "trojan_type") or "trojan-plus"
-- 判断是否过滤节点关键字
local filter_keyword_mode_default = uci:get(appname, "@global_subscribe[0]", "filter_keyword_mode") or "0"
local filter_keyword_discard_list_default = uci:get(appname, "@global_subscribe[0]", "filter_discard_list") or {}
@@ -98,15 +95,14 @@ end
-- 获取各项动态配置的当前服务器,可以用 get 和 set get必须要获取到节点表
local CONFIG = {}
do
local function import_config(protocol)
local name = string.upper(protocol)
if true then
local szType = "@global[0]"
local option = protocol .. "_node"
local option = "node"
local node_id = uci:get(appname, szType, option)
CONFIG[#CONFIG + 1] = {
log = true,
remarks = name .. "节点",
remarks = "节点",
currentNode = node_id and uci:get_all(appname, node_id) or nil,
set = function(o, server)
uci:set(appname, szType, option, server)
@@ -114,8 +110,6 @@ do
end
}
end
import_config("tcp")
import_config("udp")
if true then
local i = 0
@@ -138,14 +132,14 @@ do
if true then
local i = 0
local option = "lbss"
uci:foreach(appname, "haproxy_config", function(t)
uci:foreach(appname, "acl_rule", function(t)
i = i + 1
local option = "node"
local node_id = t[option]
CONFIG[#CONFIG + 1] = {
log = true,
id = t[".name"],
remarks = "HAProxy负载均衡节点列表[" .. i .. "]",
remarks = "访问控制列表[" .. i .. "]",
currentNode = node_id and uci:get_all(appname, node_id) or nil,
set = function(o, server)
uci:set(appname, t[".name"], option, server)
@@ -155,33 +149,11 @@ do
end)
end
if true then
local i = 0
local options = {"tcp", "udp"}
uci:foreach(appname, "acl_rule", function(t)
i = i + 1
for index, value in ipairs(options) do
local option = value .. "_node"
local node_id = t[option]
CONFIG[#CONFIG + 1] = {
log = true,
id = t[".name"],
remarks = "访问控制列表[" .. i .. "]",
currentNode = node_id and uci:get_all(appname, node_id) or nil,
set = function(o, server)
uci:set(appname, t[".name"], option, server)
o.newNodeId = server
end
}
end
end)
end
local tcp_node_table = uci:get(appname, "@auto_switch[0]", "tcp_node")
if tcp_node_table then
local node_table = uci:get(appname, "@auto_switch[0]", "node")
if node_table then
local nodes = {}
local new_nodes = {}
for k,node_id in ipairs(tcp_node_table) do
for k,node_id in ipairs(node_table) do
if node_id then
local currentNode = uci:get_all(appname, node_id) or nil
if currentNode then
@@ -190,11 +162,11 @@ do
end
nodes[#nodes + 1] = {
log = true,
remarks = "TCP备用节点的列表[" .. k .. "]",
remarks = "备用节点的列表[" .. k .. "]",
currentNode = currentNode,
set = function(o, server)
for kk, vv in pairs(CONFIG) do
if (vv.remarks == "TCP备用节点的列表") then
if (vv.remarks == "备用节点的列表") then
table.insert(vv.new_nodes, server)
end
end
@@ -204,14 +176,14 @@ do
end
end
CONFIG[#CONFIG + 1] = {
remarks = "TCP备用节点的列表",
remarks = "备用节点的列表",
nodes = nodes,
new_nodes = new_nodes,
set = function(o)
for kk, vv in pairs(CONFIG) do
if (vv.remarks == "TCP备用节点的列表") then
--log("刷新自动切换的TCP备用节点的列表")
uci:set_list(appname, "@auto_switch[0]", "tcp_node", vv.new_nodes)
if (vv.remarks == "备用节点的列表") then
--log("刷新自动切换的备用节点的列表")
uci:set_list(appname, "@auto_switch[0]", "node", vv.new_nodes)
end
end
end
@@ -224,7 +196,9 @@ do
local rules = {}
uci:foreach(appname, "shunt_rules", function(e)
table.insert(rules, e)
if e[".name"] and e.remarks then
table.insert(rules, e)
end
end)
table.insert(rules, {
[".name"] = "default_node",
@@ -530,7 +504,8 @@ local function processData(szType, content, add_mode, add_from)
content = content:sub(0, idx_sp - 1)
end
result.remarks = UrlDecode(alias)
result.type = "Trojan-Plus"
result.type = 'V2ray'
result.protocol = 'trojan'
if content:find("@") then
local Info = split(content, "@")
result.password = UrlDecode(Info[1])
@@ -571,91 +546,11 @@ local function processData(szType, content, add_mode, add_from)
if params.wspath then result.ws_path = params.wspath end
if sni == "" and params.wshost then sni = params.wshost end
end
if params.ss and params.ss == "1" then
result.ss_aead = "1"
if params.ssmethod then result.ss_aead_method = string.lower(params.ssmethod) end
if params.sspasswd then result.ss_aead_pwd = params.sspasswd end
end
result.port = port
if result.trojan_transport == "ws" or result.ss_aead then
result.type = "Trojan-Go"
result.fingerprint = "firefox"
result.mux = "1"
end
result.tls = '1'
result.tls_serverName = peer and peer or sni
result.tls_allowInsecure = allowInsecure and "1" or "0"
end
if trojan_type_default == "trojan-plus" and has_trojan_plus then
result.type = "Trojan-Plus"
elseif trojan_type_default == "v2ray" and has_v2ray then
result.type = 'V2ray'
result.protocol = 'trojan'
elseif trojan_type_default == "xray" and has_xray then
result.type = 'Xray'
result.protocol = 'trojan'
elseif trojan_type_default == "trojan-go" and has_trojan_go then
result.type = 'Trojan-Go'
end
elseif szType == "trojan-go" then
local alias = ""
if content:find("#") then
local idx_sp = content:find("#")
alias = content:sub(idx_sp + 1, -1)
content = content:sub(0, idx_sp - 1)
end
result.remarks = UrlDecode(alias)
if has_trojan_go then
result.type = "Trojan-Go"
end
if content:find("@") then
local Info = split(content, "@")
result.password = UrlDecode(Info[1])
local port = "443"
Info[2] = (Info[2] or ""):gsub("/%?", "?")
local hostInfo = nil
if Info[2]:find(":") then
hostInfo = split(Info[2], ":")
result.address = hostInfo[1]
local idx_port = 2
if hostInfo[2]:find("?") then
hostInfo = split(hostInfo[2], "?")
idx_port = 1
end
if hostInfo[idx_port] ~= "" then port = hostInfo[idx_port] end
else
if Info[2]:find("?") then
hostInfo = split(Info[2], "?")
end
result.address = hostInfo and hostInfo[1] or Info[2]
end
local peer, sni = nil, ""
local query = split(Info[2], "?")
local params = {}
for _, v in pairs(split(query[2], '&')) do
local t = split(v, '=')
params[string.lower(t[1])] = UrlDecode(t[2])
end
if params.peer then peer = params.peer end
sni = params.sni and params.sni or ""
if params.type and params.type == "ws" then
result.trojan_transport = "ws"
if params.host then result.ws_host = params.host end
if params.path then result.ws_path = params.path end
if sni == "" and params.host then sni = params.host end
end
if params.encryption and params.encryption:match('^ss;[^;:]*[;:].*$') then
result.ss_aead = "1"
result.ss_aead_method, result.ss_aead_pwd = params.encryption:match('^ss;([^;:]*)[;:](.*)$')
result.ss_aead_method = string.lower(result.ss_aead_method)
end
result.port = port
result.fingerprint = "firefox"
result.tls = "1"
result.tls_serverName = peer and peer or sni
result.tls_allowInsecure = "0"
result.mux = "1"
end
elseif szType == "ssd" then
result.type = "SS"
result.address = content.server
@@ -1082,7 +977,7 @@ local function parse_link(raw, add_mode, add_from)
local node = trim(v)
local dat = split(node, "://")
if dat and dat[1] and dat[2] then
if dat[1] == 'ss' or dat[1] == 'trojan' or dat[1] == 'trojan-go' then
if dat[1] == 'ss' or dat[1] == 'trojan' then
result = processData(dat[1], dat[2], add_mode, add_from)
else
result = processData(dat[1], base64Decode(dat[2]), add_mode, add_from)
@@ -1161,10 +1056,6 @@ local execute = function()
if ss_aead_type ~= "global" then
ss_aead_type_default = ss_aead_type
end
local trojan_type = value.trojan_type or "global"
if trojan_type ~= "global" then
trojan_type_default = trojan_type
end
local ua = value.user_agent
log('正在订阅:【' .. remark .. '' .. url)
local raw = curl(url, "/tmp/" .. cfgid, ua)
@@ -1183,7 +1074,6 @@ local execute = function()
filter_keyword_discard_list_default = uci:get(appname, "@global_subscribe[0]", "filter_discard_list") or {}
filter_keyword_keep_list_default = uci:get(appname, "@global_subscribe[0]", "filter_keep_list") or {}
ss_aead_type_default = uci:get(appname, "@global_subscribe[0]", "ss_aead_type") or "shadowsocks-libev"
trojan_type_default = uci:get(appname, "@global_subscribe[0]", "trojan_type") or "trojan-plus"
end
if #retry > 0 then

View File

@@ -1,6 +1,6 @@
#!/bin/sh
CONFIG=passwall
CONFIG=passwall2
LOG_FILE=/tmp/log/$CONFIG.log
LOCK_FILE_DIR=/tmp/lock
LOCK_FILE=${LOCK_FILE_DIR}/${CONFIG}_script.lock
@@ -67,20 +67,9 @@ url_test_node() {
local node_id=$1
local _type=$(echo $(config_n_get ${node_id} type nil) | tr 'A-Z' 'a-z')
[ "${_type}" != "nil" ] && {
if [ "${_type}" == "socks" ]; then
local _address=$(config_n_get ${node_id} address)
local _port=$(config_n_get ${node_id} port)
[ -n "${_address}" ] && [ -n "${_port}" ] && {
local curlx="socks5h://${_address}:${_port}"
local _username=$(config_n_get ${node_id} username)
local _password=$(config_n_get ${node_id} password)
[ -n "${_username}" ] && [ -n "${_password}" ] && curlx="socks5h://${_username}:${_password}@${_address}:${_port}"
}
else
local _tmp_port=$(/usr/share/${CONFIG}/app.sh get_new_port 61080 tcp)
/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=/tmp/etc/${CONFIG}/url_test_${node_id}.json
local curlx="socks5h://127.0.0.1:${_tmp_port}"
fi
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}"
sleep 1s
result=$(curl --connect-timeout 3 -o /dev/null -I -skL -w "%{http_code}:%{time_starttransfer}" -x $curlx "https://www.google.com/generate_204")
pgrep -af "url_test_${node_id}" | awk '! /test\.sh/{print $1}' | xargs kill -9 >/dev/null 2>&1
@@ -93,20 +82,10 @@ test_node() {
local node_id=$1
local _type=$(echo $(config_n_get ${node_id} type nil) | tr 'A-Z' 'a-z')
[ "${_type}" != "nil" ] && {
if [ "${_type}" == "socks" ]; then
local _address=$(config_n_get ${node_id} address)
local _port=$(config_n_get ${node_id} port)
[ -n "${_address}" ] && [ -n "${_port}" ] && {
local curlx="socks5h://${_address}:${_port}"
local _username=$(config_n_get ${node_id} username)
local _password=$(config_n_get ${node_id} password)
[ -n "${_username}" ] && [ -n "${_password}" ] && curlx="socks5h://${_username}:${_password}@${_address}:${_port}"
}
else
local _tmp_port=$(/usr/share/${CONFIG}/app.sh get_new_port 61080 tcp)
/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=/tmp/etc/${CONFIG}/test_node_${node_id}.json
local curlx="socks5h://127.0.0.1:${_tmp_port}"
fi
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}"
sleep 1s
_proxy_status=$(test_url "https://www.google.com/generate_204" ${retry_num} ${connect_timeout} "-x $curlx")
pgrep -af "test_node_${node_id}" | awk '! /test\.sh/{print $1}' | xargs kill -9 >/dev/null 2>&1
rm -rf "/tmp/etc/${CONFIG}/test_node_${node_id}.json"
@@ -118,21 +97,22 @@ test_node() {
}
flag=0
main_node=$(config_t_get global tcp_node nil)
main_node=$(config_t_get global node nil)
test_auto_switch() {
flag=$(expr $flag + 1)
local TYPE=$1
local b_tcp_nodes=$2
local b_nodes=$2
local now_node=$3
[ -z "$now_node" ] && {
if [ -f "/tmp/etc/$CONFIG/id/${TYPE}" ]; then
now_node=$(cat /tmp/etc/$CONFIG/id/${TYPE})
local f="/tmp/etc/$CONFIG/id/global"
if [ -f "${f}" ]; then
now_node=$(cat ${f})
if [ "$(config_n_get $now_node protocol nil)" = "_shunt" ]; then
if [ "$shunt_logic" == "1" ] && [ -f "/tmp/etc/$CONFIG/id/${TYPE}_default" ]; then
now_node=$(cat /tmp/etc/$CONFIG/id/${TYPE}_default)
elif [ "$shunt_logic" == "2" ] && [ -f "/tmp/etc/$CONFIG/id/${TYPE}_main" ]; then
now_node=$(cat /tmp/etc/$CONFIG/id/${TYPE}_main)
if [ "$shunt_logic" == "1" ] && [ -f "${f}_default" ]; then
now_node=$(cat ${f}_default)
elif [ "$shunt_logic" == "2" ] && [ -f "${f}_main" ]; then
now_node=$(cat ${f}_main)
else
shunt_logic=0
fi
@@ -161,16 +141,16 @@ test_auto_switch() {
[ $? -eq 0 ] && {
#主节点正常,切换到主节点
echolog "自动切换检测:${TYPE}主节点【$(config_n_get $main_node type)[$(config_n_get $main_node remarks)]】正常,切换到主节点!"
/usr/share/${CONFIG}/app.sh node_switch ${TYPE} ${main_node} ${shunt_logic} 1
/usr/share/${CONFIG}/app.sh node_switch flag=global new_node=${main_node} shunt_logic=${shunt_logic} log_output=1
[ $? -eq 0 ] && {
echolog "自动切换检测:${TYPE}节点切换完毕!"
[ "$shunt_logic" != "0" ] && {
local tcp_node=$(config_t_get global tcp_node nil)
[ "$(config_n_get $tcp_node protocol nil)" = "_shunt" ] && {
local node=$(config_t_get global node nil)
[ "$(config_n_get $node protocol nil)" = "_shunt" ] && {
if [ "$shunt_logic" == "1" ]; then
uci set $CONFIG.$tcp_node.default_node="$main_node"
uci set $CONFIG.$node.default_node="$main_node"
elif [ "$shunt_logic" == "2" ]; then
uci set $CONFIG.$tcp_node.main_node="$main_node"
uci set $CONFIG.$node.main_node="$main_node"
fi
uci commit $CONFIG
}
@@ -186,17 +166,17 @@ test_auto_switch() {
elif [ "$status" == 1 ]; then
echolog "自动切换检测:${TYPE}节点【$(config_n_get $now_node type)[$(config_n_get $now_node remarks)]】异常,切换到下一个备用节点检测!"
local new_node
in_backup_nodes=$(echo $b_tcp_nodes | grep $now_node)
in_backup_nodes=$(echo $b_nodes | grep $now_node)
# 判断当前节点是否存在于备用节点列表里
if [ -z "$in_backup_nodes" ]; then
# 如果不存在,设置第一个节点为新的节点
new_node=$(echo $b_tcp_nodes | awk -F ' ' '{print $1}')
new_node=$(echo $b_nodes | awk -F ' ' '{print $1}')
else
# 如果存在,设置下一个备用节点为新的节点
#local count=$(expr $(echo $b_tcp_nodes | grep -o ' ' | wc -l) + 1)
local next_node=$(echo $b_tcp_nodes | awk -F "$now_node" '{print $2}' | awk -F " " '{print $1}')
#local count=$(expr $(echo $b_nodes | grep -o ' ' | wc -l) + 1)
local next_node=$(echo $b_nodes | awk -F "$now_node" '{print $2}' | awk -F " " '{print $1}')
if [ -z "$next_node" ]; then
new_node=$(echo $b_tcp_nodes | awk -F ' ' '{print $1}')
new_node=$(echo $b_nodes | awk -F ' ' '{print $1}')
else
new_node=$next_node
fi
@@ -204,20 +184,20 @@ test_auto_switch() {
test_node ${new_node}
if [ $? -eq 0 ]; then
[ "$restore_switch" == "0" ] && {
[ "$shunt_logic" == "0" ] && uci set $CONFIG.@global[0].tcp_node=$new_node
[ -z "$(echo $b_tcp_nodes | grep $main_node)" ] && uci add_list $CONFIG.@auto_switch[0].tcp_node=$main_node
[ "$shunt_logic" == "0" ] && uci set $CONFIG.@global[0].node=$new_node
[ -z "$(echo $b_nodes | grep $main_node)" ] && uci add_list $CONFIG.@auto_switch[0].node=$main_node
uci commit $CONFIG
}
echolog "自动切换检测:${TYPE}节点【$(config_n_get $new_node type)[$(config_n_get $new_node remarks)]】正常,切换到此节点!"
/usr/share/${CONFIG}/app.sh node_switch ${TYPE} ${new_node} ${shunt_logic} 1
/usr/share/${CONFIG}/app.sh node_switch flag=global new_node=${new_node} shunt_logic=${shunt_logic} log_output=1
[ $? -eq 0 ] && {
[ "$restore_switch" == "1" ] && [ "$shunt_logic" != "0" ] && {
local tcp_node=$(config_t_get global tcp_node nil)
[ "$(config_n_get $tcp_node protocol nil)" = "_shunt" ] && {
local node=$(config_t_get global node nil)
[ "$(config_n_get $node protocol nil)" = "_shunt" ] && {
if [ "$shunt_logic" == "1" ]; then
uci set $CONFIG.$tcp_node.default_node="$main_node"
uci set $CONFIG.$node.default_node="$main_node"
elif [ "$shunt_logic" == "2" ]; then
uci set $CONFIG.$tcp_node.main_node="$main_node"
uci set $CONFIG.$node.main_node="$main_node"
fi
uci commit $CONFIG
}
@@ -226,7 +206,7 @@ test_auto_switch() {
}
return 0
else
test_auto_switch ${TYPE} "${b_tcp_nodes}" ${new_node}
test_auto_switch ${TYPE} "${b_nodes}" ${new_node}
fi
fi
}
@@ -248,10 +228,10 @@ start() {
continue
}
touch $LOCK_FILE
TCP_NODE=$(config_t_get auto_switch tcp_node nil)
[ -n "$TCP_NODE" -a "$TCP_NODE" != "nil" ] && {
TCP_NODE=$(echo $TCP_NODE | tr -s ' ' '\n' | uniq | tr -s '\n' ' ')
test_auto_switch TCP "$TCP_NODE"
NODE=$(config_t_get auto_switch node nil)
[ -n "$NODE" -a "$NODE" != "nil" ] && {
NODE=$(echo $NODE | tr -s ' ' '\n' | uniq | tr -s '\n' ' ')
test_auto_switch TCP "$NODE"
}
rm -f $LOCK_FILE
sleep ${delay}m

View File

@@ -0,0 +1,11 @@
{
"luci-app-passwall2": {
"description": "Grant UCI access for luci-app-passwall2",
"read": {
"uci": [ "passwall2", "passwall2_server" ]
},
"write": {
"uci": [ "passwall2", "passwall2_server" ]
}
}
}