136 lines
3.8 KiB
Bash
Executable File
136 lines
3.8 KiB
Bash
Executable File
#!/bin/bash
|
|
# run_strategy.sh - Generic strategy runner using .conf files
|
|
# Loads strategies/strategy_name.conf, substitutes variables, runs nfqws.
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
source "$SCRIPT_DIR/lib/functions.sh"
|
|
|
|
# Require root for firewall/nfqueue manipulation
|
|
if [[ "${EUID:-$(id -u)}" -ne 0 ]]; then
|
|
print_red "[!] This script must be run as root (or with sudo)"
|
|
echo " sudo $0"
|
|
exit 1
|
|
fi
|
|
|
|
STRATEGY="${1:-general}"
|
|
CONF_FILE="$SCRIPT_DIR/strategies/${STRATEGY}.conf"
|
|
|
|
if [[ ! -f "$CONF_FILE" ]]; then
|
|
print_red "[ERROR] Strategy config not found: $CONF_FILE"
|
|
print_yellow "[*] Known strategies:"
|
|
for f in "$SCRIPT_DIR/strategies"/*.conf; do
|
|
[[ -f "$f" ]] || continue
|
|
local name
|
|
name=$(basename "$f" .conf)
|
|
echo " - $name"
|
|
done
|
|
exit 1
|
|
fi
|
|
|
|
# Pre-run setup
|
|
load_user_lists
|
|
get_game_filter
|
|
|
|
# Function to parse conf and build args
|
|
parse_conf_args() {
|
|
local conf="$1"
|
|
local -a args=()
|
|
|
|
while IFS= read -r line || [[ -n "$line" ]]; do
|
|
[[ "$line" =~ ^# ]] && continue
|
|
[[ -z "$line" ]] && continue
|
|
[[ "$line" =~ ^RULE[0-9]+= ]] || continue
|
|
|
|
local rule_value="${line#*=}"
|
|
|
|
# Substitute variables using sed (no envsubst dependency)
|
|
rule_value=$(echo "$rule_value" | sed \
|
|
-e "s|%BIN%|$BIN_DIR/|g" \
|
|
-e "s|%LISTS%|$LISTS_DIR/|g" \
|
|
-e "s|%GAME_TCP%|${GameFilterTCP:-}|g" \
|
|
-e "s|%GAME_UDP%|${GameFilterUDP:-}|g")
|
|
|
|
# Remove surrounding quotes added by .bat conversion around path args
|
|
rule_value=$(echo "$rule_value" | sed -E 's/="([^"]*)"/=\1/g')
|
|
|
|
# Skip rule if game filter placeholders remain but filter is empty
|
|
if [[ "$rule_value" == *'%GAME_TCP%'* ]] && [[ -z "${GameFilterTCP:-}" ]]; then
|
|
continue
|
|
fi
|
|
if [[ "$rule_value" == *'%GAME_UDP%'* ]] && [[ -z "${GameFilterUDP:-}" ]]; then
|
|
continue
|
|
fi
|
|
|
|
# Parse into array
|
|
local rule_arr=()
|
|
read -ra rule_arr <<< "$rule_value"
|
|
for arg in "${rule_arr[@]}"; do
|
|
args+=("$arg")
|
|
done
|
|
args+=("--new")
|
|
done < "$conf"
|
|
|
|
# Remove trailing --new
|
|
local last_idx=$(( ${#args[@]} - 1 ))
|
|
if [[ $last_idx -ge 0 ]] && [[ "${args[$last_idx]}" == "--new" ]]; then
|
|
unset 'args[last_idx]'
|
|
fi
|
|
|
|
# Return via echo (space-separated, properly quoted)
|
|
printf '%s\n' "${args[@]}"
|
|
}
|
|
|
|
# Build args in main shell using temp file
|
|
cd "$SCRIPT_DIR"
|
|
TMP_ARGS="$(mktemp /tmp/zapret_args.XXXXXX)"
|
|
cleanup_tmp() { rm -f "$TMP_ARGS" 2>/dev/null || true; }
|
|
trap cleanup_tmp EXIT
|
|
|
|
parse_conf_args "$CONF_FILE" > "$TMP_ARGS"
|
|
|
|
# If no args parsed
|
|
if [[ ! -s "$TMP_ARGS" ]]; then
|
|
print_red "[ERROR] No arguments parsed from $CONF_FILE"
|
|
rm -f "$TMP_ARGS"
|
|
exit 1
|
|
fi
|
|
|
|
# Read args into array from file
|
|
CLEAN_ARGS=()
|
|
while IFS= read -r arg; do
|
|
[[ -n "$arg" ]] && CLEAN_ARGS+=("$arg")
|
|
done < "$TMP_ARGS"
|
|
|
|
rm -f "$TMP_ARGS"
|
|
trap - EXIT
|
|
|
|
# Setup firewall and start nfqws
|
|
check_nfqws || exit 1
|
|
tcp_enable_timestamps
|
|
setup_firewall
|
|
|
|
# Trap cleanup on SIGTERM/SIGINT (e.g. from systemd or autotest kill)
|
|
cleanup_strategy() {
|
|
print_yellow ""
|
|
print_yellow "[*] Caught stop signal, cleaning up..."
|
|
pkill -f "nfqws.*qnum=$NFQUEUE_NUM" 2>/dev/null || true
|
|
cleanup_firewall >/dev/null 2>&1 || true
|
|
exit 0
|
|
}
|
|
trap cleanup_strategy SIGTERM SIGINT
|
|
|
|
echo ""
|
|
print_cyan "[*] Starting strategy: $STRATEGY"
|
|
print_cyan "[*] $(describe_strategy "$SCRIPT_DIR/general_${STRATEGY}.sh")"
|
|
echo ""
|
|
|
|
# Start nfqws in background so this shell handles signals and cleanup
|
|
"$BIN_DIR/nfqws" --qnum=$NFQUEUE_NUM "${CLEAN_ARGS[@]}" &
|
|
NFQWS_PID=$!
|
|
wait "$NFQWS_PID"
|
|
EXIT_CODE=$?
|
|
|
|
# If nfqws exited on its own, cleanup firewall
|
|
cleanup_firewall >/dev/null 2>&1 || true
|
|
exit $EXIT_CODE
|