Skip to content

Instantly share code, notes, and snippets.

@koolvn
Last active October 27, 2025 22:52
Show Gist options
  • Save koolvn/993d9c7eb2666dbf15bdccc7d3c4fe33 to your computer and use it in GitHub Desktop.
Save koolvn/993d9c7eb2666dbf15bdccc7d3c4fe33 to your computer and use it in GitHub Desktop.
# UDP Trash Hack for WireGuard on AsusWRT Merlin

UDP Trash Hack for WireGuard on AsusWRT Merlin

Подготовка

Проверяем, что включен пункт меню Enable JFFS custom scripts and configs

image

Установка

  • Кладём файл wgclient-start в /jffs/scripts/
  • Делаем скрипт запускаемым
chmod +x /jffs/scripts/wgclient-start
  • Подключаем WG клиента в настройках роутера. Если клиент уже подключен, то выполняем команду /jffs/scripts/wgclient-start <номер впн клиента> (Например /jffs/scripts/wgclient-start 1 если подключен клиент под номером 1)
  • Done ✅

Спасибо @alexbozhenko за полезные ссылки:

Проверен на роутерах:

  • ASUS RT-AX88U PRO, Merlin 3004.388.8_2
  • ASUS RT-AX68U, Merlin 3004.388.8_2
  • ASUS RT-AX86U
  • ASUS RT-AX56U, Merlin 3004.388.8_2
#!/bin/sh
# Set the number of times a random message would be sent
NUM_MESSAGES_SENT=3
# Random message generation params
block_size=512
block_count=5
# Enable exit on error
set -e
# Function to generate a random number between 49152 and 65535
generate_random_port() {
awk -v min=49152 -v max=65535 'BEGIN { srand(); print int(min + rand() * (max - min + 1)) }'
}
# Function to generate a random message and send it
send_random_message() {
message=$(dd if=/dev/urandom bs=$block_size count=$block_count 2>/dev/null | tr -dc 'A-Za-z0-9')
echo "$message" | socat - UDP-SENDTO:"$wg_server:$wg_port",sourceport="$l_port"
logger -t WireGuardClient -p user.notice "Message sent to WG server $wg_server:$wg_port from client's port $l_port"
sleep 1
}
interface="wgc$1"
sleep 3
# Log the start of the script
logger -t WireGuardClient -p user.notice "Starting junk-udp-hack script"
logger -t WireGuardClient -p user.notice "Processing WG interface - $interface"
# Retrieve the server and port
wg_endpoint=$(wg show "$interface" endpoints 2>/dev/null || echo "")
if [ -z "$wg_endpoint" ]; then
logger -s -t WireGuardClient -p user.err "Unable to retrieve endpoint for interface $interface" >&2
exit 1
fi
wg_server=$(echo "$wg_endpoint" | awk '{print $2}' | cut -d':' -f1 2>/dev/null || echo "")
wg_port=$(echo "$wg_endpoint" | awk '{print $2}' | cut -d':' -f2 2>/dev/null || echo "")
if [ -z "$wg_server" ] || [ -z "$wg_port" ]; then
logger -s -t WireGuardClient -p user.err "Unable to extract server or port for interface $interface" >&2
exit 1
fi
l_port=$(generate_random_port)
while netstat -an | grep -qE '(^|[^0-9])'"$l_port"'([^0-9]|$)'; do
logger -t WireGuardClient -p user.warn "Port $l_port is already in use. Generating new one"
sleep 1
l_port=$(generate_random_port)
done
# Send random messages specified number of times
i=1
while [ "$i" -le "$NUM_MESSAGES_SENT" ]; do
send_random_message
i=$((i + 1))
done
# Update the WireGuard interface with the new listen port
wg set "$interface" listen-port "$l_port"
logger -t WireGuardClient -p user.notice "Done"

Бонус

Случайно обнаружил, что многие сервисы, блокирующие трафик из РФ используют для этого Cloudflare. Так же РКН, видимо, частично блокирует адреса Cloudflare.

