Files
vpn-raspberry/README.md
Maxim 886ba62ea6 Исправление маршрутизации, порт 25565 и документирование окружения
Транспорт 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, диагностика петли и выхода в интернет
2026-07-07 13:16:50 +03:00

277 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

Файл документации (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.17172.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` — порт должен быть открыт (проброс на роутере сервера).