557 lines
16 KiB
Bash
Executable File
557 lines
16 KiB
Bash
Executable File
#!/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 <<EOF
|
|
[Unit]
|
|
Description=Zapret DPI bypass (strategy: $strategy_name)
|
|
After=network.target
|
|
|
|
[Service]
|
|
Type=simple
|
|
ExecStart=$SCRIPT_DIR/run_strategy.sh $strategy_name
|
|
Restart=on-failure
|
|
RestartSec=5
|
|
StandardOutput=journal
|
|
StandardError=journal
|
|
|
|
[Install]
|
|
WantedBy=multi-user.target
|
|
EOF
|
|
|
|
if command -v systemctl >/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
|