Оказалось, что если прописать IPшники Cloudflare в VPN Director и гнать трафик через ВПН, то волшебным образом начинают работать многие сервисы (например chatgpt.com и многие другие)

Написал скрипт для этого чуда и спешу поделиться 😅

Установка

  1. Прописываем нужного клиента в переменную VPN_CLIENT_ID (У меня это WGC2 у вас это может быть другой - WGC1 например)
  2. (Опционально) Прописываем в переменную LOCAL_SUBNET локальную подсеть или IP. В таком случае правила будут применяться только для них. Оставьте пустым, чтоб трафик к Cloudflare от всех клиентов роутера был пущен через ВПН
  3. Записываем файл в /jffs/scripts/update_cloudflare_rules.sh
  4. Делаем его запускаемым chmod +x /jffs/scripts/update_cloudflare_rules.sh
  5. Запускаем /jffs/scripts/update_cloudflare_rules.sh
  6. Если отработал без ошибок идём на вкладку VPN Director в UI роутера http://<ip:port>/Advanced_VPNDirector.asp Должно появиться что-то похожее: image
  7. Ставим автозапуск скрипта на 3 часа утра каждый день (IPшники Cloudflare могут периодически изменяться) cru a UpdCfVpnDirRules "0 3 * * * /jffs/scripts/update_cloudflare_rules.sh"

Всё готово!

