-
Notifications
You must be signed in to change notification settings - Fork 1
/
udp_proxy.go
157 lines (143 loc) · 3.38 KB
/
udp_proxy.go
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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
package main
import (
"fmt"
"net"
)
const serverIP = "147.75.85.99"
const localIP = "127.0.0.1"
// we set this to 127.0.0.1 in /etc/hosts
const serverHost = "maze.liveoverflow.com"
const minPort = 1337
const maxPort = 1357
// proxy http requests to maze.liveoverflow.com
// set hostname and port to something on this machine
// send all requests to that to maze.liveoverflow.com
// MessageHandler will receive all message payloads.
type MessageHandler func(origin string, msg []byte) [][]byte
type udpProxy struct {
clientConn *net.UDPConn
serverConn *net.UDPConn
clientChan chan []byte
serverChan chan []byte
clientAddr *net.UDPAddr
msgHandler MessageHandler
activePort int
}
func newUDPProxy() {
up := &udpProxy{
serverChan: make(chan []byte),
clientChan: make(chan []byte),
msgHandler: msgInterceptor,
}
for port := minPort; port <= maxPort; port++ {
maybeConn, err := net.ListenUDP("udp", addr(localIP, port))
check(err)
go func(port int) {
buffer := make([]byte, 4096)
// fmt.Println("Listening on", port)
n, clientAddr, err := maybeConn.ReadFromUDP(buffer)
check(err)
if up.clientAddr != nil {
fmt.Printf("== WARN == Switched to port %d\n", port)
}
msg := buffer[:n]
fmt.Printf("STARTED COMMS ON PORT %d\n", port)
fmt.Printf("CLIENT>0x%x\n", decode(msg))
up.clientAddr = clientAddr
up.clientConn = maybeConn
up.serverChan <- msg
up.serverConn, err = net.DialUDP("udp", nil, addr(serverIP, port))
if err != nil {
fmt.Println(err)
}
check(err)
up.activePort = port
}(port)
// wait for first message
}
done := make(chan bool, 1)
msg := <-up.serverChan
fmt.Println("Starting UDP proxy")
go up.recvClient()
go up.recvServer()
go up.sendClient()
go up.sendServer()
up.serverChan <- msg
<-done
}
func (up *udpProxy) sendClient() {
for msg := range up.clientChan {
_, err := up.clientConn.WriteToUDP(msg, up.clientAddr)
if err != nil {
fmt.Println("CLIENT SEND", err)
}
// print("CLIENT SEND", msg)
}
}
func (up *udpProxy) ensureServerConn() {
if up.serverConn == nil {
serverConn, err := net.DialUDP("udp", nil, addr(serverIP, up.activePort))
if err != nil {
fmt.Println(err)
}
up.serverConn = serverConn
}
}
func (up *udpProxy) sendServer() {
for msg := range up.serverChan {
up.ensureServerConn()
_, _, err := up.serverConn.WriteMsgUDP(msg, nil, nil)
if err != nil {
fmt.Println("SERVER SEND", err)
}
// print("SERVER SEND", msg)
}
}
func (up *udpProxy) recvClient() {
buffer := make([]byte, 4096)
for {
n, clientAddr, err := up.clientConn.ReadFromUDP(buffer)
if err != nil {
fmt.Println(err)
continue
}
up.clientAddr = clientAddr
msg := make([]byte, n)
copy(msg, buffer[:n])
msgs := up.msgHandler("CLIENT", msg)
for _, out := range msgs {
if len(out) > 0 {
up.serverChan <- out
}
}
}
}
func (up *udpProxy) recvServer() error {
buffer := make([]byte, 4096)
for {
up.ensureServerConn()
n, _, err := up.serverConn.ReadFromUDP(buffer)
if err != nil {
fmt.Println(err)
continue
}
msg := make([]byte, n)
copy(msg, buffer[:n])
msgs := up.msgHandler("SERVER", msg)
for _, out := range msgs {
if len(out) > 0 {
up.clientChan <- out
}
}
}
}
func addr(ip string, port int) *net.UDPAddr {
addr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", ip, port))
check(err)
return addr
}
func check(err error) {
if err != nil {
panic(err)
}
}