mirror of
https://github.com/kenzok8/small-package.git
synced 2026-02-07 07:18:00 +08:00
update-03.11
This commit is contained in:
@@ -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))
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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>
|
||||
@@ -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
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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
|
||||
}
|
||||
@@ -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
@@ -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
|
||||
@@ -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
@@ -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
|
||||
@@ -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
@@ -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
|
||||
@@ -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
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
@@ -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)
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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,
|
||||
@@ -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,
|
||||
@@ -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,
|
||||
@@ -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
|
||||
@@ -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"
|
||||
},
|
||||
-- 传入连接
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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"))
|
||||
@@ -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
|
||||
@@ -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)
|
||||
@@ -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" })
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
@@ -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
|
||||
@@ -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"
|
||||
@@ -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
|
||||
@@ -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"
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
@@ -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"}
|
||||
@@ -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"
|
||||
},
|
||||
-- 传入连接
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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()
|
||||
-%>
|
||||
|
||||
@@ -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()
|
||||
-%>
|
||||
|
||||
@@ -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()
|
||||
-%>
|
||||
|
||||
@@ -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()
|
||||
-%>
|
||||
|
||||
@@ -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">
|
||||
@@ -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 />";
|
||||
@@ -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 += "  " + 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
@@ -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[
|
||||
@@ -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);
|
||||
@@ -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("/?");
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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[
|
||||
@@ -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");
|
||||
@@ -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 Subnet(RFC7871)。"
|
||||
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 "日志等级"
|
||||
@@ -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
|
||||
16
openwrt-passwall2/luci-app-passwall2/root/etc/init.d/passwall2_server
Executable file
16
openwrt-passwall2/luci-app-passwall2/root/etc/init.d/passwall2_server
Executable 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
|
||||
}
|
||||
35
openwrt-passwall2/luci-app-passwall2/root/etc/uci-defaults/luci-passwall2
Executable file
35
openwrt-passwall2/luci-app-passwall2/root/etc/uci-defaults/luci-passwall2
Executable 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
|
||||
@@ -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'
|
||||
|
||||
761
openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/app.sh
Executable file
761
openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/app.sh
Executable 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
|
||||
138
openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/helper_dnsmasq.sh
Executable file
138
openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/helper_dnsmasq.sh
Executable 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
|
||||
946
openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/iptables.sh
Executable file
946
openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/iptables.sh
Executable 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="备注【$remarks】,IP 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="备注【$remarks】,IPset【${_ipset}】,"
|
||||
elif [ -n "$(echo ${i} | grep '^ip:')" ]; then
|
||||
_ip=$(echo ${i} | sed 's#ip:##g')
|
||||
_ipt_source=$(factor ${_ip} "-s")
|
||||
msg="备注【$remarks】,IP【${_ip}】,"
|
||||
elif [ -n "$(echo ${i} | grep '^mac:')" ]; then
|
||||
_mac=$(echo ${i} | sed 's#mac:##g')
|
||||
_ipt_source=$(factor ${_mac} "-m mac --mac-source")
|
||||
msg="备注【$remarks】,MAC【${_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
|
||||
47
openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/monitor.sh
Executable file
47
openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/monitor.sh
Executable 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
|
||||
196
openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/rule_update.lua
Executable file
196
openwrt-passwall2/luci-app-passwall2/root/usr/share/passwall2/rule_update.lua
Executable 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("规则更新完毕...")
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user