Skip to content

Instantly share code, notes, and snippets.

@koolvn
Last active June 21, 2025 16:34
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. Записываем файл в /jffs/scripts/update_cloudflare_rules.sh
  3. Делаем его запускаемым chmod +x /jffs/scripts/update_cloudflare_rules.sh
  4. Запускаем /jffs/scripts/update_cloudflare_rules.sh
  5. Если отработал без ошибок идём на вкладку VPN Director в UI роутера http://<ip:port>/Advanced_VPNDirector.asp Должно появиться что-то похожее: image
  6. Ставим автозапуск скрипта на 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"
# 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"
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 CIDRs.
logger -sc -t "Cloudflare CIDR VPN Director Updater" -p user.notice "INFO: Extracting existing Cloudflare CIDRs from $RULES_FILE..."
if [ -f "$RULES_FILE" ] && [ -s "$RULES_FILE" ]; then
# Correct parsing: Use '<' as the record separator (RS).
# A rule like "<1>label>>cidr>iface" becomes a record "1>label>>cidr>iface".
# Fields are separated by '>'. The CIDR is the 4th field ($4).
# The label is the 2nd field ($2). We match it against the prefix.
awk -F'>' -v prefix="^${RULE_PREFIX}" 'BEGIN{RS="<"} $2 ~ prefix {print $4}' "$RULES_FILE" > "$OLD_CIDRS_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."
touch "$OLD_CIDRS_FILE"
fi
# Step 3: Compare the old and new CIDR lists.
logger -sc -t "Cloudflare CIDR VPN Director Updater" -p user.notice "INFO: Comparing new and existing CIDR lists..."
sort "$NEW_CIDRS_FILE" -o "$NEW_CIDRS_FILE"
sort "$OLD_CIDRS_FILE" -o "$OLD_CIDRS_FILE"
if diff -q "$OLD_CIDRS_FILE" "$NEW_CIDRS_FILE" >/dev/null 2>&1; then
logger -sc -t "Cloudflare CIDR VPN Director Updater" -p user.notice "INFO: No changes detected. 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 4: Rebuild the entire rule list.
# A. Extract all non-Cloudflare rules.
CUSTOM_RULES_BLOCK=""
if [ -f "$RULES_FILE" ] && [ -s "$RULES_FILE" ]; then
# Use the same correct parsing logic to filter out our managed rules.
# ORS="" prevents newlines. We prepend '<' to reassemble the rule correctly.
CUSTOM_RULES_BLOCK=$(awk -F'>' -v prefix="^${RULE_PREFIX}" 'BEGIN{RS="<"; ORS=""} NF>0 && $2 !~ prefix {print "<"$0}' "$RULES_FILE")
fi
# B. 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}>>${cidr}>${VPN_CLIENT_ID}"
counter=$((counter + 1))
done < "$NEW_CIDRS_FILE"
# C. Combine custom rules with the new Cloudflare rules by simple concatenation.
FINAL_RULE_LIST="${CUSTOM_RULES_BLOCK}${NEW_CLOUDFLARE_RULES_BLOCK}"
# Step 5: 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 Nov 6, 2024

@Moskvitch
Copy link

Moskvitch commented Nov 21, 2024

Приветствую. VPN: Surfshark Wireguard, загрузил конфиг, включил клиента, запустил скрипт. Пишет connected, но все пролетает в старый добрый МТС. Лог ниже. Плиз хелп

Nov 21 23:57:25 custom_script: Running /jffs/scripts/wgclient-start (args: 1)
Nov 21 23:57:25 WireGuard: Starting client 1.
Nov 21 23:57:28 WireGuardClient: Starting junk-udp-hack script
Nov 21 23:57:28 WireGuardClient: Processing WG interface - wgc1
Nov 21 23:57:29 WireGuardClient: Message sent to WG server 172.93.153.69:51820 from client's port 52113
Nov 21 23:57:30 WireGuardClient: Message sent to WG server 172.93.153.69:51820 from client's port 52113
Nov 21 23:57:32 WireGuardClient: Message sent to WG server 172.93.153.69:51820 from client's port 52113
Nov 21 23:57:33 WireGuardClient: Done
Nov 21 23:57:44 rc_service: watchdog 2499:notify_rc stop_aae
Nov 21 23:57:44 rc_service: watchdog 2499:notify_rc start_mastiff
Nov 21 23:57:44 rc_service: waitting "stop_aae" via watchdog ...
Nov 21 23:57:45 Mastiff: init

