8000
Skip to content

Latest commit

 

History

20 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Lightweight VPN

Легковесный VPN сервер и клиент на Go с современной криптографией и защитой от DPI.

Особенности

  • Реальное VPN подключение через TUN интерфейс (видно ОС как сетевое подключение)
  • 🔐 Современная криптография (как в WireGuard):
    • Noise Protocol (Noise_IK_25519_ChaChaPoly_BLAKE2s) для handshake
    • Curve25519 статические ключи-идентичности (аутентификация по публичным ключам)
    • ChaCha20-Poly1305 для шифрования трафика
    • Perfect Forward Secrecy за счёт эфемерных ключей в каждом handshake
    • Периодический rehandshake (rekey) — ключи сессии ротируются без разрыва трафика (как в WireGuard)
  • 🔑 Аутентификация по ключам: клиент пинит публичный ключ сервера, сервер сверяет ключ клиента со списком разрешённых (allowlist)
  • 🛡️ Anti-replay (sequence number + sliding window, RFC 6479) и per-source-IP rate limiting против DoS
  • 🚀 UDP транспорт - устойчивость к потерям пакетов
  • 🎭 DPI Obfuscation - защита от глубокой проверки пакетов:
    • Случайный префикс в каждом пакете
    • Случайный padding для скрытия размера
    • Шифрование делает содержимое неотличимым от случайных данных
  • 🔄 Кросс-платформенность: Linux и Windows

Архитектура

┌─────────────┐                        ┌─────────────┐
│   Client    │                        │   Server    │
│             │                        │             │
│  TUN iface  │◄──────────────────────►│  TUN iface  │
│  (10.0.0.2) │   Encrypted UDP        │  (10.0.0.1) │
│             │   Noise + ChaCha20     │             │
└─────────────┘   + DPI Obfuscation    └─────────────┘

Криптография

Handshake (Noise Protocol)

Используется паттерн Noise_IK с набором примитивов WireGuard (25519 / ChaChaPoly / BLAKE2s):

  1. У каждой стороны есть долговременная статическая пара ключей Curve25519 («идентичность»). Приватный ключ хранится в файле (-key-file), публичный — это «сертификат».
  2. Клиент заранее знает и пинит публичный ключ сервера (-server-key). Это аутентифицирует сервер и закрывает MITM — без приватного ключа сервер подменить нельзя.
  3. Статический ключ клиента передаётся серверу внутри зашифрованного handshake; сервер сверяет его с allowlist (-peers) — так публичные ключи заменяют общий PSK.
  4. Из handshake выводятся два симметричных ключа (по одному на направление) с Perfect Forward Secrecy (эфемерные ключи уникальны для каждой сессии).

Всего 2 сообщения (один round-trip), как в текущем дизайне.

Периодический rehandshake (rekey)

Клиент (инициатор) раз в -rekey (по умолчанию 120 c) повторяет handshake → обе стороны получают свежие эфемерные ключи. Прежняя сессия остаётся валидной короткое grace-окно (~30 c) только для расшифровки пакетов «в полёте», так что ротация ключей не рвёт трафик (в e2e-тесте — 0% потерь на 6+ ротациях).

Шифрование трафика

  • ChaCha20-Poly1305 (AEAD), отдельный ключ на каждое направление.
  • Каждый data-кадр: [counter(8)] [ciphertext] [tag(16)], где counter — это nonce шифра (монотонный, гарантирует уникальность nonce в сессии).

Защита от replay

  • На приёме — sequence number + скользящее окно 1024 (RFC 6479): каждый counter принимается ровно один раз; дубликаты и устаревшие кадры отбрасываются.
  • Counter ставится в nonce только после успешной аутентификации, так что подделанный counter не сдвигает окно.

DoS protection

  • Per-source-IP token-bucket на handshake (≈5/с, burst 10 на IP, до 4096 IP)
    • глобальный backstop (≈100/с, burst 200). Дешёвая Noise-проверка отсеивает неаутентичные пакеты до дорогих операций.

Формат пакета (внешний слой / обфускация)

