2022-03-05 13:13:49 +08:00
|
|
|
#!/usr/bin/lua
|
|
|
|
|
|
|
|
local action = arg[1]
|
2023-02-16 23:37:45 +08:00
|
|
|
local api = require "luci.passwall2.api"
|
2022-03-05 13:13:49 +08:00
|
|
|
local sys = api.sys
|
|
|
|
local uci = api.uci
|
|
|
|
local jsonc = api.jsonc
|
|
|
|
|
2022-03-11 18:29:27 +08:00
|
|
|
local CONFIG = "passwall2_server"
|
2022-03-05 13:13:49 +08:00
|
|
|
local CONFIG_PATH = "/tmp/etc/" .. CONFIG
|
2023-06-14 23:15:20 +08:00
|
|
|
local NFT_INCLUDE_FILE = CONFIG_PATH .. "/" .. CONFIG .. ".nft"
|
2022-03-05 13:13:49 +08:00
|
|
|
local LOG_APP_FILE = "/tmp/log/" .. CONFIG .. ".log"
|
|
|
|
local TMP_BIN_PATH = CONFIG_PATH .. "/bin"
|
2023-02-16 23:37:45 +08:00
|
|
|
local require_dir = "luci.passwall2."
|
2022-03-05 13:13:49 +08:00
|
|
|
|
2022-03-11 18:29:27 +08:00
|
|
|
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)")
|
2022-03-05 13:13:49 +08:00
|
|
|
|
2023-05-25 23:35:42 +08:00
|
|
|
local nft_flag = api.is_finded("fw4") and "1" or "0"
|
|
|
|
|
2022-03-05 13:13:49 +08:00
|
|
|
local function log(...)
|
|
|
|
local f, err = io.open(LOG_APP_FILE, "a")
|
2023-04-09 23:35:07 +08:00
|
|
|
if f and err == nil then
|
|
|
|
local str = os.date("%Y-%m-%d %H:%M:%S: ") .. table.concat({...}, " ")
|
|
|
|
f:write(str .. "\n")
|
|
|
|
f:close()
|
|
|
|
end
|
2022-03-05 13:13:49 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
local function cmd(cmd)
|
2023-04-09 23:35:07 +08:00
|
|
|
sys.call(cmd)
|
2022-03-05 13:13:49 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
local function ipt(arg)
|
2023-05-16 23:35:34 +08:00
|
|
|
if ipt_bin and #ipt_bin > 0 then
|
|
|
|
cmd(ipt_bin .. " -w " .. arg)
|
|
|
|
end
|
2022-03-05 13:13:49 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
local function ip6t(arg)
|
2023-05-16 23:35:34 +08:00
|
|
|
if ip6t_bin and #ip6t_bin > 0 then
|
|
|
|
cmd(ip6t_bin .. " -w " .. arg)
|
|
|
|
end
|
2022-03-05 13:13:49 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
local function ln_run(s, d, command, output)
|
2023-04-09 23:35:07 +08:00
|
|
|
if not output then
|
|
|
|
output = "/dev/null"
|
|
|
|
end
|
|
|
|
d = TMP_BIN_PATH .. "/" .. d
|
|
|
|
cmd(string.format('[ ! -f "%s" ] && ln -s %s %s 2>/dev/null', d, s, d))
|
|
|
|
return string.format("%s >%s 2>&1 &", d .. " " ..command, output)
|
2022-03-05 13:13:49 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
local function gen_include()
|
2023-04-09 23:35:07 +08:00
|
|
|
cmd(string.format("echo '#!/bin/sh' > /tmp/etc/%s.include", CONFIG))
|
|
|
|
local function extract_rules(n, a)
|
|
|
|
local _ipt = ipt_bin
|
|
|
|
if n == "6" then
|
|
|
|
_ipt = ip6t_bin
|
|
|
|
end
|
|
|
|
local result = "*" .. a
|
|
|
|
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
|
2023-05-25 23:35:42 +08:00
|
|
|
if nft_flag == "0" then
|
|
|
|
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 "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")
|
|
|
|
f:close()
|
|
|
|
else
|
2023-06-14 23:15:20 +08:00
|
|
|
f:write("nft -f " .. NFT_INCLUDE_FILE .. "\n")
|
2023-05-25 23:35:42 +08:00
|
|
|
f:close()
|
|
|
|
end
|
2023-04-09 23:35:07 +08:00
|
|
|
end
|
2022-03-05 13:13:49 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
local function start()
|
2023-04-09 23:35:07 +08:00
|
|
|
local enabled = tonumber(uci:get(CONFIG, "@global[0]", "enable") or 0)
|
|
|
|
if enabled == nil or enabled == 0 then
|
|
|
|
return
|
|
|
|
end
|
|
|
|
cmd(string.format("mkdir -p %s %s", CONFIG_PATH, TMP_BIN_PATH))
|
|
|
|
cmd(string.format("touch %s", LOG_APP_FILE))
|
2023-05-25 23:35:42 +08:00
|
|
|
if nft_flag == "0" then
|
|
|
|
ipt("-N PSW2-SERVER")
|
|
|
|
ipt("-I INPUT -j PSW2-SERVER")
|
|
|
|
ip6t("-N PSW2-SERVER")
|
|
|
|
ip6t("-I INPUT -j PSW2-SERVER")
|
|
|
|
else
|
2023-06-14 23:15:20 +08:00
|
|
|
nft_file, err = io.open(NFT_INCLUDE_FILE, "w")
|
|
|
|
nft_file:write('#!/usr/sbin/nft -f\n')
|
|
|
|
nft_file:write('add chain inet fw4 PSW2-SERVER\n')
|
|
|
|
nft_file:write('flush chain inet fw4 PSW2-SERVER\n')
|
|
|
|
nft_file:write('insert rule inet fw4 input position 0 jump PSW2-SERVER comment "PSW2-SERVER"\n')
|
2023-05-25 23:35:42 +08:00
|
|
|
end
|
2023-04-09 23:35:07 +08:00
|
|
|
uci:foreach(CONFIG, "user", function(user)
|
|
|
|
local id = user[".name"]
|
|
|
|
local enable = user.enable
|
|
|
|
if enable and tonumber(enable) == 1 then
|
|
|
|
local enable_log = user.log
|
|
|
|
local log_path = nil
|
|
|
|
if enable_log and enable_log == "1" then
|
|
|
|
log_path = CONFIG_PATH .. "/" .. id .. ".log"
|
|
|
|
else
|
|
|
|
log_path = nil
|
|
|
|
end
|
|
|
|
local remarks = user.remarks
|
|
|
|
local port = tonumber(user.port)
|
|
|
|
local bin
|
|
|
|
local config = {}
|
|
|
|
local config_file = CONFIG_PATH .. "/" .. id .. ".json"
|
|
|
|
local udp_forward = 1
|
|
|
|
local type = user.type or ""
|
|
|
|
if type == "Socks" then
|
|
|
|
local auth = ""
|
|
|
|
if user.auth and user.auth == "1" then
|
|
|
|
local username = user.username or ""
|
|
|
|
local password = user.password or ""
|
|
|
|
if username ~= "" and password ~= "" then
|
|
|
|
username = "-u " .. username
|
|
|
|
password = "-P " .. password
|
|
|
|
auth = username .. " " .. password
|
|
|
|
end
|
|
|
|
end
|
|
|
|
bin = ln_run("/usr/bin/microsocks", "microsocks_" .. id, string.format("-i :: -p %s %s", port, auth), log_path)
|
|
|
|
elseif type == "SS" or type == "SSR" then
|
|
|
|
config = require(require_dir .. "util_shadowsocks").gen_config_server(user)
|
|
|
|
local udp_param = ""
|
|
|
|
udp_forward = tonumber(user.udp_forward) or 1
|
|
|
|
if udp_forward == 1 then
|
|
|
|
udp_param = "-u"
|
|
|
|
end
|
|
|
|
type = type:lower()
|
|
|
|
bin = ln_run("/usr/bin/" .. type .. "-server", type .. "-server", "-c " .. config_file .. " " .. udp_param, log_path)
|
|
|
|
elseif type == "SS-Rust" then
|
|
|
|
config = require(require_dir .. "util_shadowsocks").gen_config_server(user)
|
|
|
|
bin = ln_run("/usr/bin/ssserver", "ssserver", "-c " .. config_file, log_path)
|
|
|
|
elseif type == "V2ray" then
|
|
|
|
config = require(require_dir .. "util_xray").gen_config_server(user)
|
2023-05-20 23:34:57 +08:00
|
|
|
bin = ln_run(api.get_app_path("v2ray"), "v2ray", "run -c " .. config_file, log_path)
|
2023-04-09 23:35:07 +08:00
|
|
|
elseif type == "Xray" then
|
|
|
|
config = require(require_dir .. "util_xray").gen_config_server(user)
|
2023-05-20 23:34:57 +08:00
|
|
|
bin = ln_run(api.get_app_path("xray"), "xray", "run -c " .. config_file, log_path)
|
2023-04-09 23:35:07 +08:00
|
|
|
elseif type == "Brook" then
|
|
|
|
local brook_protocol = user.protocol
|
|
|
|
local brook_password = user.password
|
|
|
|
local brook_path = user.ws_path or "/ws"
|
|
|
|
local brook_path_arg = ""
|
|
|
|
if brook_protocol == "wsserver" and brook_path then
|
|
|
|
brook_path_arg = " --path " .. brook_path
|
|
|
|
end
|
2023-05-20 23:34:57 +08:00
|
|
|
bin = ln_run(api.get_app_path("brook"), "brook_" .. id, string.format("--debug %s -l :%s -p %s%s", brook_protocol, port, brook_password, brook_path_arg), log_path)
|
2023-04-09 23:35:07 +08:00
|
|
|
elseif type == "Hysteria" then
|
|
|
|
config = require(require_dir .. "util_hysteria").gen_config_server(user)
|
2023-05-20 23:34:57 +08:00
|
|
|
bin = ln_run(api.get_app_path("hysteria"), "hysteria", "-c " .. config_file .. " server", log_path)
|
2023-04-09 23:35:07 +08:00
|
|
|
end
|
2022-03-05 13:13:49 +08:00
|
|
|
|
2023-04-09 23:35:07 +08:00
|
|
|
if next(config) then
|
|
|
|
local f, err = io.open(config_file, "w")
|
|
|
|
if f and err == nil then
|
|
|
|
f:write(jsonc.stringify(config, 1))
|
|
|
|
f:close()
|
|
|
|
end
|
|
|
|
log(string.format("%s %s 生成配置文件并运行 - %s", remarks, port, config_file))
|
|
|
|
end
|
2022-03-05 13:13:49 +08:00
|
|
|
|
2023-04-09 23:35:07 +08:00
|
|
|
if bin then
|
|
|
|
cmd(bin)
|
|
|
|
end
|
2022-03-05 13:13:49 +08:00
|
|
|
|
2023-04-09 23:35:07 +08:00
|
|
|
local bind_local = user.bind_local or 0
|
|
|
|
if bind_local and tonumber(bind_local) ~= 1 then
|
2023-05-25 23:35:42 +08:00
|
|
|
if nft_flag == "0" then
|
|
|
|
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 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
|
|
|
|
else
|
2023-06-14 23:15:20 +08:00
|
|
|
nft_file:write(string.format('add rule inet fw4 PSW2-SERVER meta l4proto tcp tcp dport {%s} counter accept comment "%s"\n', port, remarks))
|
2023-05-25 23:35:42 +08:00
|
|
|
if udp_forward == 1 then
|
2023-06-14 23:15:20 +08:00
|
|
|
nft_file:write(string.format('add rule inet fw4 PSW2-SERVER meta l4proto udp udp dport {%s} counter accept comment "%s"\n', port, remarks))
|
2023-05-25 23:35:42 +08:00
|
|
|
end
|
|
|
|
end
|
2023-04-09 23:35:07 +08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
end)
|
2023-06-14 23:15:20 +08:00
|
|
|
if nft_flag == "1" then
|
|
|
|
nft_file:write("add rule inet fw4 PSW2-SERVER return\n")
|
|
|
|
nft_file:close()
|
|
|
|
cmd("nft -f " .. NFT_INCLUDE_FILE)
|
|
|
|
end
|
2023-04-09 23:35:07 +08:00
|
|
|
gen_include()
|
2022-03-05 13:13:49 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
local function stop()
|
2023-04-09 23:35:07 +08:00
|
|
|
cmd(string.format("top -bn1 | grep -v 'grep' | grep '%s/' | awk '{print $1}' | xargs kill -9 >/dev/null 2>&1", CONFIG_PATH))
|
2023-05-25 23:35:42 +08:00
|
|
|
if nft_flag == "0" then
|
|
|
|
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")
|
|
|
|
else
|
|
|
|
local nft_cmd = "handles=$(nft -a list chain inet fw4 input | grep -E \"PSW2-SERVER\" | awk -F '# handle ' '{print$2}')\n for handle in $handles; do\n nft delete rule inet fw4 input handle ${handle} 2>/dev/null\n done"
|
|
|
|
cmd(nft_cmd)
|
|
|
|
cmd("nft flush chain inet fw4 PSW2-SERVER 2>/dev/null")
|
|
|
|
cmd("nft delete chain inet fw4 PSW2-SERVER 2>/dev/null")
|
|
|
|
end
|
2023-04-09 23:35:07 +08:00
|
|
|
cmd(string.format("rm -rf %s %s /tmp/etc/%s.include", CONFIG_PATH, LOG_APP_FILE, CONFIG))
|
2022-03-05 13:13:49 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
if action then
|
2023-04-09 23:35:07 +08:00
|
|
|
if action == "start" then
|
|
|
|
start()
|
2022-03-05 13:13:49 +08:00
|
|
|
elseif action == "stop" then
|
2023-04-09 23:35:07 +08:00
|
|
|
stop()
|
2022-03-05 13:13:49 +08:00
|
|
|
end
|
2022-04-14 20:39:04 +08:00
|
|
|
end
|