#!/bin/sh
# ==============================================================================
# VPN Director - Cloudflare CIDR Updater
#
# This script automatically fetches the latest Cloudflare IPv4 CIDRs,
# compares them against the currently configured rules in VPN Director,
# and updates the rule list if any changes are detected.
#
# It correctly parses and generates the concatenated rule format.
# Designed for POSIX-compliant shells (e.g., ash on BusyBox).
# ==============================================================================
# --- Configuration ---
readonly RULE_PREFIX="Cloudflare v4_"
readonly VPN_CLIENT_ID="WGC1"
readonly RULES_FILE="/jffs/openvpn/vpndirector_rulelist"
readonly LOCAL_SUBNET="" # (Optional) Specify a subnet (e.g., 192.168.1.0/24) or a single IP address to restrict the Cloudflare rules to a specific local network segment or client.
# Leave empty ("") to apply the rules to ALL clients on the router.
# Example: LOCAL_SUBNET="192.168.1.0/24" will only route traffic from this subnet through the VPN for Cloudflare IPs.
# Use for testing
#readonly RULES_FILE="./vpndirector_rulelist"
# --- Script Logic ---
set -e
set -u
set -o pipefail
readonly TEMP_DIR="/tmp/cf_updater_$$"
mkdir "$TEMP_DIR"
trap 'rm -rf -- "$TEMP_DIR"' EXIT
readonly NEW_CIDRS_FILE="$TEMP_DIR/cloudflare_cidrs_new.txt"
readonly OLD_CIDRS_FILE="$TEMP_DIR/cloudflare_cidrs_old.txt"
readonly NEW_CF_RULES_FILE="$TEMP_DIR/cloudflare_rules_new.txt"
readonly OLD_CF_RULES_FILE="$TEMP_DIR/cloudflare_rules_old.txt"
logger -sc -t "Cloudflare CIDR VPN Director Updater" -p user.notice "INFO: Starting Cloudflare CIDR update process."
# Step 1: Fetch the latest Cloudflare IPv4 CIDRs.
intrfce=$(echo "$VPN_CLIENT_ID" | awk '{print tolower($0)}')
logger -sc -t "Cloudflare CIDR VPN Director Updater" -p user.notice "INFO: Fetching latest Cloudflare IPv4 CIDRs..."
if ! curl --interface "$intrfce" -s "https://api.cloudflare.com/client/v4/ips" | jq -r '.result.ipv4_cidrs[]' > "$NEW_CIDRS_FILE"; then
logger -sc -t "Cloudflare CIDR VPN Director Updater" -p user.error "ERROR: Failed to fetch or parse Cloudflare IPs. Exiting."
exit 1
fi
if [ ! -s "$NEW_CIDRS_FILE" ]; then
logger -sc -t "Cloudflare CIDR VPN Director Updater" -p user.error "ERROR: Fetched CIDR list is empty. Exiting."
exit 1
fi
# Step 2: Extract currently configured Cloudflare rules block.
logger -sc -t "Cloudflare CIDR VPN Director Updater" -p user.notice "INFO: Extracting existing Cloudflare rules from $RULES_FILE..."
if [ -f "$RULES_FILE" ] && [ -s "$RULES_FILE" ]; then
# Extract the full Cloudflare rules block (not just CIDRs)
awk -F'>' -v prefix="^${RULE_PREFIX}" 'BEGIN{RS="<"; ORS=""} NF>0 && $2 ~ prefix {print "<"$0}' "$RULES_FILE" > "$OLD_CF_RULES_FILE"
else
logger -sc -t "Cloudflare CIDR VPN Director Updater" -p user.notice "INFO: Rules file does not exist or is empty. Will create it."
: > "$OLD_CF_RULES_FILE"
fi
# Step 3: Generate the new block of Cloudflare rules.
NEW_CLOUDFLARE_RULES_BLOCK=""
counter=0
while IFS= read -r cidr; do
label="${RULE_PREFIX}${counter}"
NEW_CLOUDFLARE_RULES_BLOCK="${NEW_CLOUDFLARE_RULES_BLOCK}<1>${label}>${LOCAL_SUBNET}>${cidr}>${VPN_CLIENT_ID}"
counter=$((counter + 1))
done < "$NEW_CIDRS_FILE"
echo -n "$NEW_CLOUDFLARE_RULES_BLOCK" > "$NEW_CF_RULES_FILE"
# Step 4: Compare the new and existing Cloudflare rules blocks.
logger -sc -t "Cloudflare CIDR VPN Director Updater" -p user.notice "INFO: Comparing new and existing Cloudflare rules block..."
if cmp -s "$OLD_CF_RULES_FILE" "$NEW_CF_RULES_FILE"; then
logger -sc -t "Cloudflare CIDR VPN Director Updater" -p user.notice "INFO: No changes detected in Cloudflare rules. No update necessary. Exiting."
exit 0
fi
logger -sc -t "Cloudflare CIDR VPN Director Updater" -p user.notice "INFO: Changes detected. Proceeding with rule update."
# Step 5: Extract all non-Cloudflare rules.
CUSTOM_RULES_BLOCK=""
if [ -f "$RULES_FILE" ] && [ -s "$RULES_FILE" ]; then
CUSTOM_RULES_BLOCK=$(awk -F'>' -v prefix="^${RULE_PREFIX}" 'BEGIN{RS="<"; ORS=""} NF>0 && $2 !~ prefix {print "<"$0}' "$RULES_FILE")
fi
# Step 6: Combine custom rules with the new Cloudflare rules by simple concatenation.
FINAL_RULE_LIST="${CUSTOM_RULES_BLOCK}${NEW_CLOUDFLARE_RULES_BLOCK}"
# Step 7: Atomically update the rule list and apply changes.
logger -sc -t "Cloudflare CIDR VPN Director Updater" -p user.notice "INFO: Writing new rules to $RULES_FILE and applying changes."
echo -n "$FINAL_RULE_LIST" > "$RULES_FILE.tmp"
mv "$RULES_FILE.tmp" "$RULES_FILE"
service restart_vpndirector
logger -sc -t "Cloudflare CIDR VPN Director Updater" -p user.notice "SUCCESS: VPN Director rules updated successfully."
exit 0
@koolvn
Copy link
Author

koolvn commented Sep 2, 2025

Полезное для тех, кто хочет настроить роутинг трафика через VPN для определённых сайтов для всех устройств сети

Как настроить роутинг трафика через VPN по доменному имени

@JugglerLKR
Copy link

JugglerLKR commented Oct 27, 2025

Перестало работать на МТС Home. Есть какое-то решение, кроме NFQWS?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment