- service.sh: split service_remove into internal (no prompts) and interactive versions to prevent 'eternal wait' when installing new strategy. Install now calls service_remove_internal > /dev/null instead of service_remove. Also filter strategy list to general*.sh only to avoid clutter. Systemd ExecStart now points to run_strategy.sh <name> consistently. - run_strategy.sh: add SIGTERM/SIGINT trap cleanup_strategy() that kills nfqws and cleans up firewall. Prevents stale nfqws/firewall rules after autotest kill. Also handles nfqws exit gracefully with final cleanup. - autotest.sh: rewritten to test strategies by config name (not wrapper filename). Stop now sends SIGTERM to wrapper (which triggers trap cleanup) instead of bare kill. Added extra sleep after stop to let trap fire. Auto-install ExecStart fixed to run_strategy.sh <strategy>. - setup.sh: added libmnl-dev and zlib1g-dev to Ubuntu/Debian dependency install to prevent build failures (missing libmnl/libmnl.h and zlib.h). - general*.sh: removed UTF-8 BOM (0xEF 0xBB 0xBF) that caused 'exec format error' when running scripts on Linux. All 19 wrappers cleaned. - ensure_wrappers.sh: always rewrite wrappers to ensure no stale BOM or paths. Fixes: eternal wait on menu option 1, nfqws build failure, stale processes after test.
225 lines
7.5 KiB
Bash
Executable File
225 lines
7.5 KiB
Bash
Executable File
#!/bin/bash
|
|
# Common functions for zapret-discord-youtube Linux
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && cd .. && pwd)"
|
|
BIN_DIR="$SCRIPT_DIR/bin"
|
|
LISTS_DIR="$SCRIPT_DIR/lists"
|
|
UTILS_DIR="$SCRIPT_DIR/utils"
|
|
SYSTEMD_DIR="$SCRIPT_DIR/systemd"
|
|
LOCAL_VERSION="1.9.8c-linux"
|
|
NFT_TABLE="zapret"
|
|
NFQUEUE_NUM=200
|
|
|
|
# Colors
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
CYAN='\033[0;36m'
|
|
NC='\033[0m'
|
|
|
|
print_green() { echo -e "${GREEN}$1${NC}"; }
|
|
print_red() { echo -e "${RED}$1${NC}"; }
|
|
print_yellow(){ echo -e "${YELLOW}$1${NC}"; }
|
|
print_cyan() { echo -e "${CYAN}$1${NC}"; }
|
|
|
|
# Detect package manager
|
|
check_root() {
|
|
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
|
|
}
|
|
|
|
detect_distro() {
|
|
if [ -f /etc/os-release ]; then
|
|
. /etc/os-release
|
|
echo "$ID"
|
|
else
|
|
echo "unknown"
|
|
fi
|
|
}
|
|
|
|
# iptables wrapper with -w support
|
|
iptables_cmd() {
|
|
if iptables -w -L -n -t mangle >/dev/null 2>&1; then
|
|
iptables -w "$@"
|
|
else
|
|
iptables "$@"
|
|
fi
|
|
}
|
|
|
|
ip6tables_cmd() {
|
|
if ip6tables -w -L -n -t mangle >/dev/null 2>&1; then
|
|
ip6tables -w "$@"
|
|
else
|
|
ip6tables "$@"
|
|
fi
|
|
}
|
|
|
|
nft_supports() {
|
|
nft list tables >/dev/null 2>&1
|
|
}
|
|
|
|
load_user_lists() {
|
|
if [[ ! -f "$LISTS_DIR/ipset-exclude-user.txt" ]]; then
|
|
echo "203.0.113.113/32" > "$LISTS_DIR/ipset-exclude-user.txt"
|
|
fi
|
|
if [[ ! -f "$LISTS_DIR/list-general-user.txt" ]]; then
|
|
echo "domain.example.abc" > "$LISTS_DIR/list-general-user.txt"
|
|
fi
|
|
if [[ ! -f "$LISTS_DIR/list-exclude-user.txt" ]]; then
|
|
echo "domain.example.abc" > "$LISTS_DIR/list-exclude-user.txt"
|
|
fi
|
|
}
|
|
|
|
get_game_filter() {
|
|
if [[ -f "$SCRIPT_DIR/.service/game_filter_enabled" ]]; then
|
|
GameFilter="enabled"
|
|
GameFilterTCP="1024:65535"
|
|
GameFilterUDP="1024:65535"
|
|
else
|
|
GameFilter="disabled"
|
|
GameFilterTCP=""
|
|
GameFilterUDP=""
|
|
fi
|
|
}
|
|
|
|
describe_strategy() {
|
|
local name
|
|
name=$(basename "$1")
|
|
case "$name" in
|
|
general.sh) echo "Standard multisplit strategy";;
|
|
general_ALT.sh) echo "Fake fakedsplit with ts fooling";;
|
|
general_ALT2.sh) echo "Multisplit with split-pos=2";;
|
|
general_ALT3.sh) echo "Hostfake split (Google/ya.ru)";;
|
|
general_ALT4.sh) echo "Fake multisplit with badseq";;
|
|
general_ALT5.sh) echo "NOT RECOMMENDED: syndata multidisorder";;
|
|
general_ALT6.sh) echo "Uniform split-seqovl=681";;
|
|
general_ALT7.sh) echo "Multisplit + syndata";;
|
|
general_ALT8.sh) echo "Fake with badseq-increment=2";;
|
|
general_ALT9.sh) echo "Hostfakesplit (ozon.ru)";;
|
|
general_ALT10.sh) echo "Fake with ts fooling";;
|
|
general_ALT11.sh) echo "Fake multisplit with max_ru pattern";;
|
|
general_FAKE_TLS_AUTO.sh) echo "FAKE TLS AUTO multidisorder";;
|
|
general_FAKE_TLS_AUTO_ALT.sh) echo "FAKE TLS fakedsplit";;
|
|
general_FAKE_TLS_AUTO_ALT2.sh) echo "FAKE TLS multisplit badseq";;
|
|
general_FAKE_TLS_AUTO_ALT3.sh) echo "FAKE TLS with 4pda pattern";;
|
|
general_SIMPLE_FAKE.sh) echo "Simple fake strategy";;
|
|
general_SIMPLE_FAKE_ALT.sh) echo "Simple fakedsplit";;
|
|
general_SIMPLE_FAKE_ALT2.sh) echo "Simple hostfakesplit";;
|
|
*) echo "Custom strategy";;
|
|
esac
|
|
}
|
|
|
|
check_nfqws() {
|
|
if [[ ! -x "$BIN_DIR/nfqws" ]]; then
|
|
echo ""
|
|
print_red "ERROR: nfqws binary not found!"
|
|
echo ""
|
|
echo "Please build it first:"
|
|
echo " ./install_nfqws.sh"
|
|
echo ""
|
|
return 1
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
tcp_enable_timestamps() {
|
|
if [[ -w /proc/sys/net/ipv4/tcp_timestamps ]]; then
|
|
echo 1 > /proc/sys/net/ipv4/tcp_timestamps 2>/dev/null || true
|
|
fi
|
|
}
|
|
|
|
setup_firewall() {
|
|
local tcp_ports="80,443,2053,2083,2087,2096,8443"
|
|
local udp_ports="443,19294:19344,50000:50100"
|
|
|
|
get_game_filter
|
|
if [[ -n "$GameFilterTCP" ]]; then
|
|
tcp_ports="${tcp_ports},${GameFilterTCP}"
|
|
fi
|
|
if [[ -n "$GameFilterUDP" ]]; then
|
|
udp_ports="${udp_ports},${GameFilterUDP}"
|
|
fi
|
|
|
|
if nft_supports; then
|
|
print_cyan "[*] Using nftables..."
|
|
nft add table ip $NFT_TABLE 2>/dev/null || true
|
|
nft add chain ip $NFT_TABLE postrouting '{ type filter hook postrouting priority mangle; policy accept; }' 2>/dev/null || nft flush chain ip $NFT_TABLE postrouting 2>/dev/null || true
|
|
|
|
IFS=',' read -ra TCP_P <<< "$tcp_ports"
|
|
for port in "${TCP_P[@]}"; do
|
|
nft add rule ip $NFT_TABLE postrouting tcp dport "$port" counter queue num $NFQUEUE_NUM 2>/dev/null || true
|
|
done
|
|
IFS=',' read -ra UDP_P <<< "$udp_ports"
|
|
for port in "${UDP_P[@]}"; do
|
|
nft add rule ip $NFT_TABLE postrouting udp dport "$port" counter queue num $NFQUEUE_NUM 2>/dev/null || true
|
|
done
|
|
else
|
|
print_cyan "[*] Using iptables..."
|
|
IFS=',' read -ra TCP_P <<< "$tcp_ports"
|
|
for port in "${TCP_P[@]}"; do
|
|
iptables_cmd -t mangle -C POSTROUTING -p tcp --dport "$port" -j NFQUEUE --queue-num "$NFQUEUE_NUM" 2>/dev/null || \
|
|
iptables_cmd -t mangle -I POSTROUTING -p tcp --dport "$port" -j NFQUEUE --queue-num "$NFQUEUE_NUM"
|
|
done
|
|
IFS=',' read -ra UDP_P <<< "$udp_ports"
|
|
for port in "${UDP_P[@]}"; do
|
|
iptables_cmd -t mangle -C POSTROUTING -p udp --dport "$port" -j NFQUEUE --queue-num "$NFQUEUE_NUM" 2>/dev/null || \
|
|
iptables_cmd -t mangle -I POSTROUTING -p udp --dport "$port" -j NFQUEUE --queue-num "$NFQUEUE_NUM"
|
|
done
|
|
fi
|
|
}
|
|
|
|
cleanup_firewall() {
|
|
echo "[*] Removing firewall rules..."
|
|
pkill -f "nfqws.*qnum=$NFQUEUE_NUM" 2>/dev/null || true
|
|
sleep 1
|
|
|
|
if nft list table ip $NFT_TABLE >/dev/null 2>&1; then
|
|
nft delete table ip $NFT_TABLE 2>/dev/null || true
|
|
fi
|
|
|
|
local ports=(80 443 2053 2083 2087 2096 8443 "1024:65535")
|
|
for port in "${ports[@]}"; do
|
|
while iptables_cmd -t mangle -C POSTROUTING -p tcp --dport "$port" -j NFQUEUE --queue-num "$NFQUEUE_NUM" 2>/dev/null; do
|
|
iptables_cmd -t mangle -D POSTROUTING -p tcp --dport "$port" -j NFQUEUE --queue-num "$NFQUEUE_NUM" 2>/dev/null || break
|
|
done
|
|
while iptables_cmd -t mangle -C POSTROUTING -p udp --dport "$port" -j NFQUEUE --queue-num "$NFQUEUE_NUM" 2>/dev/null; do
|
|
iptables_cmd -t mangle -D POSTROUTING -p udp --dport "$port" -j NFQUEUE --queue-num "$NFQUEUE_NUM" 2>/dev/null || break
|
|
done
|
|
done
|
|
for port in 19294:19344 50000:50100; do
|
|
while iptables_cmd -t mangle -C POSTROUTING -p udp --dport "$port" -j NFQUEUE --queue-num "$NFQUEUE_NUM" 2>/dev/null; do
|
|
iptables_cmd -t mangle -D POSTROUTING -p udp --dport "$port" -j NFQUEUE --queue-num "$NFQUEUE_NUM" 2>/dev/null || break
|
|
done
|
|
done
|
|
}
|
|
|
|
run_nfqws() {
|
|
local strategy_file="$1"
|
|
shift
|
|
|
|
check_nfqws || return 1
|
|
tcp_enable_timestamps
|
|
load_user_lists
|
|
get_game_filter
|
|
|
|
if pgrep -f "nfqws.*qnum=$NFQUEUE_NUM" >/dev/null 2>&1; then
|
|
print_yellow "WARNING: nfqws is already running. Stopping existing instance..."
|
|
cleanup_firewall
|
|
sleep 1
|
|
fi
|
|
|
|
setup_firewall
|
|
|
|
local strat_name
|
|
strat_name=$(basename "$strategy_file")
|
|
echo ""
|
|
print_cyan "[*] Starting strategy: $strat_name"
|
|
print_cyan "[*] $(describe_strategy "$strategy_file")"
|
|
echo ""
|
|
|
|
"$BIN_DIR/nfqws" --qnum=$NFQUEUE_NUM "$@"
|
|
}
|