Файл документации (README.md) # Схема WireGuard + udp2raw Данный проект содержит конфигурации для развертывания отказоустойчивого VPN-туннеля между **Удаленным сервером (Ubuntu 24.04)** и **Raspberry Pi 4**. Решение маскирует UDP-трафик WireGuard под стандартные TCP-пакеты (режим `faketcp`), что позволяет успешно обходить ограничения провайдеров, блокирующих или урезающих UDP-протокол на интерфейсе `usbnet`. > **Порт входа — `25565/tcp`, а не `443`.** Порт `443` на сервере занят nginx (reverse-proxy для Gitea `totmaxim.ru`), и `udp2raw` в режиме `faketcp` (через правило `-a`) перехватил бы весь TCP на своём порту, поломав nginx. Поэтому транспорт вынесен на выделенный `25565/tcp`. --- ## 0. Справочные данные и пути проекта ### Архитектура и сетевые параметры * **Публичный вход сервера:** `95.174.102.77:25565` (TCP, `udp2raw`; `443` занят nginx/Gitea) * **Внутренний порт WireGuard (Сервер):** `127.0.0.1:51820` * **Внутренний порт udp2raw (Клиент RPi):** `127.0.0.1:51821` * **Подсеть VPN:** `10.66.66.0/24` (Сервер: `10.66.66.1`, Клиент: `10.66.66.2`) ### Фактическая топология (важно для маршрутизации) **Сервер (Ubuntu 24.04) — за NAT, НЕ имеет публичного IP напрямую:** * Внешний интерфейс: `enp2s0 = 192.168.31.163/24`, шлюз `192.168.31.1` * `95.174.102.77` — это WAN-адрес роутера `192.168.31.1`, а НЕ адрес самого сервера * На хосте работает Docker (бриджи `172.17–172.21.0.0/16`, `docker0`) со своими правилами nftables/iptables — поэтому WG-правила изолированы в отдельной таблице `wgfwd` и маскарадят **только** `10.66.66.0/24` **Клиент (Raspberry Pi 4) — роутер для локальной сети:** * Uplink (в интернет): `usbnet = 192.168.200.13/24`, шлюз и DNS `192.168.200.1` (мобильный канал; провайдер режет UDP → маскировка под TCP) * Downstream (клиенты): `wlan0 = 192.168.77.0/24` — их трафик уходит в интернет через туннель * Прочие интерфейсы (`eth0 10.1.1.33`, `eth1 192.168.2.10`) в схеме VPN не участвуют ### ⚠️ Обязательные требования к окружению (предусловия) | # | Требование | Где | Проверка | |---|-----------|-----|----------| | 1 | **Проброс порта** `TCP 25565 → 192.168.31.163:25565` на роутере `95.174.102.77` | Роутер сервера | с клиента: `nc -vz 95.174.102.77 25565` | | 2 | `net.ipv4.ip_forward = 1` (закрепить в `/etc/sysctl.d/`) | Сервер + Клиент | `sysctl net.ipv4.ip_forward` | | 3 | Порт `25565/tcp` на хосте свободен; `443` оставить за nginx (Gitea) | Сервер | `sudo ss -ltnp 'sport = :25565'` | | 4 | Одинаковый пароль `-k` в обеих службах `udp2raw` | Сервер + Клиент | сверить `.service` | | 5 | Маршрут `95.174.102.77/32 via 192.168.200.1 dev usbnet` при поднятом `wg0` | Клиент | `ip route get 95.174.102.77` (должен быть `dev usbnet`, НЕ `wg0`) | > **Почему требование #5 критично:** на клиенте `AllowedIPs = 0.0.0.0/0`, поэтому `wg-quick` заворачивает весь трафик в `wg0`. Без закреплённого маршрута сам транспорт `udp2raw` (пакеты к `95.174.102.77:25565`) тоже уйдёт в `wg0` — получится **петля**, и туннель порвётся. Маршрут добавляется автоматически через `PreUp` в `client/wg0.conf`. ### Актуальные ключи WireGuard * **Сервер (`95.174.102.77`):** * Public Key: `dVIwnwxkjan/K278vzhOjp5A79N98j0O1zsYqT24qzs=` * Private Key: `KMcPBI6LAY/NC1zFNYopsvNXqQ8w8ssluDj4yOh3skk=` * **Клиент (Raspberry Pi 4):** * Public Key: `WWFhoYfIgIhGOsvdJ/F9eWx7hPksrV6riiqo5lFPExI=` * Private Key: `eKiGDY62/9pgFrwzoNIb7URRLPgEHC1W7zHwIIDYQVw=` > ⚠️ **Важно:** Перед запуском служб измените дефолтный пароль `"MY_CONFIDENTIAL_PASS"` в аргументе `-k` в файлах `.service` на ваш собственный секретный пароль. Он должен быть одинаковым везде. --- ## 1. Спецификация релиза udp2raw * **Ссылка для скачивания архива:** `https://github.com/wangyu-/udp2raw/releases/download/20230206.0/udp2raw_binaries.tar.gz` * **Версия:** 20230206.0 При распаковке архива (`tar -xvf`) используются только два конкретных файла: 1. `udp2raw_amd64` — устанавливается на **Сервер** (архитектура x86_64). 2. `udp2raw_arm_asm_aes` — устанавливается на **Raspberry Pi 4** (оптимизированный ARM-бинарник). --- ## 2. Пошаговое развертывание на СЕРВЕРЕ (Ubuntu) Выполняется в терминале сервера (`totserver@95.174.102.77`): ### Шаг 2.0. Подготовка окружения (проброс порта + форвардинг) ```bash # 1) Убедитесь, что на роутере 95.174.102.77 проброшен TCP 25565 -> 192.168.31.163:25565 # 2) Включаем и ЗАКРЕПЛЯЕМ форвардинг пакетов (wg-quick сам его НЕ включает): echo 'net.ipv4.ip_forward = 1' | sudo tee /etc/sysctl.d/99-wg.conf sudo sysctl --system # 3) Проверяем, что порт 25565 на хосте свободен (udp2raw слушает 0.0.0.0:25565). # Порт 443 ДОЛЖЕН оставаться за nginx (Gitea) — udp2raw его не трогает: sudo ss -ltnp 'sport = :25565' ``` ### Шаг 2.1. Установка WireGuard ```bash sudo apt update && sudo apt install wireguard -y Шаг 2.2. Скачивание и сборка udp2raw Bash mkdir -p ~/download && cd ~/download wget [https://github.com/wangyu-/udp2raw/releases/download/20230206.0/udp2raw_binaries.tar.gz](https://github.com/wangyu-/udp2raw/releases/download/20230206.0/udp2raw_binaries.tar.gz) tar -xvf udp2raw_binaries.tar.gz # Копируем x86_64 бинарник в системный путь и даем права sudo cp udp2raw_amd64 /usr/local/bin/udp2raw sudo chmod +x /usr/local/bin/udp2raw Шаг 2.3. Создание конфигурационных файлов Создайте конфиг WireGuard: sudo nano /etc/whiteguard/wg0.conf (или /etc/wireguard/wg0.conf) Ini, TOML [Interface] Address = 10.66.66.1/24 ListenPort = 51820 PrivateKey = KMcPBI6LAY/NC1zFNYopsvNXqQ8w8ssluDj4yOh3skk= MTU = 1200 # Изолированная таблица wgfwd: masquerade ТОЛЬКО 10.66.66.0/24 (не конфликтует с Docker) # + MSS-clamp на входе в туннель. PostDown сносит всё одной командой. PostUp = nft add table ip wgfwd PostUp = nft add chain ip wgfwd postrouting { type nat hook postrouting priority 100 \; policy accept \; } PostUp = nft add rule ip wgfwd postrouting ip saddr 10.66.66.0/24 oifname "enp2s0" masquerade PostUp = nft add chain ip wgfwd mangle { type filter hook forward priority -150 \; policy accept \; } PostUp = nft add rule ip wgfwd mangle oifname "wg0" tcp flags syn tcp option maxseg size set rt mtu PostDown = nft delete table ip wgfwd [Peer] PublicKey = WWFhoYfIgIhGOsvdJ/F9eWx7hPksrV6riiqo5lFPExI= AllowedIPs = 10.66.66.2/32 Создайте службу демона udp2raw: sudo nano /etc/systemd/system/udp2raw-server.service Ini, TOML [Unit] Description=udp2raw Server (FakeTCP) After=network.target [Service] Type=simple User=root ExecStart=/usr/local/bin/udp2raw -s -l 0.0.0.0:25565 -r 127.0.0.1:51820 -k "MY_CONFIDENTIAL_PASS" --raw-mode faketcp -a Restart=always RestartSec=5 [Install] WantedBy=multi-user.target Шаг 2.4. Запуск служб на сервере Bash sudo systemctl daemon-reload sudo systemctl enable --now udp2raw-server sudo systemctl enable --now wg-quick@wg0 3. Пошаговое развертывание на КЛИЕНТЕ (Raspberry Pi 4) Выполняется в терминале малинки (user@raspberrypi): Шаг 3.1. Установка WireGuard Bash sudo apt update && sudo apt install wireguard -y Шаг 3.2. Доставка бинарника udp2raw Если малинка имеет доступ к интернету, скачайте архив прямо на неё: Bash mkdir -p ~/download && cd ~/download wget [https://github.com/wangyu-/udp2raw/releases/download/20230206.0/udp2raw_binaries.tar.gz](https://github.com/wangyu-/udp2raw/releases/download/20230206.0/udp2raw_binaries.tar.gz) tar -xvf udp2raw_binaries.tar.gz # Переносим специализированный ARM-бинарник в системный путь sudo cp udp2raw_arm_asm_aes /usr/local/bin/udp2raw sudo chmod +x /usr/local/bin/udp2raw Шаг 3.3. Настройка сетевого экрана (nftables) Учитывая строгую политику policy drop на вашей Raspberry Pi, откройте текущие правила: Bash sudo nano /etc/nftables.conf Добавьте/разрешите следующие строки в соответствующие таблицы: В table inet filter -> chain input: Code snippet iifname "lo" accept iifname "wg0" accept В table inet filter -> chain forward: Code snippet iifname "wlan0" oifname "wg0" accept iifname "wg0" oifname "wlan0" ct state established,related accept # MSS-clamp: клиенты (MTU 1500) не знают про туннель 1200 -> иначе крупный TCP залипает iifname "wlan0" oifname "wg0" tcp flags syn tcp option maxseg size set rt mtu В table ip nat -> chain postrouting: Code snippet ip saddr 192.168.77.0/24 oifname "wg0" masquerade Примените изменения: sudo nft -f /etc/nftables.conf Шаг 3.4. Создание конфигурационных файлов Создайте конфиг WireGuard: sudo nano /etc/wireguard/wg0.conf Ini, TOML [Interface] Address = 10.66.66.2/24 PrivateKey = eKiGDY62/9pgFrwzoNIb7URRLPgEHC1W7zHwIIDYQVw= MTU = 1200 # КРИТИЧНО (анти-петля): маршрут к серверу через реальный uplink ДО поднятия default в wg0. # 192.168.200.1 — шлюз usbnet; при смене канала поправить адрес здесь. PreUp = ip route replace 95.174.102.77/32 via 192.168.200.1 dev usbnet PostDown = ip route del 95.174.102.77/32 2>/dev/null || true [Peer] PublicKey = dVIwnwxkjan/K278vzhOjp5A79N98j0O1zsYqT24qzs= Endpoint = 127.0.0.1:51821 AllowedIPs = 0.0.0.0/0 PersistentKeepalive = 25 Создайте службу демона udp2raw: sudo nano /etc/systemd/system/udp2raw-client.service Ini, TOML [Unit] Description=udp2raw Client (FakeTCP) After=network.target [Service] Type=simple User=root ExecStart=/usr/local/bin/udp2raw -c -l 127.0.0.1:51821 -r 95.174.102.77:25565 -k "MY_CONFIDENTIAL_PASS" --raw-mode faketcp -a Restart=always RestartSec=5 [Install] WantedBy=multi-user.target Шаг 3.5. Запуск служб на клиенте Bash sudo systemctl daemon-reload sudo systemctl enable --now udp2raw-client sudo systemctl enable --now wg-quick@wg0 4. Диагностика и проверка статуса При возникновении неполадок проверяйте компоненты строго по цепочке от нижнего уровня к верхнему: 1. Проверка работоспособности FakeTCP (udp2raw) На клиенте: sudo systemctl status udp2raw-client На сервере: sudo systemctl status udp2raw-server Критерий успеха: Строка состояния [ready] в логах сервиса и отсутствие циклических перезапусков. 2. Проверка туннеля WireGuard На любом из устройств: sudo wg show Критерий успеха: Наличие строчки latest handshake: X seconds ago (данные должны обновляться и не сбрасываться). 3. Проверка сетевого уровня (Пинг) С Raspberry Pi запустите: ping 10.66.66.1 Если пинг идет, но интернета на устройствах за малинкой (wlan0) нет — перепроверяйте синтаксис правил в /etc/nftables.conf и masquerade на сервере. 4. Проверка отсутствия петли (при поднятом wg0) На клиенте: `ip route get 95.174.102.77` Критерий успеха: маршрут идёт через `dev usbnet` (шлюз 192.168.200.1), а НЕ через `dev wg0`. Если видите `dev wg0` — не отработал `PreUp` из `wg0.conf`, транспорт закольцован. 5. Проверка выхода в интернет через туннель С устройства за малинкой (192.168.77.0/24): `curl -s https://ifconfig.me` Критерий успеха: возвращается публичный IP канала сервера (сети `192.168.31.1`), а не мобильного канала клиента. 6. Доступность публичного входа (проброс 25565) С клиента: `nc -vz 95.174.102.77 25565` — порт должен быть открыт (проброс на роутере сервера).