237 lines
8.0 KiB
Bash
Executable File
237 lines
8.0 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
|
|
}
|
|
|
|
# Verify the binary actually runs (catches segfaults/missing deps)
|
|
check_nfqws() {
|
|
if [[ ! -f "$BIN_DIR/nfqws" ]] || [[ ! -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
|
|
# Verify the binary actually runs (catches segfaults/missing deps).
|
|
# Use --version because --help exits with code 1 in zapret.
|
|
if ! "$BIN_DIR/nfqws" --version >/dev/null 2>&1; then
|
|
echo ""
|
|
print_red "ERROR: nfqws binary exists but does not run (segfault? missing deps?)"
|
|
echo ""
|
|
echo "Try rebuilding:"
|
|
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 "$@"
|
|
}
|