Кастомная имплементация виртуальной частной сети (VPN) под Linux. Представляет собой строго учебный проект; не предназначена для обхода блокировок и коммерческого использования.
Общая идея протокола была вдохновлена Wireguard, но реализована полностью с нуля. Из зависимостей в основном только криптография и библиотека songgao/water для использования TUN-интерфейсов.
Протокол использует UDP в качестве транспорта, по которому передаются пользовательские пакеты. Каждый пакет включает в себя 17-байтовый header и payload произвольного размера. Payload может быть зашифрованным в зависимости от типа пакета; header всегда открыт, что впрочем не является большой проблемой.
Первый и главный этап соединения — рукопожатие (handshake). В нём производится аутентификация клиента по переданному публичному ключу и создание новой сессии. На основе своего приватного ключа и полученного публичного другой стороны на клиенте и сервере вычисляется общий секрет с помощью ECDH. В дальнейшем он используется для симметричного шифрования полезной нагрузки пакетов по AES-GCM.
После установки зашифрованного соединения клиент и сервер могут начать пересылать друг другу IPv4-пакеты. Каждый входящий пакет декодируется, а полезная нагрузка расшифровывается по вычисленному ключу и переданному в header nonce. Исходящие пакеты претерпевают обратную процедуру.
Ввиду своей непопулярности протокол не детектируется системами DPI, и при неправильном выборе локации сервера могут проявиться некоторые побочные явления. Так что ни в коем случае не размещайте свой сервер за рубежом, чтобы случайно не получить доступ к заблокированным ресурсам. Используйте данное ПО лишь в учебных и демонстрационных целях.
Требования: Linux, iptables, Golang >= 1.26.2, IPv4-сеть, root-права на клиенте и на сервере.
- Сгенерируйте по паре из публичного/приватного ключа для клиента и для сервера.
- Запишите приватные ключи в client.json и server.json соответственно. Добавьте публичный ключ клиента в список allowedIPs (server.json), присвоив адрес из диапазона 10.0.5.0/24.
- На сервере:
go run server/main.go --config server.json - На клиенте:
go run client/main.go --config client.json
Убедитесь, что все значения правильно соотносятся в обеих конфигурационных файлах.