From dd2d38994d0a24544b2ffd5eae1ebcc9b3f4869a Mon Sep 17 00:00:00 2001 From: damir Date: Mon, 30 Mar 2026 17:25:26 +0000 Subject: [PATCH] Add main.go --- main.go | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 main.go diff --git a/main.go b/main.go new file mode 100644 index 0000000..b427691 --- /dev/null +++ b/main.go @@ -0,0 +1,108 @@ +package main + +import ( + "context" + "crypto/tls" + "fmt" + "io" + "log" + "net/http" + "os" + + "github.com/pion/webtransport" + "github.com/quic-go/quic-go/http3" +) + +func main() { + // 1. Настройка TLS (обязательно для WebTransport/QUIC) + // Поскольку SSL терминация на VPS, здесь мы используем самоподписанный сертификат + // для внутренней связи (Dokploy <-> Caddy). Nixpacks соберет это. + // Но для простоты примера мы просто слушаем обычный HTTP, так как Caddy проксирует. + // ОДНАКО: WebTransport ТРЕБУЕТ TLS. Внутренний TLS тоже нужен. + // Мы сгенерируем его на лету, чтобы не возиться с файлами. + + cert, err := generateSelfSignedCert() + if err != nil { + log.Fatal(err) + } + + tlsConfig := &tls.Config{ + Certificates: []tls.Certificate{cert}, + NextProtos: []string{"h3"}, // HTTP/3 + } + + // 2. Настройка WebTransport Handler + server := webtransport.Server{ + H3: http3.Server{ + Addr: ":8080", // Порт внутри контейнера + TLSConfig: tlsConfig, + }, + CheckOrigin: func(r *http.Request) bool { return true }, // Разрешить все Origin для теста + } + + http.HandleFunc("/wt", func(w http.ResponseWriter, r *http.Request) { + log.Println("New WebTransport request from:", r.RemoteAddr) + sess, err := server.Upgrade(w, r) + if err != nil { + log.Printf("Upgrade failed: %v", err) + return + } + + // Обработка сессии в отдельной горутине + go handleSession(sess) + }) + + log.Println("WebTransport server listening on https://localhost:8080/wt (via Caddy)") + // Запускаем HTTP/3 сервер + if err := server.ListenAndServe(); err != nil { + log.Fatal(err) + } +} + +// Обработка одной WebTransport сессии +func handleSession(sess *webtransport.Session) { + defer sess.CloseWithError(0, "session closed") + + for { + // Читаем датаграммы (самый быстрый и ненадежный способ, как UDP) + msg, err := sess.ReadDatagram(context.Background()) + if err != nil { + if err != io.EOF { + log.Printf("ReadDatagram error: %v", err) + } + return + } + fmt.Printf("Received Datagram from %v: %s\n", sess.RemoteAddr(), string(msg)) + } +} + +// Вспомогательная функция для генерации внутреннего SSL +// (Для связи Caddy -> Dokploy по Wireguard) +import ( + "crypto/rand" + "crypto/rsa" + "crypto/x509" + "crypto/x509/pkix" + "encoding/pem" + "math/big" + "time" +) + +func generateSelfSignedCert() (tls.Certificate, error) { + priv, _ := rsa.GenerateKey(rand.Reader, 2048) + template := x509.Certificate{ + SerialNumber: big.NewInt(1), + Subject: pkix.Name{Organization: []string{"Pion WebTransport Test"}}, + NotBefore: time.Now(), + NotAfter: time.Now().Add(time.Hour * 24 * 365), + KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature, + ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth}, + BasicConstraintsValid: true, + } + derBytes, _ := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv) + + certPEM := pem.EncodeToMemory(&pem.Block{Type: "CERTIFICATE", Bytes: derBytes}) + keyPEM := pem.EncodeToMemory(&pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(priv)}) + + return tls.X509KeyPair(certPEM, keyPEM) +} \ No newline at end of file