@AirAlarm
Copy link

Приветствую. VPN: Surfshark Wireguard, загрузил конфиг, включил клиента, запустил скрипт. Пишет connected, но все пролетает в старый добрый МТС. Лог ниже. Плиз хелп

В VPN Director попробуйте принудительно выбрать WG туннель для конкретного устройства

@Moskvitch
Copy link

Есть контакт, спасибо. А функция, обзываемая в стоковой прошивке Apply to all devices, видимо, через /24?

@avesgit
Copy link

avesgit commented Dec 20, 2024

А андроида так можно подключить как то? Если не рассматривать что поднимается впн сервер на маршрутизаторе к нему подключать мобильный и пробрасывать маршруты до wireguard? хотя если только так то тоже хотелось бы знать как это сделать заранее благодарю

@JoyZzzzz
Copy link

@avesgit А что вам на андройде мешает использовать amneziawg или любой другой софт для обхода?

@avesgit
Copy link

avesgit commented Dec 20, 2024

@avesgitА что вам на андройде мешает использовать amneziawg или любое другое программное обеспечение для обхода?

поставил амнезию на сервер и андроид и не коннектится он, а вто этот рецепт выше все нормально работает и телек коннектится к ютубам

@JoyZzzzz
Copy link

@avesgit Если у вас на роутере этот способ работает, то и amneziawg должна работать на андройде.

@AlexeyAM
Copy link

Самое занятное оказалось вот здесь:

Кладём файл wgclient-start в /jffs/scripts/

Как это делать из-под Windows 10?
Bitvise не хочет запускать окно для передачи файлов. Я когда-то пользовался Линуксом на Амазоновской машине, там всё было нормально. Но на роутере, понятное дело, Линукс сильно усечённый.
Как копировать на него файлы с компа под Windows?

@jamal200591
Copy link

@AlexeyAM Попробуй WinSCP

@AirAlarm
Copy link

Самое занятное оказалось вот здесь:

Кладём файл wgclient-start в /jffs/scripts/

Как это делать из-под Windows 10? Bitvise не хочет запускать окно для передачи файлов. Я когда-то пользовался Линуксом на Амазоновской машине, там всё было нормально. Но на роутере, понятное дело, Линукс сильно усечённый. Как копировать на него файлы с компа под Windows?

Создать файл под nano, вставить код и сохранить.

cd /jffs/scripts/
nano wgclient-start 

@AlexeyAM
Copy link

Самое занятное оказалось вот здесь:
Кладём файл wgclient-start в /jffs/scripts/
Как это делать из-под Windows 10? Bitvise не хочет запускать окно для передачи файлов. Я когда-то пользовался Линуксом на Амазоновской машине, там всё было нормально. Но на роутере, понятное дело, Линукс сильно усечённый. Как копировать на него файлы с компа под Windows?

Создать файл под nano, вставить код и сохранить.

cd /jffs/scripts/
nano wgclient-start 

Ага. Спасибо. Как раз до nano добрался. Сначала хочу список заблокированных сайтов задействовать (выше в этой ветке мне присоветовали) и это через nano решаю.

@AlexeyAM
Copy link

@AlexeyAM Попробуй WinSCP

Вроде заработало. Спасибо.

@GPSMapper
Copy link

@avesgit А что вам на андройде мешает использовать amneziawg или любой другой софт для обхода?

Вот тут не очень понимаю. У меня wireguard сервер настроен на Асус роутере за границей, классический.
С другого роутере Асус в РФ цепляюсь к нему без проблем с помощью данного решения и далее впн директором настраиваю маршруты.

