Транспорт udp2raw: 443 -> 25565/tcp
- 443 на сервере занят nginx (reverse-proxy Gitea totmaxim.ru); udp2raw в
faketcp через правило -a перехватил бы весь TCP на своём порту и поломал nginx
- server/client .service: -l/-r переведены на 25565
Клиент (Raspberry Pi):
- wg0.conf: PreUp-маршрут 95.174.102.77/32 via 192.168.200.1 dev usbnet
— устраняет петлю транспорта udp2raw при AllowedIPs=0.0.0.0/0
- nftables.conf: MSS-clamp для wlan0->wg0 (клиенты MTU 1500 vs туннель 1200)
Сервер (Ubuntu за NAT 192.168.31.163):
- wg0.conf: masquerade сужен до 10.66.66.0/24 в изолированной таблице wgfwd
(не конфликтует с Docker), MSS-clamp на входе в туннель, MTU=1200
README:
- фактическая топология (сервер за NAT, 95.174.102.77 = WAN роутера, проброс
25565 обязателен), таблица предусловий окружения и проверок
- шаг закрепления net.ipv4.ip_forward, диагностика петли и выхода в интернет
Данный проект содержит готовые конфигурации для развертывания отказоустойчивого VPN-туннеля между **Удаленным сервером (Ubuntu)** и **Raspberry Pi 4**.
Данный проект содержит конфигурации для развертывания отказоустойчивого VPN-туннеля между **Удаленным сервером (Ubuntu 24.04)** и **Raspberry Pi 4**.
Решение маскирует UDP-трафик WireGuard под стандартные TCP-пакеты (рукопожатие HTTPS на порт 443), что позволяет успешно обходить ограничения провайдеров, блокирующих или урезающих UDP-протокол на интерфейсе `usbnet`.
Решение маскирует 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` — это 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 не участвуют
### ⚠️ Обязательные требования к окружению (предусловия)
| 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=`
> **Внимание:** Перед запуском обязательно измените значение `"MY_CONFIDENTIAL_PASS"` в аргументе `-k` системных сервисов `udp2raw` на сервере и клиенте на ваш собственный секретный пароль.
Проверка соответствия ключей:
```
echo "--- SERVER PUBLIC KEY ---" && sudo cat server_public.key
echo "--- SERVER PRIVATE KEY ---" && sudo cat server_private.key
```
> ⚠️ **Важно:** Перед запуском служб измените дефолтный пароль `"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`):
wg genkey | tee server_private.key | wg pubkey > server_public.key
# Ключи Клиента (Raspberry Pi)
wg genkey | tee client_private.key | wg pubkey > client_public.key
# 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'
```
Важно: Замените плейсхолдеры _KEY_HERE во всех файлах конфигурации на сгенерированные строки. Также замените "SUPER_SECRET_PASSWORD" в сервисах udp2raw на ваш собственный секретный общий пароль.
Инструкция по развертыванию на СЕРВЕРЕ (Ubuntu)
Установите WireGuard:
```Bash
### Шаг 2.1. Установка WireGuard
```bash
sudo apt update && sudo apt install wireguard -y
```
Установите udp2raw:
Скачайте бинарный файл udp2raw_amd64 со страницы релизов проекта wangyu/udp2raw.
# Симметрично клиенту: транспорт идёт внутри faketcp, держим запас на оверхед
MTU = 1200
# Автоматический NAT для выхода клиентов в интернет через основной интерфейс enp2s0
PostUp = nft add table ip wg_nat; nft add chain ip wg_nat post { type nat hook postrouting priority srcnat\; policy accept\; }; nft add rule ip wg_nat post oifname "enp2s0" masquerade
PostDown = nft delete table ip wg_nat
# Всё хозяйство WG держим в отдельной nft-таблице wgfwd, чтобы:
# - не конфликтовать с правилами Docker/UFW в главных таблицах;
# - на PostDown снести одной командой (идемпотентно).
# NAT: маскарадим ТОЛЬКО подсеть туннеля (не трогаем docker и трафик хоста).
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
# MSS-clamp для пакетов, входящих В туннель (SYN-ACK от внешних серверов),
# чтобы large-TCP не «залипал» из-за MTU 1200 и заблокированного PMTUD.
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]
# Публичный ключ Raspberry Pi (из файла client_public.key)
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.