Skip to content

Instantly share code, notes, and snippets.

@ShutovKS
Created February 2, 2026 22:09
Show Gist options
  • Select an option

  • Save ShutovKS/0c4e780e4b54230b385e69454c7ba653 to your computer and use it in GitHub Desktop.

Select an option

Save ShutovKS/0c4e780e4b54230b385e69454c7ba653 to your computer and use it in GitHub Desktop.
WireGuard DPI Bypass (macOS) — pre-UDP before handshake

WireGuard DPI Bypass (macOS) — pre-UDP before handshake

Иногда провайдер/DPI распознаёт “первый” WireGuard handshake и начинает резать/душить соединение (часто выглядит как: handshake то появляется, то пропадает, либо “пакеты отправляются, но не приходят”).

Решение: перед включением туннеля отправить любой UDP-пакет на Endpoint с того же локального порта, который будет использовать WireGuard (ListenPort). Это “ломает” сигнатуру DPI на старте, и WireGuard обычно подключается стабильно.


Что нужно

  1. WireGuard конфиг (DE-3_Tunel.conf) с фиксированным ListenPort
  2. Скрипт pre-UDP (wg-preudp-mac.sh), который читает ListenPort и Endpoint прямо из конфига и отправляет пакет ":)"

1) Конфиг WireGuard (обязательно фиксируем ListenPort)

Пример DE-3_Tunel.conf:

# ============ WireGuard Client ============
[Interface]
PrivateKey = <CLIENT_PRIVATE_KEY>
Address = 10.8.0.3/32

# ВАЖНО: фиксируем локальный UDP порт (для обхода DPI и стабильности)
ListenPort = 57932

DNS = 1.1.1.1, 1.0.0.1

[Peer]
PublicKey = <SERVER_PUBLIC_KEY>
PresharedKey = <CLIENT_PSK>
Endpoint = <SERVER_PUBLIC_IP_OR_DOMAIN>:51820
AllowedIPs = 10.8.0.0/24
PersistentKeepalive = 25

Важно:

  • ListenPort должен быть постоянным (не “рандомным”), иначе pre-UDP не совпадёт с source-port WireGuard.
  • Endpoint должен быть host:port (или [ipv6]:port).

2) Скрипт wg-preudp-mac.sh

Скрипт:

  • читает ListenPort и Endpoint из .conf
  • отправляет любой UDP-пакет с source-port = ListenPort
  • сначала пробует nc (обычно есть на macOS), иначе использует python3
#!/usr/bin/env bash
set -euo pipefail

CFG="${1:-./DE-3_Tunel.conf}"
[[ -f "$CFG" ]] || { echo "Config not found: $CFG" >&2; exit 1; }

# Берём ListenPort и Endpoint из конфига
listen_port="$(awk -F'=' '/^[[:space:]]*ListenPort[[:space:]]*=/ {
  v=$2; sub(/#.*/,"",v); gsub(/[[:space:]]/,"",v); print v; exit
}' "$CFG")"

endpoint="$(awk -F'=' '/^[[:space:]]*Endpoint[[:space:]]*=/ {
  v=$2; sub(/#.*/,"",v); gsub(/[[:space:]]/,"",v); print v; exit
}' "$CFG")"

[[ -n "${listen_port:-}" ]] || { echo "ListenPort not found in config" >&2; exit 1; }
[[ -n "${endpoint:-}"   ]] || { echo "Endpoint not found in config"   >&2; exit 1; }

# Endpoint может быть host:port или [ipv6]:port
host=""
port=""
if [[ "$endpoint" =~ ^\[(.+)\]:(\d+)$ ]]; then
  host="${BASH_REMATCH[1]}"
  port="${BASH_REMATCH[2]}"
else
  host="${endpoint%:*}"
  port="${endpoint##*:}"
fi

# Отправляем любой UDP пакет с того же source-port (ListenPort)
# Сначала пробуем nc (обычно есть на macOS), иначе python3.
if command -v nc >/dev/null 2>&1; then
  # Важно: WireGuard должен быть отключён, чтобы порт был свободен.
  printf ":)" | nc -u -w 1 -p "$listen_port" "$host" "$port" >/dev/null 2>&1 || true
  echo "Sent pre-UDP via nc from :$listen_port to $host:$port"
else
  HOST="$host" PORT="$port" LISTEN_PORT="$listen_port" python3 - <<'PY'
import os, socket
host = os.environ["HOST"]
port = int(os.environ["PORT"])
listen_port = int(os.environ["LISTEN_PORT"])

ip = socket.gethostbyname(host)

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(("0.0.0.0", listen_port))
s.sendto(b":)", (ip, port))
s.close()

print(f"Sent pre-UDP via python from :{listen_port} to {host}:{port} (resolved {ip})")
PY
fi

Сделать исполняемым:

chmod +x ./wg-preudp-mac.sh

3) Использование (ручной запуск)

  1. Отключи туннель в WireGuard.app (важно: ListenPort должен быть свободен)

  2. Запусти pre-UDP:

./wg-preudp-mac.sh ./DE-3_Tunel.conf
  1. Сразу после этого включи туннель в WireGuard.app (Activate)

Примечания / Troubleshooting

  • Если случайно включил WireGuard до запуска скрипта: выключи туннель, подожди 30–60 секунд и повтори: pre-UDP → Activate.
  • Если провайдер режет UDP целиком (не только WireGuard), этот способ не поможет — тогда нужен WireGuard через TCP/443 (обёртка).
  • Если скрипт пишет, что ListenPort или Endpoint не найден — проверь, что они реально есть в .conf, и строки не закомментированы.

Security

Никогда не публикуй PrivateKey / PresharedKey в публичных gist/repo. Если ключи утекли — пересоздай конфиг и обнови peer на сервере.

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