luci: refactoring haproxy function

This commit is contained in:
xiaorouji 2023-03-27 18:26:14 +08:00 committed by sbwml
parent bdba72f178
commit 2b0f1aa628
3 changed files with 159 additions and 102 deletions

View File

@ -7,7 +7,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-passwall
PKG_VERSION:=4.61
PKG_RELEASE:=1
PKG_RELEASE:=2
PKG_CONFIG_DEPENDS:= \
CONFIG_PACKAGE_$(PKG_NAME)_Iptables_Transparent_Proxy \

View File

@ -1213,108 +1213,10 @@ delete_ip2route() {
}
start_haproxy() {
local haproxy_path haproxy_file item items lport sort_items
[ "$(config_t_get global_haproxy balancing_enable 0)" != "1" ] && return
echolog "HAPROXY 负载均衡..."
haproxy_path=${TMP_PATH}/haproxy
mkdir -p "${haproxy_path}"
haproxy_file=${haproxy_path}/config.cfg
cat <<-EOF > "${haproxy_file}"
global
log 127.0.0.1 local2
chroot ${haproxy_path}
maxconn 60000
stats socket ${haproxy_path}/haproxy.sock
daemon
defaults
mode tcp
log global
option tcplog
option dontlognull
option http-server-close
#option forwardfor except 127.0.0.0/8
option redispatch
retries 2
timeout http-request 10s
timeout queue 1m
timeout connect 10s
timeout client 1m
timeout server 1m
timeout http-keep-alive 10s
timeout check 10s
maxconn 3000
EOF
items=$(uci show ${CONFIG} | grep "=haproxy_config" | cut -d '.' -sf 2 | cut -d '=' -sf 1)
for item in $items; do
lport=$(config_n_get ${item} haproxy_port 0)
[ "${lport}" = "0" ] && echolog " - 丢弃1个明显无效的节点" && continue
sort_items="${sort_items}${IFS}${lport} ${item}"
done
items=$(echo "${sort_items}" | sort -n | cut -d ' ' -sf 2)
unset lport
local haproxy_port lbss lbweight export backup remark
local msg bip bport hasvalid bbackup failcount interface
for item in ${items}; do
unset haproxy_port bbackup
eval $(uci -q show "${CONFIG}.${item}" | cut -d '.' -sf 3-)
[ "$enabled" = "1" ] || continue
get_ip_port_from "$lbss" bip bport 1
[ -z "$haproxy_port" ] || [ -z "$bip" ] && echolog " - 丢弃1个明显无效的节点" && continue
[ "$backup" = "1" ] && bbackup="backup"
remark=$(echo $bip | sed "s/\[//g" | sed "s/\]//g")
[ "$lport" = "${haproxy_port}" ] || {
hasvalid="1"
lport=${haproxy_port}
echolog " + 入口 0.0.0.0:${lport}..."
cat <<-EOF >> "${haproxy_file}"
listen $lport
mode tcp
bind 0.0.0.0:$lport
EOF
}
cat <<-EOF >> "${haproxy_file}"
server $remark:$bport $bip:$bport weight $lbweight check inter 1500 rise 1 fall 3 $bbackup
EOF
if [ "$export" != "0" ]; then
add_ip2route ${bip} ${export} > /dev/null 2>&1 &
fi
haproxy_items="${haproxy_items}${IFS}${bip}:${bport}"
echolog " | - 出口节点:${bip}:${bport},权重:${lbweight}"
done
# 控制台配置
local console_port=$(config_t_get global_haproxy console_port)
local console_user=$(config_t_get global_haproxy console_user)
local console_password=$(config_t_get global_haproxy console_password)
local auth=""
[ -n "$console_user" ] && [ -n "$console_password" ] && auth="stats auth $console_user:$console_password"
cat <<-EOF >> "${haproxy_file}"
listen console
bind 0.0.0.0:$console_port
mode http
stats refresh 30s
stats uri /
stats admin if TRUE
$auth
EOF
[ "${hasvalid}" != "1" ] && echolog " - 没有发现任何有效节点信息,不启动。" && return 0
ln_run "$(first_type haproxy)" haproxy "/dev/null" -f "${haproxy_file}"
echolog " * 控制台端口:${console_port}/${auth:-公开}"
haproxy_conf="config.cfg"
lua $APP_PATH/haproxy.lua -path ${haproxy_path} -conf ${haproxy_conf}
ln_run "$(first_type haproxy)" haproxy "/dev/null" -f "${haproxy_path}/${haproxy_conf}"
}
kill_all() {
@ -1701,6 +1603,9 @@ mkdir -p /tmp/etc $TMP_PATH $TMP_BIN_PATH $TMP_SCRIPT_FUNC_PATH $TMP_ID_PATH $TM
arg1=$1
shift
case $arg1 in
add_ip2route)
add_ip2route $@
;;
get_new_port)
get_new_port $@
;;

