#!/bin/bash # service.sh - Zapret Service Manager for Linux # Analogous to service.bat on Windows SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "$SCRIPT_DIR/lib/functions.sh" # ============================================ # External commands (called from general*.sh) # ============================================ if [[ "$1" == "status_zapret" ]]; then check_nfqws >/dev/null 2>&1 || true tcp_enable_timestamps exit 0 fi if [[ "$1" == "check_updates" ]]; then if [[ "${2:-}" != "soft" ]]; then bash "$0" check_updates soft >&1 & exit 0 else check_for_updates soft exit 0 fi fi if [[ "$1" == "load_game_filter" ]]; then get_game_filter exit 0 fi if [[ "$1" == "load_user_lists" ]]; then load_user_lists exit 0 fi # ============================================ # MENU # ============================================ show_menu() { local ipset_status game_filter_status check_updates_status current_strategy ipset_status=$(ipset_switch_status) game_filter_status=$(game_switch_status) check_updates_status=$(check_updates_switch_status) current_strategy=$(get_strategy_name) echo "" echo " ZAPRET SERVICE MANAGER v$LOCAL_VERSION" echo " $current_strategy" echo " ----------------------------------------" echo "" echo " :: SERVICE" echo " 1. Install Service" echo " 2. Remove Services" echo " 3. Check Status" echo "" echo " :: SETTINGS" echo " 4. Game Filter [$game_filter_status]" echo " 5. IPSet Filter [$ipset_status]" echo " 6. Auto-Update Check [$check_updates_status]" echo "" echo " :: UPDATES" echo " 7. Update IPSet List" echo " 8. Update Hosts File" echo " 9. Check for Updates" echo "" echo " :: TOOLS" echo " 10. Run Diagnostics" echo " 11. Run Tests (find ALL working strategies)" echo "" echo " ----------------------------------------" echo " 0. Exit" echo "" } # ============================================ # STATUS HELPERS # ============================================ get_strategy_name() { if [[ -f "$SCRIPT_DIR/.service/installed_strategy" ]]; then local strat strat=$(cat "$SCRIPT_DIR/.service/installed_strategy") echo "Current strategy: $strat" else echo "No service installed" fi } ipset_switch_status() { if [[ -f "$SCRIPT_DIR/.service/ipset_filter_any" ]]; then echo "any" elif [[ -f "$SCRIPT_DIR/.service/ipset_filter_loaded" ]]; then echo "loaded" else echo "none" fi } game_switch_status() { if [[ -f "$SCRIPT_DIR/.service/game_filter_enabled" ]]; then echo "enabled" else echo "disabled" fi } check_updates_switch_status() { if [[ -f "$SCRIPT_DIR/.service/check_updates_enabled" ]]; then echo "enabled" else echo "disabled" fi } # ============================================ # SERVICE INSTALL # ============================================ service_install() { echo "" echo "[*] Pick one of the strategies:" echo "" local files=() local i=1 while IFS= read -r -d '' f; do local name name=$(basename "$f") [[ "$name" == general*.sh ]] || continue files+=("$f") local desc desc=$(describe_strategy "$f") printf " %2d. %-35s %s\n" "$i" "$name" "$desc" ((i++)) done < <(find "$SCRIPT_DIR" -maxdepth 1 -type f -name 'general*.sh' -print0 | sort -z) echo "" read -rp " Input file index (number): " choice if [[ -z "$choice" ]]; then echo "The choice is empty, exiting..." return fi local selected="${files[$((choice-1))]}" if [[ -z "$selected" ]]; then echo "Invalid choice, exiting..." return fi local strategy_name strategy_name=$(basename "$selected" .sh | sed 's/^general_//') [[ -z "$strategy_name" ]] && strategy_name="general" echo "" echo "[*] Installing strategy: $strategy_name" service_remove_internal > /dev/null 2>&1 || true mkdir -p "$SCRIPT_DIR/.service" echo "$strategy_name" > "$SCRIPT_DIR/.service/installed_strategy" cat > /etc/systemd/system/zapret.service </dev/null 2>&1; then systemctl daemon-reload systemctl enable zapret.service systemctl start zapret.service echo "" print_green "[OK] Service installed and started." echo " Strategy: $strategy_name" echo " systemd: /etc/systemd/system/zapret.service" else echo "" print_yellow "[!] systemctl not found. Service file created but not installed automatically." echo " To start manually: $SCRIPT_DIR/run_strategy.sh $strategy_name" fi read -rp "Press Enter to continue..." } # ============================================ # SERVICE REMOVE (internal — no prompts) # ============================================ service_remove_internal() { if command -v systemctl >/dev/null 2>&1; then systemctl stop zapret.service 2>/dev/null || true systemctl disable zapret.service 2>/dev/null || true rm -f /etc/systemd/system/zapret.service systemctl daemon-reload fi pkill -f "nfqws.*qnum=$NFQUEUE_NUM" 2>/dev/null || true sleep 1 cleanup_firewall rm -f "$SCRIPT_DIR/.service/installed_strategy" } # ============================================ # SERVICE REMOVE (interactive) # ============================================ service_remove() { echo "" echo "[*] Removing services..." service_remove_internal echo "" print_green "[OK] Services removed." read -rp "Press Enter to continue..." } # ============================================ # SERVICE STATUS # ============================================ service_status() { echo "" echo "[*] Service Status" echo "" if command -v systemctl >/dev/null 2>&1; then if systemctl is-active zapret.service >/dev/null 2>&1; then print_green "zapret.service is RUNNING." else print_red "zapret.service is NOT running." fi fi if pgrep -f "nfqws.*qnum=$NFQUEUE_NUM" >/dev/null 2>&1; then print_green "nfqws process is RUNNING." else print_red "nfqws process is NOT running." fi if nft list table ip $NFT_TABLE >/dev/null 2>&1; then print_green "nftables rules are LOADED." elif iptables -t mangle -L -n 2>/dev/null | grep -q "NFQUEUE"; then print_green "iptables rules are LOADED." else print_red "No firewall rules found." fi local strat strat=$(get_strategy_name) echo "" echo "Strategy: $strat" echo "" read -rp "Press Enter to continue..." } # ============================================ # GAME FILTER SWITCH # ============================================ game_switch() { echo "" if [[ -f "$SCRIPT_DIR/.service/game_filter_enabled" ]]; then rm -f "$SCRIPT_DIR/.service/game_filter_enabled" echo "[*] Game Filter: DISABLED" echo " (Restart strategy to apply)" else touch "$SCRIPT_DIR/.service/game_filter_enabled" echo "[*] Game Filter: ENABLED" echo " (Restart strategy to apply)" fi read -rp "Press Enter to continue..." } # ============================================ # IPSET FILTER SWITCH # ============================================ ipset_switch() { echo "" echo "[*] IPSet Filter options:" echo " 1. none - no IPs checked" echo " 2. loaded - check against ipset-all.txt" echo " 3. any - any IP goes through filter" echo "" read -rp " Select option (1-3): " choice rm -f "$SCRIPT_DIR/.service/ipset_filter_none" rm -f "$SCRIPT_DIR/.service/ipset_filter_loaded" rm -f "$SCRIPT_DIR/.service/ipset_filter_any" case "$choice" in 1) touch "$SCRIPT_DIR/.service/ipset_filter_none" ;; 2) touch "$SCRIPT_DIR/.service/ipset_filter_loaded" ;; 3) touch "$SCRIPT_DIR/.service/ipset_filter_any" ;; *) echo "Invalid choice"; return ;; esac echo "[*] IPSet filter updated. (Restart strategy to apply)" read -rp "Press Enter to continue..." } # ============================================ # AUTO-UPDATE SWITCH # ============================================ check_updates_switch() { echo "" if [[ -f "$SCRIPT_DIR/.service/check_updates_enabled" ]]; then rm -f "$SCRIPT_DIR/.service/check_updates_enabled" echo "[*] Auto-Update Check: DISABLED" else touch "$SCRIPT_DIR/.service/check_updates_enabled" echo "[*] Auto-Update Check: ENABLED" fi read -rp "Press Enter to continue..." } # ============================================ # UPDATE IPSET LIST # ============================================ ipset_update() { echo "" echo "[*] Updating IPSet list..." local url="https://raw.githubusercontent.com/Flowseal/zapret-discord-youtube/main/.service/ipset-all.txt" if curl -sfL "$url" -o "$LISTS_DIR/ipset-all.txt.new" 2>/dev/null; then mv "$LISTS_DIR/ipset-all.txt.new" "$LISTS_DIR/ipset-all.txt" print_green "[OK] ipset-all.txt updated." else print_red "[!] Failed to update ipset-all.txt" echo " (URL may be unavailable)" fi read -rp "Press Enter to continue..." } # ============================================ # UPDATE HOSTS FILE # ============================================ hosts_update() { echo "" echo "[*] Hosts File Manager" echo "" local hosts_file="$SCRIPT_DIR/.service/hosts" if [[ ! -f "$hosts_file" ]]; then print_red "[!] Local hosts file not found: $hosts_file" read -rp "Press Enter to continue..." return fi echo "[*] Local hosts entries (for GitHub, Telegram, Discord):" echo "" grep -v '^#' "$hosts_file" | grep -v '^$' | head -n 20 local total total=$(grep -v '^#' "$hosts_file" | grep -v '^$' | wc -l) echo "" echo "Total entries: $total" echo "" read -rp "Append these entries to /etc/hosts? [y/N]: " ans if [[ "$ans" == [yY]* ]]; then sudo cp /etc/hosts "/etc/hosts.backup.$(date +%s)" echo "" | sudo tee -a /etc/hosts > /dev/null echo "# --- zapret-discord-youtube-linux hosts ---" | sudo tee -a /etc/hosts > /dev/null grep -v '^#' "$hosts_file" | grep -v '^$' | sudo tee -a /etc/hosts > /dev/null echo "# --- end zapret hosts ---" | sudo tee -a /etc/hosts > /dev/null print_green "[OK] Entries added to /etc/hosts" echo " Backup saved as /etc/hosts.backup.*" else echo "[*] Skipped. To add manually:" echo " sudo nano /etc/hosts" echo " Then copy from: $hosts_file" fi read -rp "Press Enter to continue..." } # ============================================ # CHECK FOR UPDATES # ============================================ # ============================================ # CHECK FOR UPDATES # ============================================ check_for_updates() { local mode="${1:-interactive}" local github_version_url="https://raw.githubusercontent.com/Flowseal/zapret-discord-youtube/main/.service/version.txt" local github_release_url="https://github.com/Flowseal/zapret-discord-youtube/releases/latest" local github_version github_version=$(curl -sfL "$github_version_url" 2>/dev/null | head -n1 | tr -d '[:space:]') if [[ -z "$github_version" ]]; then echo "Warning: failed to fetch the latest version." if [[ "$mode" == "interactive" ]]; then read -rp "Press Enter to continue..." fi return fi local local_ver_norm="${LOCAL_VERSION%-linux}" if [[ "$local_ver_norm" == "$github_version" ]]; then echo "Latest version installed: $LOCAL_VERSION" if [[ "$mode" == "interactive" ]]; then read -rp "Press Enter to continue..." fi return fi echo "" echo "New version available: $github_version" echo "Your version: $LOCAL_VERSION" echo "Release page: $github_release_url" echo "" if [[ "$mode" == "interactive" ]]; then read -rp "Open download page? [Y/n]: " ans if [[ "${ans:-Y}" == [yY]* ]]; then if command -v xdg-open >/dev/null 2>&1 && [[ -n "${DISPLAY:-}" ]]; then xdg-open "$github_release_url" elif command -v gnome-open >/dev/null 2>&1 && [[ -n "${DISPLAY:-}" ]]; then gnome-open "$github_release_url" else echo "Please open: $github_release_url" fi fi read -rp "Press Enter to continue..." fi } # ============================================ # DIAGNOSTICS # ============================================ service_diagnostics() { echo "" echo "[*] Running Diagnostics" echo "" if [[ "$EUID" -ne 0 ]]; then print_yellow "[!] Not running as root. Some checks may fail." fi if [[ -x "$BIN_DIR/nfqws" ]]; then print_green "[OK] nfqws binary found" else print_red "[FAIL] nfqws binary NOT found" echo " Run: ./install_nfqws.sh" fi if command -v iptables >/dev/null 2>&1; then print_green "[OK] iptables found" else print_red "[FAIL] iptables NOT found" fi if command -v nft >/dev/null 2>&1; then print_green "[OK] nftables (nft) found" else print_yellow "[WARN] nftables (nft) NOT found" fi if lsmod | grep -q "nfnetlink_queue"; then print_green "[OK] nfnetlink_queue module loaded" else print_yellow "[WARN] nfnetlink_queue module not loaded" echo " Try: sudo modprobe nfnetlink_queue" fi if command -v resolvectl >/dev/null 2>&1; then echo "" echo "[*] DNS settings:" resolvectl status 2>/dev/null | head -n 20 || true fi echo "" echo "[*] Checking for conflicting processes..." if pgrep -f "goodbye-dpi\|byedpi\|zapret-win" >/dev/null 2>&1; then print_yellow "[!] Another DPI bypass tool may be running" else print_green "[OK] No conflicting processes found" fi echo "" read -rp "Clear Discord cache? [y/N]: " ans if [[ "$ans" == [yY]* ]]; then local discord_cache="$HOME/.config/discord/Cache" if [[ -d "$discord_cache" ]]; then rm -rf "$discord_cache"/* 2>/dev/null || true print_green "[OK] Discord cache cleared." else print_yellow "[!] Discord cache directory not found." fi fi echo "" read -rp "Press Enter to continue..." } # ============================================ # RUN TESTS (menu 11 — finds ALL working strategies) # ============================================ run_tests() { echo "" echo "[*] Running strategy tests..." echo " This will test all strategies against YouTube + Discord." echo " At the end you'll see a list of ALL working strategies." echo "" read -rp " Press Enter to start or Ctrl+C to cancel..." bash "$SCRIPT_DIR/autotest.sh" --list-all echo "" read -rp "Press Enter to continue..." } # ============================================ # MAIN LOOP # ============================================ main() { 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 while true; do clear 2>/dev/null || true show_menu read -rp " Select option (0-11): " menu_choice case "$menu_choice" in 1) service_install ;; 2) service_remove ;; 3) service_status ;; 4) game_switch ;; 5) ipset_switch ;; 6) check_updates_switch ;; 7) ipset_update ;; 8) hosts_update ;; 9) check_for_updates ;; 10) service_diagnostics ;; 11) run_tests ;; 0) echo "Goodbye!"; exit 0 ;; *) echo "Invalid option" ; sleep 1 ;; esac done } main