fracturize

This commit is contained in:
Merith-TK 2025-02-04 17:13:27 +00:00
parent 6e0b8f546b
commit 0b300f64cc
7 changed files with 163 additions and 135 deletions

2
.gitignore vendored Normal file
View file

@ -0,0 +1,2 @@
simpleproxy*
*.exe

31
config.go Normal file
View file

@ -0,0 +1,31 @@
package main
import (
"log"
"os"
"github.com/yosuke-furukawa/json5/encoding/json5"
)
type ProxyConfig struct {
Proxy []Proxy `json:"proxy"`
}
type Proxy struct {
Local string `json:"local,omitempty"`
Remote string `json:"remote"`
Type string `json:"type,omitempty"` // "tcp", "udp", or "both"
}
func ReadConfig(configPath string) ProxyConfig {
configData, err := os.ReadFile(configPath)
if err != nil {
log.Fatalf("[ERROR] Failed to read config file (%s): %v\n", configPath, err)
}
var config ProxyConfig
if err := json5.Unmarshal(configData, &config); err != nil {
log.Fatalf("[ERROR] Failed to parse config file: %v\n", err)
}
return config
}

2
go.mod
View file

@ -1,4 +1,4 @@
module github.com/merith-tk/simpleproxy module github.com/Merith-TK/simpleproxy
go 1.22.5 go 1.22.5

BIN
goproxy

Binary file not shown.

135
main.go
View file