View File

@ -0,0 +1,152 @@
#!/usr/bin/lua
local api = require ("luci.passwall.api")
local appname = api.appname
local fs = api.fs
local jsonc = api.jsonc
local uci = api.uci
local sys = api.sys
if uci:get_first(appname, 'global_haproxy', "balancing_enable", 0) ~= 1 then
return
end
local log = function(...)
local result = os.date("%Y-%m-%d %H:%M:%S: ") .. table.concat({...}, " ")
local f, err = io.open("/tmp/log/passwall.log", "a")
if f and err == nil then
f:write(result .. "\n")
f:close()
end
end
function get_ip_port_from(str)
local result_port = sys.exec("echo -n " .. str .. " | sed -n 's/^.*[:#]\\([0-9]*\\)$/\\1/p'")
local result_ip = sys.exec(string.format("__host=%s;__varport=%s;", str, result_port) .. "echo -n ${__host%%${__varport:+[:#]${__varport}*}}")
return result_ip, result_port
end
local var = api.get_args(arg)
local haproxy_path = var["-path"]
local haproxy_conf = var["-conf"]
log("HAPROXY 负载均衡...")
fs.mkdir(haproxy_path)
local haproxy_file = haproxy_path .. "/" .. haproxy_conf
local f_out = io.open(haproxy_file, "a")
local haproxy_config = [[
global
log 127.0.0.1 local2
chroot %s
maxconn 60000
stats socket %s/haproxy.sock
daemon
defaults
mode tcp
log global
option tcplog
option dontlognull
option http-server-close
#option forwardfor except 127.0.0.0/8
option redispatch
retries 2
timeout http-request 10s
timeout queue 1m
timeout connect 10s
timeout client 1m
timeout server 1m
timeout http-keep-alive 10s
timeout check 10s
maxconn 3000
resolvers mydns
nameserver dns1 127.0.0.1:53
resolve_retries 3
timeout retry 3s
hold valid 10s
]]
f_out:write(string.format(haproxy_config, haproxy_path, haproxy_path))
local listens = {}
uci:foreach(appname, "haproxy_config", function(t)
if t.enabled == "1" then
local server_address
local server_port
local lbss = t.lbss
local listen_port = tonumber(t.haproxy_port) or 0
local server_node = uci:get_all(appname, lbss)
if server_node and server_node.address and server_node.port then
server_address = server_node.address
server_port = server_node.port
else
server_address, server_port = get_ip_port_from(lbss)
end
if server_address and server_port and listen_port > 0 then
if not listens[listen_port] then
listens[listen_port] = {}
end
t.server_address = server_address
t.server_port = server_port
table.insert(listens[listen_port], t)
else
log(" - 丢弃1个明显无效的节点")
end
end
end)
local sortTable = {}
for i in pairs(listens) do
if i ~= nil then
table.insert(sortTable, i)
end
end
table.sort(sortTable, function(a,b) return (a < b) end)
for i, port in pairs(sortTable) do
log(" + 入口 0.0.0.0:%s..." % port)
f_out:write(string.format([[
listen %s
bind 0.0.0.0:%s
mode tcp
balance roundrobin
]], port, port))
for i, o in ipairs(listens[port]) do
local server = o.server_address .. ":" .. o.server_port
local remark = server:gsub("%[", ""):gsub("%]", "")
f_out:write(string.format([[
server %s %s weight %s check resolvers mydns inter 1500 rise 1 fall 3 %s
]], remark, server, o.lbweight, o.backup == "1" and "backup" or ""))
if o.export ~= "0" then
sys.call(string.format("/usr/share/passwall/app.sh add_ip2route %s %s", o.server_address, o.export))
end
log(string.format(" | - 出口节点:%s:%s权重%s", o.server_address, o.server_port, o.lbweight))
end
end
--控制台配置
local console_port = uci:get(appname, "@global_haproxy[0]", "console_port")
local console_user = uci:get(appname, "@global_haproxy[0]", "console_user")
local console_password = uci:get(appname, "@global_haproxy[0]", "console_password")
local str = [[
listen console
bind 0.0.0.0:%s
mode http
stats refresh 30s
stats uri /
stats admin if TRUE
%s
]]
f_out:write(string.format(str, console_port, (console_user and console_user ~= "" and console_password and console_password ~= "") and "stats auth " .. console_user .. ":" .. console_password or ""))
log(string.format(" * 控制台端口:%s", console_port))
f_out:close()