[random_prefix(8)] [type(1)] [length(2)] [payload] [random_padding(0-64)]

payload для data-кадров — это [counter(8)] [ciphertext] [tag(16)], для handshake — сырое сообщение Noise.

Требования

Linux (WSL2/Ubuntu)

sudo apt update
sudo apt install -y build-essential golang-1.21

Windows

  • Go 1.21+
  • Драйвер TAP-Windows (для TUN интерфейса)

Сборка

Сервер (Linux/WSL2)

make deps
make server

Клиент для Linux

make client

Клиент для Windows

make windows-client

Бинарник появится в bin/vpn-client.exe и его можно перенести на Windows.

Сборка всех платформ

make all-platforms

Запуск

0. Генерация ключей (один раз)

# Ключ сервера: приватный → server.key, публичный → stdout
SERVER_PUB=$(./bin/keygen -out server.key)

# Ключ клиента: приватный → client.key, публичный → stdout
CLIENT_PUB=$(./bin/keygen -out client.key)

echo "server pub: $SERVER_PUB"   # его пинит клиент (-server-key)
echo "client pub: $CLIENT_PUB"   # его добавляет сервер в allowlist (-peers)

Сервер и клиент также создают *.key автоматически при первом запуске, если файла нет, и печатают свой публичный ключ в лог. *.key в .gitignore.

На сервере (WSL2/Linux)

# Требуется root для создания TUN интерфейса
sudo ./bin/vpn-server -listen 0.0.0.0:51820 -tun-ip 10.0.0.1/24 -peer-ip 10.0.0.2 \
     -key-file server.key -peers "$CLIENT_PUB"

