Skip to content
khromenokromanPublic

About

Простой VPN-туннель на C++17 для Linux.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

44 Commits

Folders and files

Repository files navigation

VPN

VPN preview

Простой VPN-туннель на C++17 для Linux.

Проект состоит из двух приложений:

  • vpn-server — серверная часть, поднимает TUN-интерфейс, настраивает NAT/forwarding и принимает UDP-пакеты от клиентов.
  • vpn-client — клиентская часть, поднимает TUN-интерфейс, перенаправляет трафик через UDP-туннель на сервер.

Важно: проект предназначен для Linux и требует запуска от root, так как использует /dev/net/tun, маршруты, iptables и настройку сетевых интерфейсов.

Возможности

  • Создание TUN-интерфейса.
  • UDP-туннель между клиентом и сервером.
  • Шифрование трафика через XChaCha20-Poly1305.
  • Проверка целостности и подлинности UDP-пакетов.
  • Настройка маршрута по умолчанию на клиенте через VPN.
  • Настройка NAT и forwarding на сервере.
  • Настраиваемые параметры через командную строку.
  • Логирование через syslog.
  • Увеличение буферов UDP-сокета для повышения производительности.

Как работает шифрование

Трафик шифруется на уровне UDP-пакетов:

TUN packet -> encrypt -> UDP -> decrypt -> TUN packet

По сети передаётся не открытый IP-пакет, а зашифрованный контейнер:

[magic: VPN1][nonce: 24 bytes][ciphertext + auth tag]

Используется алгоритм:

XChaCha20-Poly1305

Он обеспечивает:

  • конфиденциальность — содержимое пакетов нельзя прочитать без ключа;
  • целостность — изменение пакета приводит к ошибке расшифровки;
  • базовую аутентификацию — пакет может создать только сторона, знающая общий ключ.

В текущей версии нет защиты от replay-атак. То есть злоумышленник теоретически может повторно отправить ранее перехваченный корректный пакет. Для production-использования нужно добавить счётчики пакетов и anti-replay window.

Зависимости

Нужны:

  • C++17 compiler
  • CMake
  • Boost.Program_options
  • fmt
  • libsodium
  • pthread
  • iproute2
  • iptables
  • openssl — только для генерации ключа

Ubuntu / Debian

apt update
apt install -y \
    build-essential \
    cmake \
    libboost-program-options-dev \
    libsodium-dev \
    libfmt-dev \
    iproute2 \
    iptables \
    openssl

Сборка

mkdir build && cd build  
cmake -DCMAKE_BUILD_TYPE=Release ..
cmake --build .

После сборки бинарники будут примерно здесь:

build/src/server/vpn-server
build/src/client/vpn-client

Генерация ключа шифрования

Клиент и сервер должны использовать одинаковый общий ключ.

Сгенерировать ключ можно так:

openssl rand -base64 32

Пример результата:

CvEE3TRqqNNpmxy+/kk07Qk9912ZyCqUlv0ay5006KY=

Пример сохранения ключа в файл:

sudo mkdir -p /etc/myvpn
openssl rand -base64 32 | sudo tee /etc/myvpn/key
sudo chmod 600 /etc/myvpn/key

Посмотреть ключ:

sudo cat /etc/myvpn/key

Сейчас ключ передаётся через параметр --key. Это удобно для тестов, но не идеально с точки зрения безопасности, потому что аргументы процесса могут быть видны через ps. Более безопасный вариант — позже добавить параметр --key-file.

Запуск сервера

Минимальный пример:

sudo ./vpn-server \
    --port 1194 \
    --key 'CvEE3TRqqNNpmxy+/kk07Qk9912ZyCqUlv0ay5006KY='

Полный пример:

sudo ./vpn-server \
    --port 1194 \
    --mtu 1380 \
    --tun-name tun0 \
    --tun-ip 192.168.200.1 \
    --key 'CvEE3TRqqNNpmxy+/kk07Qk9912ZyCqUlv0ay5006KY='

Параметры сервера

Параметр Коротко Описание По умолчанию
--help -h Показать справку —
--port -p UDP-порт сервера обязательный
--mtu -m MTU TUN-интерфейса 1420
--tun-name -n Имя TUN-интерфейса tun0
--tun-ip -i IP-адрес TUN-интерфейса сервера 192.168.200.1
--key -k Общий ключ шифрования обязательный

Запуск клиента

Минимальный пример:

sudo ./vpn-client \
    --server <SERVER_PUBLIC_IP> \
    --port 1194 \
    --key 'CvEE3TRqqNNpmxy+/kk07Qk9912ZyCqUlv0ay5006KY='

Пример:

sudo ./vpn-client \
    --server 1.2.3.4 \
    --port 1194 \
    --mtu 1380 \
    --tun-name tun0 \
    --tun-ip 192.168.200.2 \
    --key 'CvEE3TRqqNNpmxy+/kk07Qk9912ZyCqUlv0ay5006KY='

Параметры клиента

Параметр Коротко Описание По умолчанию
--help -h Показать справку —
--server -s Публичный IP сервера обязательный
--port -p UDP-порт сервера обязательный
--mtu -m MTU TUN-интерфейса 1420
--tun-name -n Имя TUN-интерфейса tun0
--tun-ip -i IP-адрес TUN-интерфейса клиента 192.168.200.2
--key -k Общий ключ шифрования обязательный

Рекомендация по MTU

После включения шифрования каждый UDP-пакет становится больше примерно на:

4 bytes magic + 24 bytes nonce + 16 bytes auth tag = 44 bytes

Поэтому рекомендуется использовать MTU 1380:

--mtu 1380

Если оставить слишком большой MTU, возможна фрагментация UDP-пакетов и падение скорости.

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

На сервере:

ip addr show tun0
ip route
sudo iptables -t nat -L -n -v
sudo iptables -L FORWARD -n -v

На клиенте:

ip addr show tun0
ip route
ping 192.168.200.1

Проверка внешнего IP через VPN:

curl ifconfig.me

Логи

Проект пишет логи в syslog.

Просмотр логов через journalctl:

journalctl -f -t vpn-server
journalctl -f -t vpn-client

Важное ограничение безопасности

Трафик уже шифруется через XChaCha20-Poly1305, но проект всё ещё не является полноценным production-ready VPN.

Ограничения текущей версии:

  • нет защиты от replay-атак;
  • нет полноценного handshake;
  • нет автоматической ротации ключей;
  • общий ключ передаётся через аргумент командной строки;
  • нет разделения ключей по направлениям client -> server и server -> client.

Что стоит добавить позже:

  • --key-file вместо --key;
  • счётчики пакетов;
  • anti-replay window;
  • разные ключи на разные направления;
  • handshake для обмена сессионными ключами;
  • ротацию ключей.

About

Простой VPN-туннель на C++17 для Linux.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages