mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-10-29 09:15:14 +08:00
🎈 Sync 2026-09-09 01:06:03
This commit is contained in:
1 parent
6701c0a72f
commit
6dadf1e827
35 files changed
+5887
No files matched your search
@@ -0,0 +1,361 @@
|
||||
#!/bin/sh
|
||||
|
||||
CONFIG=haproxy_manager
|
||||
HAPROXY_CFG=/etc/haproxy.cfg
|
||||
TMP_CFG=/tmp/haproxy-manager-generated.cfg
|
||||
BACKUP_LIMIT=7
|
||||
INCIDENT_LIMIT=7
|
||||
FIREWALL_RULE_NAME='HAProxy Manager: WAN listeners'
|
||||
FIREWALL_DISABLED_PREFIX='HAProxy Manager disabled: '
|
||||
|
||||
uci_get() {
|
||||
local section="$1"
|
||||
local option="$2"
|
||||
local default="${3:-}"
|
||||
uci -q get "$CONFIG.$section.$option" 2>/dev/null || printf '%s\n' "$default"
|
||||
}
|
||||
|
||||
backup_dir() {
|
||||
local dir
|
||||
dir="$(uci_get main backup_dir /root/haproxy-manager-backups)"
|
||||
is_safe_storage_dir "$dir" || {
|
||||
echo "Recovery point directory must be a plain path under /root or /mnt: $dir" >&2
|
||||
return 1
|
||||
}
|
||||
printf '%s\n' "$dir"
|
||||
}
|
||||
|
||||
incident_dir() {
|
||||
local dir
|
||||
dir="$(uci_get main incident_dir /root/haproxy-manager-incidents)"
|
||||
is_safe_storage_dir "$dir" || {
|
||||
echo "Incident directory must be a plain path under /root or /mnt: $dir" >&2
|
||||
return 1
|
||||
}
|
||||
printf '%s\n' "$dir"
|
||||
}
|
||||
|
||||
is_safe_storage_dir() {
|
||||
case "$1" in
|
||||
/root/*|/mnt/*) ;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
case "/${1#/}/" in
|
||||
*/../*|*/./*|*[!A-Za-z0-9_./-]*) return 1 ;;
|
||||
esac
|
||||
return 0
|
||||
}
|
||||
|
||||
resolve_storage_dir() {
|
||||
local dir="$1" resolved
|
||||
[ -d "$dir" ] || return 1
|
||||
resolved="$(cd "$dir" 2>/dev/null && pwd -P)" || return 1
|
||||
is_safe_storage_dir "$resolved" || return 1
|
||||
printf '%s\n' "$resolved"
|
||||
}
|
||||
|
||||
is_safe_temp_path() {
|
||||
local path="$1" name
|
||||
name="${path#/tmp/}"
|
||||
[ "$path" = "/tmp/$name" ] || return 1
|
||||
case "$name" in
|
||||
haproxy-manager-[A-Za-z0-9._-]*) return 0 ;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
operation_lock_acquire() {
|
||||
local lock_dir="$1" lock_pid
|
||||
if mkdir "$lock_dir" 2>/dev/null; then
|
||||
printf '%s\n' "$$" > "$lock_dir/pid"
|
||||
return 0
|
||||
fi
|
||||
|
||||
lock_pid="$(cat "$lock_dir/pid" 2>/dev/null || true)"
|
||||
case "$lock_pid" in
|
||||
''|*[!0-9]*) lock_pid=0 ;;
|
||||
esac
|
||||
if [ "$lock_pid" -gt 1 ] 2>/dev/null && kill -0 "$lock_pid" 2>/dev/null; then
|
||||
return 1
|
||||
fi
|
||||
rm -f "$lock_dir/pid"
|
||||
rmdir "$lock_dir" 2>/dev/null || return 1
|
||||
mkdir "$lock_dir" 2>/dev/null || return 1
|
||||
printf '%s\n' "$$" > "$lock_dir/pid"
|
||||
}
|
||||
|
||||
operation_lock_set_pid() {
|
||||
printf '%s\n' "$2" > "$1/pid"
|
||||
}
|
||||
|
||||
operation_lock_release() {
|
||||
rm -f "$1/pid"
|
||||
rmdir "$1" 2>/dev/null || true
|
||||
}
|
||||
|
||||
atomic_install_file() {
|
||||
local source="$1" destination="$2" temporary mode
|
||||
[ -f "$source" ] || return 1
|
||||
temporary="$destination.haproxy-manager.$$"
|
||||
rm -f "$temporary"
|
||||
if ! cp "$source" "$temporary"; then
|
||||
rm -f "$temporary"
|
||||
return 1
|
||||
fi
|
||||
mode="$(stat -c '%a' "$destination" 2>/dev/null || stat -c '%a' "$source" 2>/dev/null || echo 600)"
|
||||
chmod "$mode" "$temporary" || { rm -f "$temporary"; return 1; }
|
||||
mv -f "$temporary" "$destination" || { rm -f "$temporary"; return 1; }
|
||||
}
|
||||
|
||||
active_mode() {
|
||||
local mode
|
||||
mode="$(uci_get main active_mode)"
|
||||
case "$mode" in
|
||||
generated|raw|none) printf '%s\n' "$mode" ;;
|
||||
*)
|
||||
if [ "$(uci_get main enabled 0)" = 1 ] &&
|
||||
grep -q '^# Generated by luci-app-haproxy-manager\.' "$HAPROXY_CFG" 2>/dev/null; then
|
||||
printf 'generated\n'
|
||||
else
|
||||
printf 'none\n'
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
wan_interface() {
|
||||
local interface
|
||||
interface="$(uci_get main wan_interface wan)"
|
||||
case "$interface" in
|
||||
''|*[!A-Za-z0-9_.-]*) return 1 ;;
|
||||
esac
|
||||
printf '%s\n' "$interface"
|
||||
}
|
||||
|
||||
wan_ip() {
|
||||
local configured interface
|
||||
configured="$(uci_get main wan_bind_ip auto)"
|
||||
if [ "$configured" != auto ] && [ -n "$configured" ]; then
|
||||
printf '%s\n' "$configured"
|
||||
return 0
|
||||
fi
|
||||
|
||||
interface="$(wan_interface)" || return 1
|
||||
ubus call "network.interface.$interface" status 2>/dev/null \
|
||||
| jsonfilter -e '@["ipv4-address"][0].address' 2>/dev/null \
|
||||
| grep -m1 .
|
||||
}
|
||||
|
||||
lan_ip() {
|
||||
local configured
|
||||
configured="$(uci_get main lan_bind_ip auto)"
|
||||
if [ "$configured" != auto ] && [ -n "$configured" ]; then
|
||||
printf '%s\n' "$configured"
|
||||
return 0
|
||||
fi
|
||||
|
||||
ubus call network.interface.lan status 2>/dev/null \
|
||||
| jsonfilter -e '@["ipv4-address"][0].address' 2>/dev/null \
|
||||
| grep -m1 .
|
||||
}
|
||||
|
||||
route_name() {
|
||||
printf '%s' "$1" | tr '.:-' '___' | tr -cd 'A-Za-z0-9_'
|
||||
}
|
||||
|
||||
is_valid_host() {
|
||||
case "$1" in
|
||||
''|[!A-Za-z0-9]*|*[!A-Za-z0-9]) return 1 ;;
|
||||
*[!A-Za-z0-9.-]*) return 1 ;;
|
||||
esac
|
||||
return 0
|
||||
}
|
||||
|
||||
is_valid_ip_or_host() {
|
||||
case "$1" in
|
||||
''|*[!A-Za-z0-9_.:-]*) return 1 ;;
|
||||
esac
|
||||
return 0
|
||||
}
|
||||
|
||||
is_valid_backup_id() {
|
||||
case "$1" in
|
||||
[0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]-[0-9][0-9][0-9][0-9][0-9][0-9]) return 0 ;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
}
|
||||
|
||||
backend_address() {
|
||||
local host="$1"
|
||||
local port="$2"
|
||||
|
||||
case "$host" in
|
||||
*:*) printf '[%s]:%s\n' "$host" "$port" ;;
|
||||
*) printf '%s:%s\n' "$host" "$port" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
is_valid_port() {
|
||||
local port="$1"
|
||||
[ "$port" -ge 1 ] 2>/dev/null && [ "$port" -le 65535 ] 2>/dev/null
|
||||
}
|
||||
|
||||
route_sections() {
|
||||
uci -q show "$CONFIG" \
|
||||
| sed -n "s/^$CONFIG\\.\\(@route\\[[0-9][0-9]*\\]\\)=route/\\1/p"
|
||||
}
|
||||
|
||||
route_kind() {
|
||||
local section="$1"
|
||||
local kind
|
||||
|
||||
kind="$(uci_get "$section" kind)"
|
||||
[ -n "$kind" ] || kind="$(uci_get "$section" protocol http)"
|
||||
printf '%s\n' "$kind"
|
||||
}
|
||||
|
||||
route_port_maps() {
|
||||
local section="$1"
|
||||
local kind="$2"
|
||||
local public_port backend_port
|
||||
|
||||
case "$kind" in
|
||||
ssh)
|
||||
public_port="$(uci_get "$section" ssh_listen_port 22)"
|
||||
backend_port="$(uci_get "$section" ssh_backend_port 22)"
|
||||
printf '%s:%s\n' "$public_port" "$backend_port"
|
||||
;;
|
||||
rdp)
|
||||
public_port="$(uci_get "$section" rdp_listen_port 3389)"
|
||||
backend_port="$(uci_get "$section" rdp_backend_port 3389)"
|
||||
printf '%s:%s\n' "$public_port" "$backend_port"
|
||||
;;
|
||||
custom)
|
||||
for map in $(uci_get "$section" port_map); do
|
||||
printf '%s\n' "$map"
|
||||
done
|
||||
;;
|
||||
tcp)
|
||||
public_port="$(uci_get "$section" listen_port "$(uci_get "$section" backend_port)")"
|
||||
backend_port="$(uci_get "$section" backend_port)"
|
||||
printf '%s:%s\n' "$public_port" "$backend_port"
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
is_valid_port_map() {
|
||||
local map="$1"
|
||||
local public_port backend_port
|
||||
|
||||
case "$map" in
|
||||
*:*:*) return 1 ;;
|
||||
*:*) ;;
|
||||
*) return 1 ;;
|
||||
esac
|
||||
|
||||
public_port="${map%%:*}"
|
||||
backend_port="${map#*:}"
|
||||
is_valid_port "$public_port" && is_valid_port "$backend_port"
|
||||
}
|
||||
|
||||
required_ports() {
|
||||
local section enabled kind http_enabled https_enabled map
|
||||
local http_port https_port
|
||||
|
||||
http_port="$(uci_get main http_port 80)"
|
||||
https_port="$(uci_get main https_port 443)"
|
||||
[ "$(uci_get main enabled 0)" = 1 ] || return 0
|
||||
|
||||
for section in $(route_sections); do
|
||||
enabled="$(uci_get "$section" enabled 1)"
|
||||
[ "$enabled" = 1 ] || continue
|
||||
kind="$(route_kind "$section")"
|
||||
|
||||
case "$kind" in
|
||||
web)
|
||||
http_enabled="$(uci_get "$section" web_http 1)"
|
||||
https_enabled="$(uci_get "$section" web_https 1)"
|
||||
[ "$http_enabled" != 1 ] || printf '%s\n' "$http_port"
|
||||
[ "$https_enabled" != 1 ] || printf '%s\n' "$https_port"
|
||||
;;
|
||||
http)
|
||||
printf '%s\n' "$http_port"
|
||||
;;
|
||||
https)
|
||||
printf '%s\n' "$https_port"
|
||||
;;
|
||||
both)
|
||||
printf '%s\n%s\n' "$http_port" "$https_port"
|
||||
;;
|
||||
ssh|rdp|custom|tcp)
|
||||
for map in $(route_port_maps "$section" "$kind"); do
|
||||
printf '%s\n' "${map%%:*}"
|
||||
done
|
||||
;;
|
||||
esac
|
||||
done | sort -nu
|
||||
}
|
||||
|
||||
port_spec_contains() {
|
||||
local spec="$1"
|
||||
local wanted="$2"
|
||||
local token first last
|
||||
|
||||
for token in $(printf '%s' "$spec" | tr ',' ' '); do
|
||||
case "$token" in
|
||||
*-*)
|
||||
first="${token%%-*}"
|
||||
last="${token#*-}"
|
||||
[ "$wanted" -ge "$first" ] 2>/dev/null && [ "$wanted" -le "$last" ] 2>/dev/null && return 0
|
||||
;;
|
||||
*)
|
||||
[ "$token" = "$wanted" ] && return 0
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
return 1
|
||||
}
|
||||
|
||||
set_uhttpd_list() {
|
||||
local option values current address
|
||||
option="$1"
|
||||
values="$2"
|
||||
current="$(uci -q get "uhttpd.main.$option" 2>/dev/null || true)"
|
||||
[ "$current" = "$values" ] && return 0
|
||||
|
||||
uci -q delete "uhttpd.main.$option" || true
|
||||
for address in $values; do
|
||||
uci add_list "uhttpd.main.$option=$address"
|
||||
done
|
||||
UHTTPD_CHANGED=1
|
||||
}
|
||||
|
||||
capture_uhttpd_bindings() {
|
||||
local saved_http saved_https address
|
||||
[ "$(uci_get main uhttpd_bind_owned 0)" != 1 ] || return 0
|
||||
|
||||
saved_http="$(uci -q get uhttpd.main.listen_http 2>/dev/null || true)"
|
||||
saved_https="$(uci -q get uhttpd.main.listen_https 2>/dev/null || true)"
|
||||
uci -q delete "$CONFIG.main.uhttpd_saved_listen_http" || true
|
||||
uci -q delete "$CONFIG.main.uhttpd_saved_listen_https" || true
|
||||
for address in $saved_http; do
|
||||
uci add_list "$CONFIG.main.uhttpd_saved_listen_http=$address"
|
||||
done
|
||||
for address in $saved_https; do
|
||||
uci add_list "$CONFIG.main.uhttpd_saved_listen_https=$address"
|
||||
done
|
||||
uci set "$CONFIG.main.uhttpd_bind_owned=1"
|
||||
uci commit "$CONFIG"
|
||||
}
|
||||
|
||||
restore_uhttpd_bindings() {
|
||||
[ "$(uci_get main uhttpd_bind_owned 0)" = 1 ] || return 0
|
||||
|
||||
set_uhttpd_list listen_http "$(uci_get main uhttpd_saved_listen_http)"
|
||||
set_uhttpd_list listen_https "$(uci_get main uhttpd_saved_listen_https)"
|
||||
uci -q delete "$CONFIG.main.uhttpd_saved_listen_http" || true
|
||||
uci -q delete "$CONFIG.main.uhttpd_saved_listen_https" || true
|
||||
uci -q delete "$CONFIG.main.uhttpd_bind_owned" || true
|
||||
uci commit "$CONFIG"
|
||||
}
|
||||
Reference in new issue
Block a user