1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
| package main
import ( "flag" "log" "net"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2/middleware/logger" "github.com/gofiber/websocket/v2" )
const ( localKeyBackendURL = "localKeyBackendURL" )
func main() { addrPtr := flag.String("backend", "", "backend addr") flag.Parse() if addrPtr == nil || *addrPtr == "" { log.Fatalln("Missing backend parameter. Use -h to help") } log.Println("Proxy to:", *addrPtr)
app := fiber.New(fiber.Config{ Immutable: true, }) app.Use(logger.New()) app.Get("/ws/*", wsCheckMiddleware(*addrPtr), websocket.New(wsHandler)) app.Listen(":10001") }
func wsCheckMiddleware(backendURL string) fiber.Handler { return func(c *fiber.Ctx) error { if !websocket.IsWebSocketUpgrade(c) { return fiber.ErrUpgradeRequired } c.Locals(localKeyBackendURL, backendURL) return c.Next() } }
func wsHandler(c *websocket.Conn) { url := c.Locals(localKeyBackendURL).(string) defer c.Close()
udpServer, err := net.ResolveUDPAddr("udp", url) if err != nil { log.Fatalln(err) } udpConn, err := net.DialUDP("udp", nil, udpServer) if err != nil { log.Fatalln(err) } defer udpConn.Close()
clientErrChan := make(chan error, 1) backendErrChan := make(chan error, 1)
go forwardWS2UDP(c, udpConn, clientErrChan) go forwardUDP2WS(udpConn, c, backendErrChan)
var msg string
select { case err = <-clientErrChan: msg = "forward client to backend server error" case err = <-backendErrChan: msg = "forward backend to client server error" }
if websocket.IsUnexpectedCloseError( err, websocket.CloseGoingAway, websocket.CloseNoStatusReceived) { log.Println(msg, "error:", err) } }
func forwardWS2UDP( wsConn *websocket.Conn, udpConn *net.UDPConn, errChan chan error, ) { for { _, msg, err := wsConn.ReadMessage() if err != nil { errChan <- err break }
_, err = udpConn.Write(msg) if err != nil { errChan <- err break } } }
func forwardUDP2WS( udpConn *net.UDPConn, wsConn *websocket.Conn, errChan chan error, ) { for { buf := make([]byte, 1024) n, err := udpConn.Read(buf) if err != nil { errChan <- err break }
err = wsConn.WriteMessage(websocket.TextMessage, buf[:n]) if err != nil { errChan <- err break } } }
|