mirror of
https://github.com/onyx-and-iris/q3rcon-proxy.git
synced 2025-01-18 08:40:53 +00:00
initial commit
This commit is contained in:
commit
cfa445db14
19
.vscode/launch.json
vendored
Normal file
19
.vscode/launch.json
vendored
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
// Use IntelliSense to learn about possible attributes.
|
||||||
|
// Hover to view descriptions of existing attributes.
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "http server",
|
||||||
|
"type": "go",
|
||||||
|
"request": "launch",
|
||||||
|
"mode": "auto",
|
||||||
|
"program": "${workspaceFolder}/cmd/http/main.go",
|
||||||
|
"env": {
|
||||||
|
"LILPROXY_TARGET": "localhost:9001",
|
||||||
|
"LILPROXY_PORT":":9000"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
10
Dockerfile
Normal file
10
Dockerfile
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
FROM golang:alpine
|
||||||
|
|
||||||
|
# Move to /dist directory as the place for resulting binary folder
|
||||||
|
WORKDIR /dist
|
||||||
|
|
||||||
|
# Copy binary from build to main folder
|
||||||
|
COPY ./main .
|
||||||
|
|
||||||
|
# Command to run when starting the container
|
||||||
|
ENTRYPOINT [ "/dist/main" ]
|
29
cmd/http/main.go
Normal file
29
cmd/http/main.go
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/dgparker/lilproxy/pkg/udpproxy"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
target := os.Getenv("LILPROXY_TARGET")
|
||||||
|
if target == "" {
|
||||||
|
log.Fatal("env LILPROXY_TARGET required")
|
||||||
|
}
|
||||||
|
|
||||||
|
port := os.Getenv("LILPROXY_PORT")
|
||||||
|
if port == "" {
|
||||||
|
log.Fatal("env LILPROXY_PORT required")
|
||||||
|
}
|
||||||
|
|
||||||
|
c, err := udpproxy.New(port, target)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("lilproxy initialized")
|
||||||
|
|
||||||
|
log.Fatal(c.ListenAndServe())
|
||||||
|
}
|
66
pkg/udpproxy/session.go
Normal file
66
pkg/udpproxy/session.go
Normal file
@ -0,0 +1,66 @@
|
|||||||
|
package udpproxy
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"net"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Session struct {
|
||||||
|
serverConn *net.UDPConn
|
||||||
|
proxyConn *net.UDPConn
|
||||||
|
caddr *net.UDPAddr
|
||||||
|
updateTime time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
func createSession(caddr *net.UDPAddr, raddr *net.UDPAddr, proxyConn *net.UDPConn) (*Session, error) {
|
||||||
|
serverConn, err := net.DialUDP("udp", nil, raddr)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
session := &Session{
|
||||||
|
serverConn: serverConn,
|
||||||
|
proxyConn: proxyConn,
|
||||||
|
caddr: caddr,
|
||||||
|
updateTime: time.Now(),
|
||||||
|
}
|
||||||
|
|
||||||
|
go session.listen()
|
||||||
|
|
||||||
|
return session, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Session) listen() error {
|
||||||
|
for {
|
||||||
|
buf := make([]byte, 1024)
|
||||||
|
_, err := s.serverConn.Read(buf)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
go s.proxyFrom(buf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Session) proxyFrom(buf []byte) error {
|
||||||
|
s.updateTime = time.Now()
|
||||||
|
_, err := s.proxyConn.WriteToUDP(buf, s.caddr)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Session) proxyTo(buf []byte) error {
|
||||||
|
s.updateTime = time.Now()
|
||||||
|
_, err := s.serverConn.Write(buf)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
84
pkg/udpproxy/udpproxy.go
Normal file
84
pkg/udpproxy/udpproxy.go
Normal file
@ -0,0 +1,84 @@
|
|||||||
|
package udpproxy
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"net"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Client struct {
|
||||||
|
laddr *net.UDPAddr
|
||||||
|
raddr *net.UDPAddr
|
||||||
|
|
||||||
|
proxyConn *net.UDPConn
|
||||||
|
|
||||||
|
mutex sync.RWMutex
|
||||||
|
sessions map[string]*Session
|
||||||
|
}
|
||||||
|
|
||||||
|
func New(port, target string) (*Client, error) {
|
||||||
|
laddr, err := net.ResolveUDPAddr("udp", port)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
raddr, err := net.ResolveUDPAddr("udp", target)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &Client{
|
||||||
|
laddr: laddr,
|
||||||
|
raddr: raddr,
|
||||||
|
mutex: sync.RWMutex{},
|
||||||
|
sessions: map[string]*Session{},
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) ListenAndServe() error {
|
||||||
|
var err error
|
||||||
|
c.proxyConn, err = net.ListenUDP("udp", c.laddr)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
go c.pruneSessions()
|
||||||
|
|
||||||
|
for {
|
||||||
|
buf := make([]byte, 2048)
|
||||||
|
_, caddr, err := c.proxyConn.ReadFromUDP(buf)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
session, found := c.sessions[caddr.String()]
|
||||||
|
if !found {
|
||||||
|
session, err = createSession(caddr, c.raddr, c.proxyConn)
|
||||||
|
if err != nil {
|
||||||
|
log.Println(err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
c.sessions[caddr.String()] = session
|
||||||
|
}
|
||||||
|
|
||||||
|
go session.proxyTo(buf)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Client) pruneSessions() {
|
||||||
|
ticker := time.NewTicker(1 * time.Minute)
|
||||||
|
|
||||||
|
// the locks here could be abusive and i dont even know if this is a real
|
||||||
|
// problem but we definitely need to clean up stale sessions
|
||||||
|
for range ticker.C {
|
||||||
|
for _, session := range c.sessions {
|
||||||
|
c.mutex.RLock()
|
||||||
|
if time.Since(session.updateTime) > time.Minute*5 {
|
||||||
|
delete(c.sessions, session.caddr.String())
|
||||||
|
}
|
||||||
|
c.mutex.RUnlock()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
83
pkg/udpproxy/udpproxy_test.go
Normal file
83
pkg/udpproxy/udpproxy_test.go
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
package udpproxy
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"net"
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestSendAndReceive(t *testing.T) {
|
||||||
|
go runLilProxy()
|
||||||
|
go runUDPServer()
|
||||||
|
|
||||||
|
paddr, err := net.ResolveUDPAddr("udp", "localhost:9000")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
conn, err := net.DialUDP("udp", nil, paddr)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
for {
|
||||||
|
buf := make([]byte, 2048)
|
||||||
|
_, _, err = conn.ReadFromUDP(buf)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("response received: %s", string(buf))
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
for {
|
||||||
|
time.Sleep(1 * time.Second)
|
||||||
|
_, err = conn.Write([]byte("hi\n"))
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func runLilProxy() {
|
||||||
|
port := ":9000"
|
||||||
|
target := "localhost:9001"
|
||||||
|
|
||||||
|
c, err := New(port, target)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Fatal(c.ListenAndServe())
|
||||||
|
}
|
||||||
|
|
||||||
|
func runUDPServer() {
|
||||||
|
taddr, err := net.ResolveUDPAddr("udp", ":9001")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
conn, err := net.ListenUDP("udp", taddr)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for {
|
||||||
|
buf := make([]byte, 2048)
|
||||||
|
_, caddr, err := conn.ReadFromUDP(buf)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Printf("request received: %s", string(buf))
|
||||||
|
|
||||||
|
_, err = conn.WriteToUDP([]byte("bye\n"), caddr)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
4
vendor/modules.txt
vendored
Normal file
4
vendor/modules.txt
vendored
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
# github.com/google/martian/v3 v3.3.2
|
||||||
|
## explicit; go 1.11
|
||||||
|
# golang.org/x/sys v0.3.0
|
||||||
|
## explicit; go 1.17
|
Loading…
Reference in New Issue
Block a user