199 lines
4.9 KiB
Bash
199 lines
4.9 KiB
Bash
#!/usr/bin/env bash
|
|
|
|
# ============================================
|
|
# Help
|
|
# ============================================
|
|
|
|
function cmd::preset::help() {
|
|
cat <<EOF
|
|
Usage: wgctl preset <subcommand> [options]
|
|
|
|
Manage firewall presets.
|
|
|
|
Subcommands:
|
|
list, ls List available presets
|
|
add, new, create Add a new preset
|
|
remove, rm, del Remove a preset
|
|
|
|
Options for add:
|
|
--name <name> Preset name (e.g. no-jellyfin)
|
|
--desc <description> Human readable description
|
|
--block-ip <ip> Block specific IP (repeatable)
|
|
--block-subnet <cidr> Block subnet (repeatable)
|
|
--block-port <ip:port:proto> Block specific port (repeatable)
|
|
|
|
Examples:
|
|
wgctl preset list
|
|
wgctl preset add --name no-jellyfin --desc "Block Jellyfin" --block-ip 10.0.0.210 --block-port 10.0.0.210:8096:tcp
|
|
wgctl preset remove --name no-jellyfin
|
|
EOF
|
|
}
|
|
|
|
# ============================================
|
|
# Run
|
|
# ============================================
|
|
|
|
function cmd::preset::run() {
|
|
local subcmd="${1:-help}"
|
|
shift || true
|
|
|
|
case "$subcmd" in
|
|
list|ls) cmd::preset::list "$@" ;;
|
|
add|new|create) cmd::preset::add "$@" ;;
|
|
remove|rm|del|delete) cmd::preset::remove "$@" ;;
|
|
help) cmd::preset::help ;;
|
|
*)
|
|
log::error "Unknown subcommand: '${subcmd}'"
|
|
cmd::preset::help
|
|
return 1
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# ============================================
|
|
# List
|
|
# ============================================
|
|
|
|
function cmd::preset::list() {
|
|
local dir
|
|
dir="$(ctx::presets)"
|
|
|
|
local presets=("${dir}"/*.preset)
|
|
if [[ ! -f "${presets[0]}" ]]; then
|
|
log::wg_preset "No presets configured"
|
|
return 0
|
|
fi
|
|
|
|
log::section "Available Presets"
|
|
|
|
printf "\n %-25s %-40s %s\n" "NAME" "DESCRIPTION" "RULES"
|
|
printf " %s\n" "$(printf '─%.0s' {1..75})"
|
|
|
|
for preset_file in "${dir}"/*.preset; do
|
|
[[ -f "$preset_file" ]] || continue
|
|
|
|
# Reset vars before sourcing
|
|
local PRESET_NAME="" PRESET_DESC=""
|
|
local BLOCK_IPS="" BLOCK_SUBNETS="" BLOCK_PORTS=""
|
|
|
|
source "$preset_file"
|
|
|
|
local rules=""
|
|
[[ -n "$BLOCK_IPS" ]] && rules+="IPs:$(echo "$BLOCK_IPS" | wc -w) "
|
|
[[ -n "$BLOCK_SUBNETS" ]] && rules+="Subnets:$(echo "$BLOCK_SUBNETS" | wc -w) "
|
|
[[ -n "$BLOCK_PORTS" ]] && rules+="Ports:$(echo "$BLOCK_PORTS" | wc -w)"
|
|
|
|
printf " %-25s %-40s %s\n" \
|
|
"$PRESET_NAME" \
|
|
"${PRESET_DESC:-—}" \
|
|
"${rules:-—}"
|
|
done
|
|
|
|
printf "\n"
|
|
}
|
|
|
|
# ============================================
|
|
# Add
|
|
# ============================================
|
|
|
|
function cmd::preset::add() {
|
|
local name=""
|
|
local desc=""
|
|
local block_ips=()
|
|
local block_subnets=()
|
|
local block_ports=()
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--name) name="$2"; shift 2 ;;
|
|
--desc) desc="$2"; shift 2 ;;
|
|
--block-ip) block_ips+=("$2"); shift 2 ;;
|
|
--block-subnet) block_subnets+=("$2"); shift 2 ;;
|
|
--block-port) block_ports+=("$2"); shift 2 ;;
|
|
--help) cmd::preset::help; return ;;
|
|
*)
|
|
log::error "Unknown flag: $1"
|
|
cmd::preset::help
|
|
return 1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
if [[ -z "$name" ]]; then
|
|
log::error "Missing required flag: --name"
|
|
return 1
|
|
fi
|
|
|
|
if [[ ${#block_ips[@]} -eq 0 && ${#block_subnets[@]} -eq 0 && ${#block_ports[@]} -eq 0 ]]; then
|
|
log::error "At least one of --block-ip, --block-subnet, or --block-port is required"
|
|
return 1
|
|
fi
|
|
|
|
local preset_file
|
|
preset_file="$(ctx::preset::path "${name}.preset")"
|
|
|
|
if [[ -f "$preset_file" ]]; then
|
|
log::error "Preset already exists: ${name}"
|
|
return 1
|
|
fi
|
|
|
|
cat > "$preset_file" <<EOF
|
|
# wgctl preset — ${name}
|
|
PRESET_NAME="${name}"
|
|
PRESET_DESC="${desc}"
|
|
BLOCK_IPS="${block_ips[*]:-}"
|
|
BLOCK_SUBNETS="${block_subnets[*]:-}"
|
|
BLOCK_PORTS="${block_ports[*]:-}"
|
|
EOF
|
|
|
|
log::wg_success "Preset created: ${name}"
|
|
}
|
|
|
|
# ============================================
|
|
# Remove
|
|
# ============================================
|
|
|
|
function cmd::preset::remove() {
|
|
local name=""
|
|
local force=false
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--name) name="$2"; shift 2 ;;
|
|
--force) force=true; shift ;;
|
|
--help) cmd::preset::help; return ;;
|
|
*)
|
|
log::error "Unknown flag: $1"
|
|
cmd::preset::help
|
|
return 1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
if [[ -z "$name" ]]; then
|
|
log::error "Missing required flag: --name"
|
|
return 1
|
|
fi
|
|
|
|
local preset_file
|
|
preset_file="$(ctx::preset::path "${name}.preset")"
|
|
|
|
if [[ ! -f "$preset_file" ]]; then
|
|
log::error "Preset not found: ${name}"
|
|
return 1
|
|
fi
|
|
|
|
if ! $force; then
|
|
read -r -p "Are you sure you want to remove preset '${name}'? [y/N] " confirm
|
|
case "$confirm" in
|
|
[yY][eE][sS]|[yY]) ;;
|
|
*)
|
|
log::info "Aborted"
|
|
return 0
|
|
;;
|
|
esac
|
|
fi
|
|
|
|
rm -f "$preset_file"
|
|
log::wg_success "Preset removed: ${name}"
|
|
}
|