Параметры:

  • -listen - адрес для прослушивания UDP (по умолчанию 0.0.0.0:51820)
  • -tun-ip - IP адрес TUN интерфейса на сервере (по умолчанию 10.0.0.1/24)
  • -peer-ip - IP адрес клиента (по умолчанию 10.0.0.2)
  • -mtu - MTU для TUN интерфейса (по умолчанию 1420)
  • -key-file - файл со статическим ключом сервера (создаётся, если нет)
  • -peers - список разрешённых публичных ключей клиентов (base64, через запятую)
  • -peers-file - то же из файла (по ключу на строку, # — комментарии). Если allowlist пуст — пускается любой криптографически валидный клиент (warning).

На клиенте (Windows/Linux)

# Linux
sudo ./bin/vpn-client -server 172.26.171.205:51820 -tun-ip 10.0.0.2/24 -peer-ip 10.0.0.1 \
     -key-file client.key -server-key "$SERVER_PUB"

# Windows (запустить от имени администратора)
# При первом запуске автоматически скачает wintun.dll и установит драйвер!
vpn-client.exe -server 172.26.171.205:51820 -tun-ip 10.0.0.2/24 -peer-ip 10.0.0.1 ^
     -key-file client.key -server-key <SERVER_PUB>

Windows особенности:

  • ✅ Использует Wintun - современный драйвер от создателей WireGuard
  • Автоматически скачивает wintun.dll при первом запуске
  • Автоматически устанавливает драйвер (не нужны TAP-Windows или OpenVPN!)
  • ✅ Требуется только права Администратора

См. подробную инструкцию: WINTUN_GUIDE.md

Параметры:

  • -server - адрес сервера (по умолчанию 172.26.171.205:51820)
  • -tun-ip - IP адрес клиента (по умолчанию 10.0.0.2/24)
  • -peer-ip - IP адрес сервера в VPN (по умолчанию 10.0.0.1)
  • -mtu - MTU (по умолчанию 1420)
  • -key-file - файл со статическим ключом клиента (создаётся, если нет)
  • -server-key - обязательный публичный ключ сервера (base64) для пиннинга
  • -rekey - интервал периодического rehandshake (по умолчанию 120s; 0 — выкл.)

Проверка работы

На сервере

# Проверить TUN интерфейс
ip addr show vpn0

# Пинг клиента
ping 10.0.0.2

На клиенте

# Linux
ip addr show vpn0
ping 10.0.0.1

# Windows
ipconfig
ping 10.0.0.1

Логи

Сервер и клиент выводят подробные логи:

  • Создание TUN интерфейса
  • Статические публичные ключи (свой и пира)
  • Установка аутентифицированной Noise-сессии
  • Отклонённые/неавторизованные handshake
  • Ошибки шифрования/дешифрования

Безопасность

Текущая реализация

  • Noise_IK handshake (Curve25519 + ChaCha20-Poly1305 + BLAKE2s) — как в WireGuard
  • Аутентификация по публичным ключам: пиннинг ключа сервера (анти-MITM) + allowlist ключей клиентов (вместо общего PSK)
  • Perfect Forward Secrecy — эфемерные ключи в каждом handshake
  • Периодический rehandshake — ротация ключей сессии без разрыва трафика
  • Replay protection (sequence number + sliding window, RFC 6479)
  • DoS protection — per-source-IP rate limiting + глобальный backstop
  • ✅ DPI obfuscation — случайный префикс/padding

Возможные улучшения

  • Сертификаты/CA вместо ручного allowlist публичных ключей
  • Более сложная обфускация (имитация HTTPS/DNS)

Устранение проблем

Linux: Permission denied при создании TUN

# Нужны root права
sudo ./bin/vpn-server

Windows: TUN интерфейс не создается

Firewall блокирует UDP

# Linux
sudo ufw allow 51820/udp

# Windows - добавьте правило в Windows Firewall для порта 51820 UDP

Структура проекта

.
├── cmd/
│   ├── server/          # VPN сервер
│   ├── client/          # VPN клиент
│   └── keygen/          # Генератор статических ключей-идентичностей
├── pkg/
│   ├── session/         # Noise_IK handshake, транспорт, анти-replay, идентичности + тесты
│   ├── transport/       # UDP транспорт с обфускацией + тесты/фаззинг
│   ├── ipparse/         # Разбор IPv4 для логов (общий для server/client) + тесты
│   ├── ratelimit/       # Token-bucket + per-IP лимитер (анти-DoS) + тесты
│   └── tun/             # TUN интерфейс (Linux/Windows)
├── scripts/
│   └── integration-test.sh  # End-to-end тест через network namespaces
├── Makefile            # Сборка и тесты
└── README.md           # Документация

Тестирование

Юнит-тесты (с детектором гонок)

make test          # go test ./...
make test-race     # go test -race ./...

Покрывают: полный Noise_IK handshake и транспорт, защиту от MITM (неверный пиннинг ключа сервера), отклонение replay/подделки, out-of-order в окне, ротацию ключей (rehandshake) с grace-окном, round-trip идентичностей, sliding-window фильтр, per-IP rate limiting, сериализацию пакетов и фаззинг Unmarshal, разбор IPv4/ICMP (в т.ч. с IP-опциями).

End-to-end интеграционный тест

Поднимает сервер и клиент в двух изолированных network namespaces, соединённых veth, и проверяет реальное прохождение ICMP через зашифрованный туннель в обе стороны, отсутствие открытого payload на проводе (tcpdump), периодический rehandshake (0% потерь на нескольких ротациях ключей), а также негативные сценарии: неавторизованный клиент (нет в allowlist) и MITM (клиент пинит неверный ключ сервера) — оба должны быть отклонены:

make integration-test       # требует root (sudo)
# или напрямую:
sudo bash scripts/integration-test.sh

Производительность

  • Throughput: ChaCha20-Poly1305 даёт стабильную скорость даже без AES-NI.
  • Latency: +1-2ms overhead от шифрования.
  • CPU: один Noise-handshake на подключение; data-path — потоковый AEAD.

Лицензия

MIT

Вклад

Pull requests приветствуются! Особенно интересны улучшения:

  • Более продвинутая обфускация
  • Поддержка нескольких клиентов на сервере
  • Web UI для управления
  • Маршрутизация трафика

About

Лёгкий VPN на Go: TUN-интерфейс, Curve25519 ECDH + AES-256-GCM, ротация ключей, UDP-транспорт, анти-DPI обфускация (рандомный префикс/padding).

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages

0