Skip to content

Instantly share code, notes, and snippets.

@koolvn
Last active July 17, 2025 11:29
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_rule s.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="WGC2"
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.
logger -sc -t "Cloudflare CIDR VPN Director Updater" -p user.notice "INFO: Fetching latest Cloudflare IPv4 CIDRs..."
if ! curl -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
@JoyZzzzz
Copy link

JoyZzzzz commented Jan 7, 2025

Domain_vpn_routing в скрипт wgclient-start добавляет всего 2 строчки. Все остальные файлы после uninstall пустые и никак не влияют на работу, можете их просто удалить.

@AlexeyAM
Copy link

AlexeyAM commented Jan 8, 2025

В том то и дело, что они не пустые у меня остаются.

Domain_vpn_routing в скрипт wgclient-start добавляет всего 2 строчки.

А имеет значение, в каком месте они? Перед скриптом koolvn или после?

Все остальные файлы после uninstall пустые и никак не влияют на работу, можете их просто удалить.

В том-то и дело, что они не пустые у меня остаются. В них после удаления вообще ничего не меняется. Хотя удаляю не вручную, а командой из меню. И после выполнения команды ни о никаких ошибках сообщения не появляются.

@ilyas-i
Copy link

ilyas-i commented Apr 3, 2025

Asus TUF-AX3000v2 прошивка merlin 3004.388.8_4-gnuton1. Скрипт работает. Благодарю от души!

@Andrew-SPb
Copy link

@koolvn
нужно ли вносить в скрипт какие-то изменения касательно интерфейсов, если у меня два впн-клиента? (wgc1 и wgc2)

@boroda30rus1
Copy link

/jffs/scripts/ где найти эту папку?как это сделать опишите пожалуйста подробнее

@Andrew-SPb
Copy link

/jffs/scripts/ где найти эту папку?как это сделать опишите пожалуйста подробнее

для, начала подключиться к роутеру, например, с помощью WinSCP
а дальше...
024350

@koolvn
Copy link
Author

koolvn commented Apr 14, 2025

@koolvn нужно ли вносить в скрипт какие-то изменения касательно интерфейсов, если у меня два впн-клиента? (wgc1 и wgc2)

Привет! По дефолту скрипт будет отрабатывать для любого интерфейса (и это не должно вызвать никаких проблем) при его включении. Номер интерфейса передаётся в 26ой строчке
По сути, роутер запускает команду /jffs/scripts/wgclient-start 1 где 1 - это номер интерфейса. (Можно выполнить её самому руками)
image

@kitzik
Copy link

kitzik commented Jun 24, 2025

Спасибо огромное за update_cloudflare_rules.sh Работает отлично на ASUS RT-AX68U. Ругался только на параметр логгера

logger: invalid option -- 'c'
BusyBox v1.37.0 (2025-06-01 14:50:09 UTC) multi-call binary.

Usage: logger [-s] [-t TAG] [-p PRIO] [MESSAGE]

Write MESSAGE (or stdin) to syslog

        -s      Log to stderr as well as the system log
        -t TAG  Log using the specified tag (defaults to user name)
        -p PRIO Priority (number or FACILITY.LEVEL pair)

Убрал его, и всё заработало.

@koolvn
Copy link
Author

koolvn commented Jul 2, 2025

@kitzik Спасибо за информацию и отзыв!
Видимо этот параметр не во всех версиях прошивки есть. У меня на данный момент 3006.102.4
image

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