mirror of
https://github.com/Merith-TK/simpleproxy.git
synced 2025-02-22 15:50:25 +00:00
fracturize
This commit is contained in:
parent
6e0b8f546b
commit
0b300f64cc
7 changed files with 163 additions and 135 deletions
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
simpleproxy*
|
||||||
|
*.exe
|
31
config.go
Normal file
31
config.go
Normal 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
2
go.mod
|
@ -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
BIN
goproxy
Binary file not shown.
135
main.go
135
main.go
|
@ -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
61
proxyTCP.go
Normal 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
67
proxyUDP.go
Normal 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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue