package server import ( "bufio" "crypto/tls" "errors" "fmt" "log" "net" "strings" "tunnel_pls/internal/config" "tunnel_pls/session" ) func NewHTTPSServer() error { domain := config.Getenv("DOMAIN", "localhost") httpsPort := config.Getenv("HTTPS_PORT", "8443") tlsConfig, err := NewTLSConfig(domain) if err != nil { return fmt.Errorf("failed to initialize TLS config: %w", err) } ln, err := tls.Listen("tcp", ":"+httpsPort, tlsConfig) if err != nil { return err } go func() { for { var conn net.Conn conn, err = ln.Accept() if err != nil { if errors.Is(err, net.ErrClosed) { log.Println("https server closed") } log.Printf("Error accepting connection: %v", err) continue } go HandlerTLS(conn) } }() return nil } func HandlerTLS(conn net.Conn) { defer func() { err := conn.Close() if err != nil { log.Printf("Error closing connection: %v", err) return } return }() dstReader := bufio.NewReader(conn) reqhf, err := NewRequestHeaderFactory(dstReader) if err != nil { log.Printf("Error creating request header: %v", err) return } host := strings.Split(reqhf.Get("Host"), ".") if len(host) < 1 { _, err = conn.Write([]byte("HTTP/1.1 400 Bad Request\r\n\r\n")) if err != nil { log.Println("Failed to write 400 Bad Request:", err) return } return } slug := host[0] if slug == "ping" { _, err = conn.Write([]byte( "HTTP/1.1 200 OK\r\n" + "Content-Length: 0\r\n" + "Connection: close\r\n" + "Access-Control-Allow-Origin: *\r\n" + "Access-Control-Allow-Methods: GET, HEAD, OPTIONS\r\n" + "Access-Control-Allow-Headers: *\r\n" + "\r\n", )) if err != nil { log.Println("Failed to write 200 OK:", err) return } return } sshSession, ok := session.Clients[slug] if !ok { _, err = conn.Write([]byte("HTTP/1.1 301 Moved Permanently\r\n" + fmt.Sprintf("Location: https://tunnl.live/tunnel-not-found?slug=%s\r\n", slug) + "Content-Length: 0\r\n" + "Connection: close\r\n" + "\r\n")) if err != nil { log.Println("Failed to write 301 Moved Permanently:", err) return } return } cw := NewCustomWriter(conn, dstReader, conn.RemoteAddr()) forwardRequest(cw, reqhf, sshSession) return }