Skip to content

Commit 5a24d9f

Browse files
committed
This version should work but has issues
1 parent 25b9848 commit 5a24d9f

File tree

6 files changed

+205
-0
lines changed

6 files changed

+205
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
*.exe

cmd/main.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package main
2+
3+
import (
4+
"flag"
5+
6+
"github.com/simsor/quakejs-proxy/proxy"
7+
"github.com/sirupsen/logrus"
8+
)
9+
10+
var (
11+
wsServer = flag.String("ws", "127.0.0.1:27961", "Hostname of the WebSocket server")
12+
listen = flag.String("listen", "", "Host to listen on")
13+
)
14+
15+
func main() {
16+
flag.Parse()
17+
18+
server := proxy.New(*listen, *wsServer)
19+
20+
logrus.WithFields(logrus.Fields{
21+
"listen": *listen,
22+
"dest": *wsServer,
23+
}).Info("Proxy server listening")
24+
25+
err := server.Start()
26+
if err != nil {
27+
panic(err)
28+
}
29+
server.Close()
30+
}

go.mod

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,8 @@
11
module github.com/simsor/quakejs-proxy
22

33
go 1.14
4+
5+
require (
6+
github.com/gorilla/websocket v1.4.2
7+
github.com/sirupsen/logrus v1.7.0
8+
)

go.sum

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
2+
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
3+
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
4+
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
5+
github.com/sirupsen/logrus v1.7.0 h1:ShrD1U9pZB12TX0cVy0DtePoCH97K8EtX+mg7ZARUtM=
6+
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
7+
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
8+
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4=
9+
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=

proxy/agent.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package proxy
2+
3+
import (
4+
"encoding/hex"
5+
"fmt"
6+
"net"
7+
8+
"github.com/gorilla/websocket"
9+
"github.com/sirupsen/logrus"
10+
)
11+
12+
type agent struct {
13+
remote net.Addr
14+
sock net.PacketConn
15+
ws *websocket.Conn
16+
}
17+
18+
func (a *agent) ws2sock() {
19+
log := logrus.WithFields(logrus.Fields{
20+
"remote": a.remote.String(),
21+
"func": "ws2sock",
22+
})
23+
defer a.ws.Close()
24+
25+
for {
26+
t, p, err := a.ws.ReadMessage()
27+
if err != nil {
28+
log.WithField("err", err).Error("Could not read WebSocket message")
29+
return
30+
}
31+
log.Info("Got WS message")
32+
33+
if t != websocket.BinaryMessage {
34+
log.Error("Wrong message type")
35+
return
36+
}
37+
38+
n, err := a.sock.WriteTo(p, a.remote)
39+
if err != nil {
40+
log.WithError(err).Error("Could not write to socket")
41+
return
42+
}
43+
44+
if n != len(p) {
45+
log.WithFields(logrus.Fields{
46+
"written": n,
47+
"length": len(p),
48+
}).Error("Did not write full message")
49+
return
50+
}
51+
log.Info("Successfully sent WS message to socket")
52+
53+
fmt.Println(hex.Dump(p))
54+
}
55+
}

proxy/server.go

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
package proxy
2+
3+
import (
4+
"encoding/hex"
5+
"fmt"
6+
"net"
7+
"net/url"
8+
9+
"github.com/gorilla/websocket"
10+
"github.com/sirupsen/logrus"
11+
)
12+
13+
// SocketServer is the proxy server
14+
type SocketServer struct {
15+
ListenAddress string
16+
ListenPort int
17+
Destination string
18+
19+
listener net.PacketConn
20+
agents map[string]*agent
21+
}
22+
23+
// New creates a new socket to websocket proxy server listening on the given address, on port 27960
24+
func New(listen, dest string) SocketServer {
25+
return SocketServer{
26+
ListenAddress: listen,
27+
ListenPort: 27960,
28+
Destination: dest,
29+
agents: make(map[string]*agent),
30+
}
31+
}
32+
33+
func (s *SocketServer) listen() error {
34+
// Socket server
35+
listener, err := net.ListenPacket("udp4", fmt.Sprintf("%s:%d", s.ListenAddress, s.ListenPort))
36+
if err != nil {
37+
return err
38+
}
39+
40+
s.listener = listener
41+
return nil
42+
}
43+
44+
// Start is a blocking call which starts the proxy server
45+
func (s *SocketServer) Start() error {
46+
err := s.listen()
47+
if err != nil {
48+
return err
49+
}
50+
51+
p := make([]byte, 65535)
52+
53+
for {
54+
n, addr, err := s.listener.ReadFrom(p)
55+
if err != nil {
56+
logrus.WithFields(logrus.Fields{
57+
"err": err,
58+
}).Error("Could not ReadFrom() a connection")
59+
continue
60+
}
61+
//logrus.WithField("remote", addr.String()).Info("Accepted UDP connection")
62+
63+
a := s.getAgent(addr)
64+
err = a.ws.WriteMessage(websocket.BinaryMessage, p[:n])
65+
if err != nil {
66+
logrus.WithFields(logrus.Fields{
67+
"err": err,
68+
"remote": addr.String(),
69+
}).Error("Could not WriteMessage()")
70+
continue
71+
}
72+
logrus.WithField("remote", addr.String()).Info("Successfully sent UDP message to WebSocket")
73+
fmt.Println(hex.Dump(p[:n]))
74+
}
75+
76+
}
77+
78+
// Close closes both sockets
79+
func (s *SocketServer) Close() error {
80+
return s.listener.Close()
81+
}
82+
83+
func (s *SocketServer) getAgent(ip net.Addr) *agent {
84+
a, ok := s.agents[ip.String()]
85+
if ok {
86+
return a
87+
}
88+
89+
// WebSocket client
90+
u := url.URL{Scheme: "ws", Host: s.Destination, Path: "/"}
91+
ws, _, err := websocket.DefaultDialer.Dial(u.String(), nil)
92+
if err != nil {
93+
panic(err)
94+
}
95+
96+
a = &agent{
97+
ws: ws,
98+
sock: s.listener,
99+
remote: ip,
100+
}
101+
go a.ws2sock()
102+
s.agents[ip.String()] = a
103+
104+
return a
105+
}

0 commit comments

Comments
 (0)