@ -3,139 +3,14 @@ package main
import ( import (
"context" "context"
"flag" "flag"
"io"
"log" "log"
"net"
"os" "os"
"os/signal" "os/signal"
"strings" "strings"
"sync" "sync"
"syscall" "syscall"
"github.com/yosuke-furukawa/json5/encoding/json5"
) )
type ProxyConfig struct {
Proxy []Proxy `json:"proxy"`
}
type Proxy struct {
Local string `json:"local,omitempty"`
Remote string `json:"remote"`
Type string `json:"type,omitempty"` // "tcp", "udp", or "both"
}
func handleTCPConnection(src net.Conn, targetAddr string) {
defer src.Close()
dst, err := net.Dial("tcp", targetAddr)
if err != nil {
log.Printf("[ERROR] Unable to connect to target: %v\n", err)
return
}
defer dst.Close()
done := make(chan struct{})
go func() {
io.Copy(dst, src)
done <- struct{}{}
}()
go func() {
io.Copy(src, dst)
done <- struct{}{}
}()
<-done
}
func startTCPProxy(ctx context.Context, wg *sync.WaitGroup, localAddr, targetAddr string) {
defer wg.Done()
listener, err := net.Listen("tcp", localAddr)
if err != nil {
log.Fatalf("[ERROR] Unable to listen on %s: %v\n", localAddr, err)
}
defer listener.Close()
log.Printf("[INFO] Listening on %s (TCP), forwarding to %s\n", localAddr, targetAddr)
for {
select {
case <-ctx.Done():
log.Printf("[INFO] Shutting down TCP proxy on %s\n", localAddr)
return
default:
conn, err := listener.Accept()
if err != nil {
log.Printf("[ERROR] Failed to accept connection: %v\n", err)
continue
}
go handleTCPConnection(conn, targetAddr)
}
}
}
func startUDPProxy(ctx context.Context, wg *sync.WaitGroup, localAddr, targetAddr string) {
defer wg.Done()
localConn, err := net.ListenPacket("udp", localAddr)
if err != nil {
log.Fatalf("[ERROR] Unable to listen on %s: %v\n", localAddr, err)
}
defer localConn.Close()
remoteAddr, err := net.ResolveUDPAddr("udp", targetAddr)
if err != nil {
log.Fatalf("[ERROR] Unable to resolve target address: %v\n", err)
}
buf := make([]byte, 4096)
log.Printf("[INFO] Listening on %s (UDP), forwarding to %s\n", localAddr, targetAddr)
for {
select {
case <-ctx.Done():
log.Printf("[INFO] Shutting down UDP proxy on %s\n", localAddr)
return
default:
n, addr, err := localConn.ReadFrom(buf)
if err != nil {
log.Printf("[ERROR] Failed to read from connection: %v\n", err)
continue
}
go func(data []byte, addr net.Addr) {
remoteConn, err := net.DialUDP("udp", nil, remoteAddr)
if err != nil {
log.Printf("[ERROR] Unable to connect to target: %v\n", err)
return
}
defer remoteConn.Close()
_, err = remoteConn.Write(data)
if err != nil {
log.Printf("[ERROR] Failed to write to target: %v\n", err)
return
}
n, _, err := remoteConn.ReadFrom(data)
if err != nil {
log.Printf("[ERROR] Failed to read from target: %v\n", err)
return
}
_, err = localConn.WriteTo(data[:n], addr)
if err != nil {
log.Printf("[ERROR] Failed to write back to source: %v\n", err)
}
}(buf[:n], addr)
}
}
}
func main() { func main() {
flag.Parse() flag.Parse()
configPath := os.Getenv("GOPROXY_CONFIG") configPath := os.Getenv("GOPROXY_CONFIG")
@ -143,15 +18,7 @@ func main() {
configPath = "goproxy.json" // Default path for Docker configPath = "goproxy.json" // Default path for Docker
} }
configData, err := os.ReadFile(configPath) config := ReadConfig(configPath)
if err != nil {
log.Fatalf("[ERROR] Failed to read config file (%s): %v\n", configPath, err)
}
var config ProxyConfig
if err := json5.Unmarshal(configData, &config); err != nil {
log.Fatalf("[ERROR] Failed to parse config file: %v\n", err)
}
ctx, cancel := context.WithCancel(context.Background()) ctx, cancel := context.WithCancel(context.Background())
var wg sync.WaitGroup var wg sync.WaitGroup

61
proxyTCP.go Normal file
View file

@ -0,0 +1,61 @@
package main
import (
"context"
"io"
"log"
"net"
"sync"
)
func handleTCPConnection(src net.Conn, targetAddr string) {
defer src.Close()
dst, err := net.Dial("tcp", targetAddr)
if err != nil {
log.Printf("[ERROR] Unable to connect to target: %v\n", err)
return
}
defer dst.Close()
done := make(chan struct{})
go func() {
io.Copy(dst, src)
done <- struct{}{}
}()
go func() {
io.Copy(src, dst)
done <- struct{}{}
}()
<-done
}
func startTCPProxy(ctx context.Context, wg *sync.WaitGroup, localAddr, targetAddr string) {
defer wg.Done()
listener, err := net.Listen("tcp", localAddr)
if err != nil {
log.Fatalf("[ERROR] Unable to listen on %s: %v\n", localAddr, err)
}
defer listener.Close()
log.Printf("[INFO] Listening on %s (TCP), forwarding to %s\n", localAddr, targetAddr)
for {
select {
case <-ctx.Done():
log.Printf("[INFO] Shutting down TCP proxy on %s\n", localAddr)
return
default:
conn, err := listener.Accept()
if err != nil {
log.Printf("[ERROR] Failed to accept connection: %v\n", err)
continue
}
go handleTCPConnection(conn, targetAddr)
}
}
}

67
proxyUDP.go Normal file
View file

@ -0,0 +1,67 @@
package main
import (
"context"
"log"
"net"
"sync"
)
func startUDPProxy(ctx context.Context, wg *sync.WaitGroup, localAddr, targetAddr string) {
defer wg.Done()
localConn, err := net.ListenPacket("udp", localAddr)
if err != nil {
log.Fatalf("[ERROR] Unable to listen on %s: %v\n", localAddr, err)
}
defer localConn.Close()
remoteAddr, err := net.ResolveUDPAddr("udp", targetAddr)
if err != nil {
log.Fatalf("[ERROR] Unable to resolve target address: %v\n", err)
}
buf := make([]byte, 4096)
log.Printf("[INFO] Listening on %s (UDP), forwarding to %s\n", localAddr, targetAddr)
for {
select {
case <-ctx.Done():
log.Printf("[INFO] Shutting down UDP proxy on %s\n", localAddr)
return
default:
n, addr, err := localConn.ReadFrom(buf)
if err != nil {
log.Printf("[ERROR] Failed to read from connection: %v\n", err)
continue
}
go func(data []byte, addr net.Addr) {
remoteConn, err := net.DialUDP("udp", nil, remoteAddr)
if err != nil {
log.Printf("[ERROR] Unable to connect to target: %v\n", err)
return
}
defer remoteConn.Close()
_, err = remoteConn.Write(data)
if err != nil {
log.Printf("[ERROR] Failed to write to target: %v\n", err)
return
}
n, _, err := remoteConn.ReadFrom(data)
if err != nil {
log.Printf("[ERROR] Failed to read from target: %v\n", err)
return
}
_, err = localConn.WriteTo(data[:n], addr)
if err != nil {
log.Printf("[ERROR] Failed to write back to source: %v\n", err)
}
}(buf[:n], addr)
}
}
}