#!/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#*=}" # 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 # 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') # 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