А вот с андроида с помощью amneziawg клиента не получается цепляться из РФ. Игрался с параметрами jc и не помогает, точнее иногда клиент проскакивает, но редко. Мегафон Москва.

Или для обфускации через amneziawg, необходимо чтобы и север был именно от амнезии допиленный?
Какие еще несложные элегантные способы могут быть поднимать тоннель с мегафона обходя блокировки dpi?

@AlexeyAM
Copy link

AlexeyAM commented Jan 3, 2025

Всё отлично работает, спасибо. Даже со скриптом Domain-based VPN Routing, он правда перезаписывает wgclient-start своими настройками, но достаточно в wgclient-start ручками дописать

sh /jffs/scripts/domain_vpn_routing.sh cron # domain_vpn_routing

sh /jffs/scripts/domain_vpn_routing.sh querypolicy all # domain_vpn_routing_queryall

И тогда всё будет работать вместе и ходить только на нужные адреса

А куда дописывать - в начало или в конец?

@JoyZzzzz
Copy link

JoyZzzzz commented Jan 3, 2025

А куда дописывать - в начало или в конец?

Так скрипт Domain-based VPN Routing автоматом дописывает в конец файла эти свои строчки ничего не трогая, то, что уже присутствует в wgclient-start.

@JoyZzzzz
Copy link

JoyZzzzz commented Jan 3, 2025

А вот с андроида с помощью amneziawg клиента не получается цепляться из РФ. Игрался с параметрами jc и не помогает, точнее иногда клиент проскакивает, но редко. Мегафон Москва.

Или для обфускации через amneziawg, необходимо чтобы и север был именно от амнезии допиленный?

На клиенте от AWG все работает без проблем и на Мегафоне и на МТС. Серверная часть простой WG

@GPSMapper
Copy link

На клиенте от AWG все работает без проблем и на Мегафоне и на МТС. Серверная часть простой WG

Странно, у меня именно с мобильного Мегафона Москва не работало. Точнее можно было соединиться, поменяв рандомно параметры пакетов, но только несколько раз, потом переставало работать с теми же параметрами.
А мтс без проблем, и домашний Билайн тоже.

@AlexeyAM
Copy link

AlexeyAM commented Jan 5, 2025

Не заработало. Пытался подключиться к Proton VPN. Может, дело в нём? Посоветуете проверенного провайдера? Который имеет демо режим хотя бы на пару дней. Чтобы всё запустить, а потом уже выбирать провайдера поосновательнее.

@JoyZzzzz
Copy link

JoyZzzzz commented Jan 5, 2025

Не заработало. Пытался подключиться к Proton VPN. Может, дело в нём?

Все работает, видимо что-то не нак настроили.

Посоветуете проверенного провайдера?

Покупаете VPS и настраиваете свой VPN так основательно как вам нужно.

@AlexeyAM
Copy link

AlexeyAM commented Jan 6, 2025

Не заработало. Пытался подключиться к Proton VPN. Может, дело в нём?

Все работает, видимо что-то не нак настроили.

stopped

Asus-Merlin пишет в интерфейсе "stopped" даже когда включено (активное положение radiobutton - тёмное).
Это с сервером проблемы или с роутером?
Настройки Proton просто скачиваются с конфигурационным файлом. Там не может быть что-то не так.

@JoyZzzzz
Copy link

JoyZzzzz commented Jan 6, 2025

@AlexeyAM
Copy link

AlexeyAM commented Jan 7, 2025

@AlexeyAM image

У меня тоже сначала работало, при чём без дополнительного скрипта от koolvn. Потом перестало. Как раз после установки koolvn и domain_vpn_routing. Может, они с Proton не дружат? Как очистить роутер вообще от всех дополнительных скриптов? В domain_vpn_routing есть команда uninstall, но не все его следы убираются. Во всяком случае в configs много чего остаётся.

@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

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