0.1.1
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
Server Side Public License (SSPL) v1.0
|
||||
|
||||
Copyright © 2025 Roman Nikolskii (romb.intu@gmail.com)
|
||||
|
||||
NOTICE: This license imposes commercial use restrictions for offering this software as a service. Consult legal advice before deployment.
|
||||
1. Definitions
|
||||
"Software": The godpn project and its derivative works.
|
||||
"Service": Any offering allowing third parties to interact with the Software’s functionality via a network.
|
||||
|
||||
2. Permissions
|
||||
|
||||
Subject to compliance with this license, you are granted:
|
||||
✅ Use: Run the Software for any purpose, private or commercial.
|
||||
✅ Modification: Create derivative works.
|
||||
✅ Distribution: Redistribute source or object code.
|
||||
3. Restrictions
|
||||
|
||||
❌ No Commercial SaaS: You may not offer the Software (or modifications) as a publicly available Service without:
|
||||
Open-sourcing all modifications and infrastructure code under SSPL, or
|
||||
Obtaining a commercial license from the copyright holder (Roman Nikolskii).
|
||||
|
||||
❌ No Circumvention: You may not bypass technical enforcement mechanisms.
|
||||
4. Service Provider Requirements
|
||||
|
||||
If you operate a Service using this Software, you must:
|
||||
Disclose Source: Make available to all users:
|
||||
The complete source code of the Software, including all modifications.
|
||||
The source code of all system components needed to run the Service (e.g., management software, APIs).
|
||||
Offer License: Provide instructions for users to obtain the source under SSPL.
|
||||
|
||||
5. Attribution
|
||||
|
||||
All copies must retain:
|
||||
This license file.
|
||||
Copyright notices in source files.
|
||||
|
||||
6. Disclaimer
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR DAMAGES ARISING FROM ITS USE.
|
||||
7. License Compatibility
|
||||
Third-party dependencies (e.g., go-shadowsocks2) remain under their original licenses (e.g., Apache 2.0).
|
||||
This license applies only to original code authored by Roman Nikolskii in the godpn project.
|
||||
|
||||
8. Contact
|
||||
|
||||
For commercial licensing inquiries:
|
||||
📧 Roman Nikolskii – romb.intu@gmail.com
|
||||
@@ -0,0 +1,77 @@
|
||||
# GODPN - Decentralized Private Network
|
||||
|
||||
## 🏛️ Архитектура
|
||||
1. Компоненты системы
|
||||
|
||||
1.1 Трекер (Coordinator Server)
|
||||
|
||||
Роль: Управляет пирами, собирает метрики, назначает оптимальные подключения.
|
||||
|
||||
Функции:
|
||||
|
||||
Регистрирует пиры (IP, порт, доступная пропускная способность, геолокация).
|
||||
Собирает статистику: скорость, пинг, трафик.
|
||||
Ранжирует пиры для клиентов (по скорости/стабильности).
|
||||
Начисляет монеты за трафик, списывает их у клиентов.
|
||||
|
||||
Технологии:
|
||||
|
||||
Echo (HTTP API для клиентов и пиров).
|
||||
gRPC (для быстрого обмена метриками).
|
||||
Redis (кеш рейтингов пиров).
|
||||
PostgreSQL/SQLite3 (хранение данных пользователей, транзакций).
|
||||
|
||||
1.2. Клиент (VPN Client)
|
||||
|
||||
Роль: Подключается к пирам или центральным серверам через Shadowsocks.
|
||||
|
||||
Функции:
|
||||
|
||||
Получает список пиров от трекера.
|
||||
Тестирует подключение (ping, speedtest).
|
||||
Выбирает лучший пир/сервер.
|
||||
Учитывает потраченные/заработанные монеты.
|
||||
|
||||
Технологии:
|
||||
|
||||
go-shadowsocks2 (подключение через SOCKS5).
|
||||
libp2p (для P2P-подключений).
|
||||
|
||||
1.3. Пир (Peer Node)
|
||||
|
||||
Роль: Раздает трафик другим клиентам за монеты.
|
||||
|
||||
Функции:
|
||||
|
||||
Регистрируется на трекере.
|
||||
Принимает подключения через Shadowsocks.
|
||||
Отправляет метрики (трафик, скорость) трекеру.
|
||||
Получает вознаграждение в монетах.
|
||||
|
||||
Технологии:
|
||||
|
||||
go-shadowsocks2 (режим сервера).
|
||||
Prometheus + Grafana (мониторинг).
|
||||
|
||||
2. Как работает трафик
|
||||
|
||||
2.1. Подключение клиента
|
||||
|
||||
Клиент запрашивает у трекера список доступных пиров.
|
||||
Трекер возвращает доступные пиры по скорости/стоимости.
|
||||
Клиент тестирует их и подключается к лучшему.
|
||||
Весь трафик идет через Shadowsocks-туннель (Можно настроить).
|
||||
|
||||
3. Монетизация
|
||||
|
||||
3.1. Внутренняя валюта
|
||||
|
||||
Монеты (токены) начисляются за отданный трафик.
|
||||
Клиенты покупают подписку или тратят монеты на трафик.
|
||||
|
||||
## 📜 Лицензия
|
||||
Этот проект распространяется под **SSPL-1.0**.
|
||||
Коммерческое использование в качестве сервиса (SaaS) без разрешения автора запрещено.
|
||||
|
||||
Данная лицензия (SSPL) применяется только к коду, написанному автором godpn.
|
||||
Сторонние библиотеки (например, go-shadowsocks2) используются под их исходными лицензиями.
|
||||
+2
-2
@@ -3,11 +3,11 @@ package main
|
||||
import (
|
||||
"log/slog"
|
||||
|
||||
"github.com/rombintu/godpn/internal/tracker"
|
||||
"github.com/rombintu/godpn/internal/coordinator"
|
||||
)
|
||||
|
||||
func main() {
|
||||
server := tracker.NewServer()
|
||||
server := coordinator.NewServer()
|
||||
server.Configure()
|
||||
if err := server.Run(); err != nil {
|
||||
slog.Info(err.Error())
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package coordinator
|
||||
|
||||
import "github.com/rombintu/godpn/internal/models"
|
||||
|
||||
type Coordinator struct {
|
||||
// TODO временное решение
|
||||
//
|
||||
// ip : Peer
|
||||
peers map[string]models.PeerNode
|
||||
}
|
||||
|
||||
func NewCoordinator() *Coordinator {
|
||||
return &Coordinator{
|
||||
peers: make(map[string]models.PeerNode),
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package tracker
|
||||
package coordinator
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
@@ -9,27 +9,26 @@ import (
|
||||
)
|
||||
|
||||
func (s *Server) registerHandler(c echo.Context) error {
|
||||
var peer models.PeerManifest
|
||||
if err := c.Bind(peer); err != nil {
|
||||
var node models.PeerNode
|
||||
if err := c.Bind(node); err != nil {
|
||||
return c.JSON(http.StatusBadRequest, map[string]string{"error": "invalid request"})
|
||||
}
|
||||
|
||||
if peer.PubKey == "" {
|
||||
return c.JSON(http.StatusBadRequest, map[string]string{"error": "pubkey is required"})
|
||||
if node.PublicKey == "" {
|
||||
return c.JSON(http.StatusBadRequest, map[string]string{"error": "public key is required"})
|
||||
}
|
||||
|
||||
ip := c.RealIP()
|
||||
if peer.IP != "" {
|
||||
ip = peer.IP
|
||||
if node.Endpoint != "" {
|
||||
ip = node.Endpoint
|
||||
}
|
||||
|
||||
s.mu.Lock()
|
||||
s.tracker.peers[ip] = peer.PubKey
|
||||
s.coordinator.peers[ip] = node
|
||||
s.mu.Unlock()
|
||||
|
||||
return c.JSON(http.StatusOK, map[string]string{
|
||||
"status": "registered",
|
||||
"ip": ip,
|
||||
return c.JSON(http.StatusOK, map[string]models.PeerNode{
|
||||
"registered": node,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -37,7 +36,7 @@ func (s *Server) registerHandler(c echo.Context) error {
|
||||
func (s *Server) listPeers(c echo.Context) error {
|
||||
s.mu.RLock()
|
||||
defer s.mu.RUnlock()
|
||||
return c.JSON(http.StatusOK, s.tracker.peers)
|
||||
return c.JSON(http.StatusOK, s.coordinator.peers)
|
||||
}
|
||||
|
||||
// WebSocket handler для реального времени
|
||||
@@ -54,7 +53,7 @@ func (s *Server) websocketHandler(c echo.Context) error {
|
||||
|
||||
// Отправляем текущий список peers при подключении
|
||||
s.mu.RLock()
|
||||
if err := ws.WriteJSON(s.tracker.peers); err != nil {
|
||||
if err := ws.WriteJSON(s.coordinator.peers); err != nil {
|
||||
s.mu.RUnlock()
|
||||
return err
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package tracker
|
||||
package coordinator
|
||||
|
||||
import (
|
||||
"sync"
|
||||
@@ -10,13 +10,13 @@ import (
|
||||
type Server struct {
|
||||
router *echo.Echo
|
||||
mu sync.RWMutex
|
||||
tracker *Tracker
|
||||
coordinator *Coordinator
|
||||
}
|
||||
|
||||
func NewServer() *Server {
|
||||
return &Server{
|
||||
router: echo.New(),
|
||||
tracker: NewTracker(),
|
||||
coordinator: NewCoordinator(),
|
||||
}
|
||||
}
|
||||
|
||||
+26
-3
@@ -1,6 +1,29 @@
|
||||
package models
|
||||
|
||||
type PeerManifest struct {
|
||||
IP string `json:"ip" form:"ip" query:"ip"`
|
||||
PubKey string `json:"pubkey" form:"pubkey" query:"pubkey" validate:"required"`
|
||||
import "time"
|
||||
|
||||
type PeerNode struct {
|
||||
// Basic identity
|
||||
PublicKey string `json:"public_key" validate:"required"` // WireGuard/SS public key
|
||||
|
||||
// Network information
|
||||
Endpoint string `json:"endpoint"` // IP:Port or DNS
|
||||
Protocol string `json:"protocol"` // "shadowsocks", "wireguard", etc
|
||||
|
||||
// Performance metrics
|
||||
System string `json:"system"` // "linux", "windows", etc
|
||||
Latency int `json:"latency"` // in milliseconds
|
||||
Bandwidth int `json:"bandwidth"` // in Mbps
|
||||
|
||||
// Geo information
|
||||
Region string `json:"region,omitempty"` // "eu-west", "us-east"
|
||||
Country string `json:"country,omitempty"` // 2-letter ISO code
|
||||
|
||||
// System stats
|
||||
Uptime float64 `json:"uptime"` // 0.0-1.0 percentage
|
||||
Load float64 `json:"load"` // 5-min system load avg
|
||||
|
||||
// Timestamps
|
||||
LastSeen time.Time `json:"last_seen"`
|
||||
FirstSeen time.Time `json:"first_seen"`
|
||||
}
|
||||
|
||||
@@ -6,14 +6,14 @@ import (
|
||||
)
|
||||
|
||||
func (s *Server) connectHandler(c echo.Context) error {
|
||||
var peerManifest models.PeerManifest
|
||||
var node models.PeerNode
|
||||
|
||||
if err := c.Bind(peerManifest); err != nil {
|
||||
if err := c.Bind(node); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
peer := NewPeer(peerManifest.PubKey)
|
||||
if err := peer.Connect(peerManifest.IP, "8080"); err != nil {
|
||||
peer := NewPeer(node.PublicKey)
|
||||
if err := peer.Connect(node.Endpoint); err != nil {
|
||||
return err
|
||||
}
|
||||
defer peer.Disconnect()
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
const (
|
||||
tcpNetwork = "tcp"
|
||||
bufferSize = 32 * 1024 // 32KB
|
||||
AHEAD_CHACHA20_POLY1305 = "AEAD_CHACHA20_POLY1305" // Default method cipher
|
||||
)
|
||||
|
||||
// Ошибки подключения
|
||||
@@ -34,7 +35,7 @@ func NewPeer(pubKey string) *Peer {
|
||||
}
|
||||
}
|
||||
|
||||
func (p *Peer) Connect(ip, port string) error {
|
||||
func (p *Peer) Connect(endpoint string) error {
|
||||
p.mu.Lock()
|
||||
defer p.mu.Unlock()
|
||||
|
||||
@@ -42,12 +43,12 @@ func (p *Peer) Connect(ip, port string) error {
|
||||
return nil // Уже подключен
|
||||
}
|
||||
|
||||
conn, err := net.Dial(tcpNetwork, net.JoinHostPort(ip, port))
|
||||
conn, err := net.Dial(tcpNetwork, endpoint)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
cipher, err := core.PickCipher("AEAD_CHACHA20_POLY1305", []byte(p.pubKey), "")
|
||||
cipher, err := core.PickCipher(AHEAD_CHACHA20_POLY1305, []byte(p.pubKey), "")
|
||||
if err != nil {
|
||||
conn.Close()
|
||||
return err
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
package tracker
|
||||
|
||||
type Tracker struct {
|
||||
peers map[string]string
|
||||
}
|
||||
|
||||
func NewTracker() *Tracker {
|
||||
return &Tracker{
|
||||
peers: make(map[string]string),
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user