Signed-off-by: Matheus Sampaio Queiroga <srherobrine20@gmail.com>
This commit is contained in:
Matheus Sampaio Queiroga 2024-06-09 23:58:37 -03:00
parent 15473975f8
commit 964544e08c
Signed by: Sirherobrine23
GPG Key ID: 01CCABE2580AFEBC
11 changed files with 497 additions and 145 deletions

1
.gitignore vendored

@ -1,2 +1,3 @@
*.exe
*.db
*.log

@ -2,8 +2,10 @@ package client
import (
"bytes"
"encoding/json"
"errors"
"io"
"log"
"net"
"net/netip"
"time"
@ -72,6 +74,8 @@ func (client Client) Recive() (res *proto.Response, err error) {
if err = res.Reader(bytes.NewBuffer(recBuff[:n])); err != nil {
return
}
d,_:=json.Marshal(res)
log.Println(string(d))
return
}

85
cmd/client/client.go Normal file

@ -0,0 +1,85 @@
package client
import (
"fmt"
"io"
"net"
"net/netip"
"github.com/google/uuid"
"github.com/urfave/cli/v2"
"sirherobrine23.org/Minecraft-Server/go-pproxit/client"
"sirherobrine23.org/Minecraft-Server/go-pproxit/proto"
)
var CmdClient = cli.Command{
Name: "client",
Aliases: []string{"c"},
Usage: "connect to controller server and bind new requests to local port",
Flags: []cli.Flag{
&cli.StringFlag{
Name: "url",
Required: true,
Aliases: []string{"host", "u"},
Usage: `host string to connect to controller, example: "example.com:5522"`,
},
&cli.StringFlag{
Name: "token",
Required: true,
Usage: "agent token",
Aliases: []string{"t"},
Action: func(ctx *cli.Context, s string) error {
if _, err := uuid.Parse(s); err == nil {
return nil
} else if len(s) == len(proto.AgentAuth{}) {
return nil
}
return fmt.Errorf("set valid token")
},
},
&cli.StringFlag{
Name: "dial",
Required: true,
Usage: `dial connection, default is "localhost:80"`,
Aliases: []string{"d"},
},
},
Action: func(ctx *cli.Context) (err error) {
var addr netip.AddrPort
if addr, err = netip.ParseAddrPort(ctx.String("url")); err != nil {
return
}
client := client.NewClient(addr, [36]byte([]byte(ctx.String("token"))))
var info *proto.AgentInfo
if info, err = client.Dial(); err != nil {
return err
}
fmt.Printf("Connected, Remote port: %d\n", info.LitenerPort)
fmt.Printf(" Remote address: %s\n", info.AddrPort.String())
go client.Backgroud()
localConnect := ctx.String("dial")
for {
select {
case tcp := <-client.NewTCPClient:
go func() {
conn, err := net.Dial("tcp", localConnect)
if err != nil {
return
}
go io.Copy(conn, tcp)
go io.Copy(tcp, conn)
}()
case udp := <-client.NewUDPClient:
go func () {
conn, err := net.DialUDP("udp", nil, net.UDPAddrFromAddrPort(netip.MustParseAddrPort(localConnect)))
if err != nil {
return
}
go io.Copy(conn, udp)
go io.Copy(udp, conn)
}()
}
}
},
}

@ -2,65 +2,26 @@ package main
import (
"fmt"
"io"
"log"
"net"
"net/netip"
"os"
"os/signal"
"time"
"sirherobrine23.org/Minecraft-Server/go-pproxit/client"
"sirherobrine23.org/Minecraft-Server/go-pproxit/server"
"github.com/urfave/cli/v2"
"sirherobrine23.org/Minecraft-Server/go-pproxit/cmd/client"
"sirherobrine23.org/Minecraft-Server/go-pproxit/cmd/server"
)
var description string = `pproxit is a proxy that allows anyone to host a server without port forwarding. We use tunneling. Only the server needs to run the program, not every player!`
func main() {
cctrl := make(chan os.Signal, 1)
signal.Notify(cctrl, os.Interrupt)
var port uint16 = 5522
server := server.NewServer(nil)
go server.Listen(port)
time.Sleep(time.Second)
fmt.Printf("Server listen on :%d\n", port)
go func() {
client := client.NewClient(netip.AddrPortFrom(netip.IPv6Loopback(), port), [36]byte{})
info, err := client.Dial()
if err != nil {
panic(err)
}
go client.Backgroud() // Recive data
fmt.Printf("Client remote: %s\n", client.Conn.RemoteAddr().String())
fmt.Printf("Client Listened on %d\n", info.LitenerPort)
localConnect := "127.0.0.1:5201"
for {
select {
case tcp := <-client.NewTCPClient:
go func() {
conn, err := net.Dial("tcp", localConnect)
if err != nil {
log.Println(err)
return
}
go io.Copy(conn, tcp)
go io.Copy(tcp, conn)
}()
case udp := <-client.NewUDPClient:
go func () {
conn, err := net.DialUDP("udp", nil, net.UDPAddrFromAddrPort(netip.MustParseAddrPort(localConnect)))
if err != nil {
log.Println(err)
return
}
go io.Copy(conn, udp)
go io.Copy(udp, conn)
}()
}
}
}()
<-cctrl
fmt.Println("Closing controller")
app := cli.NewApp()
app.Name = "pproxit"
app.Description = description
app.EnableBashCompletion = true
app.HideHelpCommand = true
app.Commands = []*cli.Command{
&server.CmdServer,
&client.CmdClient,
}
if err := app.Run(os.Args); err != nil {
fmt.Fprintf(app.ErrWriter, "Error: %v\n", err)
os.Exit(1)
}
}

42
cmd/server/server.go Normal file

@ -0,0 +1,42 @@
package server
import (
"github.com/urfave/cli/v2"
"sirherobrine23.org/Minecraft-Server/go-pproxit/proto"
"sirherobrine23.org/Minecraft-Server/go-pproxit/server"
)
var CmdServer = cli.Command{
Name: "server",
Usage: "Create local server and open controller ports",
Aliases: []string{"s"},
Flags: []cli.Flag{
&cli.IntFlag{
Name: "port",
Value: 5522,
Aliases: []string{"p"},
Usage: "Set controller port to watcher UDP requests",
},
&cli.StringFlag{
Name: "log",
Value: "silence",
Aliases: []string{"l"},
Usage: "set server log: silence, 0 or verbose, 2",
},
&cli.StringFlag{
Name: "db",
Value: "./pproxit.db",
Aliases: []string{"d"},
Usage: "sqlite file path",
},
},
Action: func(ctx *cli.Context) error {
calls, err := NewCall(ctx.String("db"))
if err != nil {
return err
}
pproxitServer := server.NewServer(calls)
pproxitServer.RequestBuffer = proto.PacketDataSize * 2 // More initial buffer request
return pproxitServer.Listen(uint16(ctx.Int("port")))
},
}

57
cmd/server/servercall.go Normal file

@ -0,0 +1,57 @@
package server
import (
"time"
_ "modernc.org/sqlite"
"sirherobrine23.org/Minecraft-Server/go-pproxit/server"
"xorm.io/xorm"
"xorm.io/xorm/names"
)
type serverCalls struct {
XormEngine *xorm.Engine
}
type Tun struct {
ID int64 `xorm:"pk"` // Tunnel ID
User int64 // Agent ID
Token [36]byte // Tunnel Token
Proto uint8 // Proto accept
PortListen uint16 // Port listen agent
}
type User struct {
ID int64 `xorm:"pk"` // Client ID
Username string `xorm:"varchar(32) notnull unique 'user'"` // Username
FullName string `xorm:"text notnull notnull 'name'"` // Real name for user
AccountStatus int8 `xorm:"BIT notnull 'status'"` // Account Status
CreateAt time.Time `xorm:"created"` // Create date
UpdateAt time.Time `xorm:"updated"` // Update date
}
func NewCall(DBConn string) (call *serverCalls, err error) {
call = new(serverCalls)
if call.XormEngine, err = xorm.NewEngine("sqlite", DBConn); err != nil {
return
}
call.XormEngine.SetMapper(names.SameMapper{})
call.XormEngine.CreateTables(Tun{}, User{})
return
}
func (call serverCalls) AgentShutdown(Token [36]byte) (err error) { return } // Ignore
func (call serverCalls) AgentInfo(Token [36]byte) (server.TunnelInfo, error) {
var tun = Tun{Token: Token}
if ok, err := call.XormEngine.Get(&tun); err != nil || !ok {
if !ok {
return server.TunnelInfo{}, server.ErrNoAgent
}
return server.TunnelInfo{}, err
}
return server.TunnelInfo{
PortListen: tun.PortListen,
Proto: tun.Proto,
}, nil
}

32
go.mod

@ -1,3 +1,35 @@
module sirherobrine23.org/Minecraft-Server/go-pproxit
go 1.22.3
require (
github.com/google/uuid v1.6.0
github.com/urfave/cli/v2 v2.27.2
modernc.org/sqlite v1.30.0
xorm.io/xorm v1.3.9
)
require (
github.com/cpuguy83/go-md2man/v2 v2.0.4 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/goccy/go-json v0.8.1 // indirect
github.com/golang/snappy v0.0.4 // indirect
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/ncruces/go-strftime v0.1.9 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/russross/blackfriday/v2 v2.1.0 // indirect
github.com/syndtr/goleveldb v1.0.0 // indirect
github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 // indirect
golang.org/x/sys v0.19.0 // indirect
modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 // indirect
modernc.org/libc v1.50.9 // indirect
modernc.org/mathutil v1.6.0 // indirect
modernc.org/memory v1.8.0 // indirect
modernc.org/strutil v1.2.0 // indirect
modernc.org/token v1.1.0 // indirect
xorm.io/builder v0.3.11-0.20220531020008-1bd24a7dc978 // indirect
)

113
go.sum

@ -0,0 +1,113 @@
gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a h1:lSA0F4e9A2NcQSqGqTOXqu2aRi/XEQxDCBwM8yJtE6s=
gitea.com/xorm/sqlfiddle v0.0.0-20180821085327-62ce714f951a/go.mod h1:EXuID2Zs0pAQhH8yz+DNjUbjppKQzKFAn28TMYPB6IU=
github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4=
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc=
github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI=
github.com/goccy/go-json v0.8.1 h1:4/Wjm0JIJaTDm8K1KcGrLHJoa8EsJ13YWeX+6Kfq6uI=
github.com/goccy/go-json v0.8.1/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd h1:gbpYu9NMq8jhDVbvlGkMFWCjLFlqqEZjEmObmhUy6Vo=
github.com/google/pprof v0.0.0-20240409012703-83162a5b38cd/go.mod h1:kf6iHlnVGwgKolg33glAes7Yg/8iWP8ukqeldJSO7jw=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y=
github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdhx/f4=
github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0 h1:WSHQ+IS43OoUrWtD1/bbclrwK8TTH5hzp+umCiuxHgs=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v1.4.3 h1:RE1xgDvH7imwFD45h+u2SgIfERHlS2yNG4DObb5BSKU=
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
github.com/urfave/cli/v2 v2.27.2 h1:6e0H+AkS+zDckwPCUrZkKX38mRaau4nL2uipkJpbkcI=
github.com/urfave/cli/v2 v2.27.2/go.mod h1:g0+79LmHHATl7DAcHO99smiR/T7uGLw84w8Y42x+4eM=
github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913 h1:+qGGcbkzsfDQNPPe9UDgpxAWQrhbbBXOYJFQDq/dtJw=
github.com/xrash/smetrics v0.0.0-20240312152122-5f08fbb34913/go.mod h1:4aEEwZQutDLsQv2Deui4iYQ6DWTxR14g6m8Wv88+Xqk=
golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic=
golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd h1:nTDtHvHSdCn1m6ITfMRqtOd/9+7a3s8RBNOZ3eYZzJA=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o=
golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc=
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/tools v0.19.0 h1:tfGCXNR1OsFG+sVdLAitlpjAvD/I6dHDKnYrpEZUHkw=
golang.org/x/tools v0.19.0/go.mod h1:qoJWxmGSIBmAeriMx19ogtrEPrGtDbPK634QFIcLAhc=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
modernc.org/cc/v4 v4.21.2 h1:dycHFB/jDc3IyacKipCNSDrjIC0Lm1hyoWOZTRR20Lk=
modernc.org/cc/v4 v4.21.2/go.mod h1:HM7VJTZbUCR3rV8EYBi9wxnJ0ZBRiGE5OeGXNA0IsLQ=
modernc.org/ccgo/v4 v4.17.8 h1:yyWBf2ipA0Y9GGz/MmCmi3EFpKgeS7ICrAFes+suEbs=
modernc.org/ccgo/v4 v4.17.8/go.mod h1:buJnJ6Fn0tyAdP/dqePbrrvLyr6qslFfTbFrCuaYvtA=
modernc.org/fileutil v1.3.0 h1:gQ5SIzK3H9kdfai/5x41oQiKValumqNTDXMvKo62HvE=
modernc.org/fileutil v1.3.0/go.mod h1:XatxS8fZi3pS8/hKG2GH/ArUogfxjpEKs3Ku3aK4JyQ=
modernc.org/gc/v2 v2.4.1 h1:9cNzOqPyMJBvrUipmynX0ZohMhcxPtMccYgGOJdOiBw=
modernc.org/gc/v2 v2.4.1/go.mod h1:wzN5dK1AzVGoH6XOzc3YZ+ey/jPgYHLuVckd62P0GYU=
modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6 h1:5D53IMaUuA5InSeMu9eJtlQXS2NxAhyWQvkKEgXZhHI=
modernc.org/gc/v3 v3.0.0-20240107210532-573471604cb6/go.mod h1:Qz0X07sNOR1jWYCrJMEnbW/X55x206Q7Vt4mz6/wHp4=
modernc.org/libc v1.50.9 h1:hIWf1uz55lorXQhfoEoezdUHjxzuO6ceshET/yWjSjk=
modernc.org/libc v1.50.9/go.mod h1:15P6ublJ9FJR8YQCGy8DeQ2Uwur7iW9Hserr/T3OFZE=
modernc.org/mathutil v1.6.0 h1:fRe9+AmYlaej+64JsEEhoWuAYBkOtQiMEU7n/XgfYi4=
modernc.org/mathutil v1.6.0/go.mod h1:Ui5Q9q1TR2gFm0AQRqQUaBWFLAhQpCwNcuhBOSedWPo=
modernc.org/memory v1.8.0 h1:IqGTL6eFMaDZZhEWwcREgeMXYwmW83LYW8cROZYkg+E=
modernc.org/memory v1.8.0/go.mod h1:XPZ936zp5OMKGWPqbD3JShgd/ZoQ7899TUuQqxY+peU=
modernc.org/opt v0.1.3 h1:3XOZf2yznlhC+ibLltsDGzABUGVx8J6pnFMS3E4dcq4=
modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
modernc.org/sortutil v1.2.0 h1:jQiD3PfS2REGJNzNCMMaLSp/wdMNieTbKX920Cqdgqc=
modernc.org/sortutil v1.2.0/go.mod h1:TKU2s7kJMf1AE84OoiGppNHJwvB753OYfNl2WRb++Ss=
modernc.org/sqlite v1.30.0 h1:8YhPUs/HTnlEgErn/jSYQTwHN/ex8CjHHjg+K9iG7LM=
modernc.org/sqlite v1.30.0/go.mod h1:cgkTARJ9ugeXSNaLBPK3CqbOe7Ec7ZhWPoMFGldEYEw=
modernc.org/strutil v1.2.0 h1:agBi9dp1I+eOnxXeiZawM8F4LawKv4NzGWSaLfyeNZA=
modernc.org/strutil v1.2.0/go.mod h1:/mdcBmfOibveCTBxUl5B5l6W+TTH1FXPLHZE6bTosX0=
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
xorm.io/builder v0.3.11-0.20220531020008-1bd24a7dc978 h1:bvLlAPW1ZMTWA32LuZMBEGHAUOcATZjzHcotf3SWweM=
xorm.io/builder v0.3.11-0.20220531020008-1bd24a7dc978/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=
xorm.io/xorm v1.3.9 h1:TUovzS0ko+IQ1XnNLfs5dqK1cJl1H5uHpWbWqAQ04nU=
xorm.io/xorm v1.3.9/go.mod h1:LsCCffeeYp63ssk0pKumP6l96WZcHix7ChpurcLNuMw=

@ -1,91 +1,140 @@
package udplisterner
import (
"io"
"net"
"net/netip"
"sync"
"sirherobrine23.org/Minecraft-Server/go-pproxit/internal/pipe"
)
type clientInfo struct {
WriteSize int // Size to Write
Conn net.Conn // Client Pipe
}
type UdpListerner struct {
MTU func() uint64
udpConn *net.UDPConn
clients map[string]net.Conn
newClient chan any
readSize int // UDPConn size to reader
udpConn *net.UDPConn // UDPConn root
clientInfo *sync.Map // Storage *clientInfo
newClient chan any // Accept connection channel or error
}
func (udpConn UdpListerner) Close() error {
for addr, cli := range udpConn.clients {
cli.Close()
delete(udpConn.clients, addr)
func ListenUDPAddr(network string, address *net.UDPAddr) (UdpListen *UdpListerner, err error) {
UdpListen = new(UdpListerner)
if UdpListen.udpConn, err = net.ListenUDP(network, address); err != nil {
return nil, err
}
close(udpConn.newClient)
return udpConn.udpConn.Close()
UdpListen.readSize = 1024 // Initial buffer reader
UdpListen.newClient = make(chan any)
UdpListen.clientInfo = new(sync.Map)
go UdpListen.backgroud() // Recive new requests
return UdpListen, nil
}
func (udpConn UdpListerner) Addr() net.Addr {
return udpConn.udpConn.LocalAddr()
func ListenAddrPort(network string, address netip.AddrPort) (*UdpListerner, error) {
return ListenUDPAddr(network, net.UDPAddrFromAddrPort(address))
}
func (udpConn UdpListerner) Accept() (net.Conn, error) {
if data, ok := <-udpConn.newClient; ok {
if err, isErr := data.(error); isErr {
func Listen(network, address string) (*UdpListerner, error) {
local, err := net.ResolveUDPAddr(network, address)
if err != nil {
return nil, err
}
return ListenUDPAddr(network, local)
}
// Close clients and close client channel
func (udp *UdpListerner) Close() error {
close(udp.newClient) // Close channel to new accepts
var toDelete map[string]*clientInfo
udp.clientInfo.Range(func(key, value any) bool {
toDelete[key.(string)] = value.(*clientInfo)
return true
})
for key, info := range toDelete {
info.Conn.Close()
udp.clientInfo.Delete(key)
}
return nil
}
func (udp *UdpListerner) CloseClient(clientAddrPort string) {
client, ok := udp.clientInfo.LoadAndDelete(clientAddrPort)
if !ok {
return
}
agent := client.(clientInfo)
agent.Conn.Close()
}
func (udp UdpListerner) Addr() net.Addr {
if udp.udpConn == nil {
return &net.UDPAddr{}
}
return udp.udpConn.LocalAddr()
}
func (udp UdpListerner) Accept() (net.Conn, error) {
if conn, ok := <-udp.newClient; ok {
if err, isErr := conn.(error); isErr {
return nil, err
}
return data.(net.Conn), nil
return conn.(*clientInfo).Conn, nil
}
return nil, net.ErrClosed
}
func (udp *UdpListerner) backgroud() {
for {
buffer := make([]byte, udp.MTU())
n, from, err := udp.udpConn.ReadFromUDP(buffer)
readBuffer := make([]byte, udp.readSize) // Make reader size
n, from, err := udp.udpConn.ReadFromUDP(readBuffer)
if err != nil {
udp.newClient <- err // Send to accept error
return
} else if toListener, exist := udp.clients[from.String()]; exist {
// Send in backgroud
go func() {
if _, err := toListener.Write(buffer[:n]); err != nil {
toListener.Close()
delete(udp.clients, from.String()) // Remove from clients
}
}()
continue // Call next request
if err == io.EOF || err == io.ErrUnexpectedEOF {
udp.Close() // Close clients
break
}
continue
} else if n-udp.readSize == 0 {
udp.readSize += 500 // Add 500 Bytes to reader
}
// Create new connection and send to accept
toClinet, toListener := pipe.CreatePipe(udp.udpConn.LocalAddr(), from)
udp.clients[from.String()] = toListener // Set listerner clients
udp.newClient <- toClinet // return to accept
// Check if exists current connection
if client, ok := udp.clientInfo.Load(from.String()); ok {
toListener := client.(*clientInfo)
toListener.Conn.Write(readBuffer[:n]) // n size from Buffer to client
continue // Contine loop
}
go func() {
toListener.Write(buffer[:n]) // Write buffer to new pipe
for {
buffer := make([]byte, udp.MTU())
n, err := toListener.Read(buffer)
if err != nil {
toListener.Close()
delete(udp.clients, from.String()) // Remove from clients
return
// Create new client
newClient := new(clientInfo)
newClient.WriteSize = n // Same Size from reader buffer
var agentPipe net.Conn
newClient.Conn, agentPipe = pipe.CreatePipe(udp.udpConn.LocalAddr(), from)
udp.newClient <- newClient // Send to accept
udp.clientInfo.Store(from.String(), newClient)
go agentPipe.Write(readBuffer[:n]) // n size from Buffer to client
go func() {
for {
client, ok := udp.clientInfo.Load(from.String())
if !ok {
udp.clientInfo.Delete(from.String())
agentPipe.Close()
break // bye-bye
}
newClient := client.(*clientInfo)
writeBuffer := make([]byte, newClient.WriteSize)
n, err := agentPipe.Read(writeBuffer)
if err != nil {
udp.clientInfo.Delete(from.String())
agentPipe.Close()
break
}
go udp.udpConn.WriteToUDP(writeBuffer[:n], from)
}
udp.udpConn.WriteToUDP(buffer[:n], from)
}
}()
}()
}
}
func Listen(UdpProto string, Address netip.AddrPort, MTU func() uint64) (net.Listener, error) {
conn, err := net.ListenUDP(UdpProto, net.UDPAddrFromAddrPort(Address))
if err != nil {
return nil, err
}
udp := new(UdpListerner)
udp.udpConn = conn
udp.newClient = make(chan any)
udp.clients = make(map[string]net.Conn)
udp.MTU = MTU
go udp.backgroud()
return udp, nil
}

36
server/call.go Normal file

@ -0,0 +1,36 @@
package server
import (
"net"
"sirherobrine23.org/Minecraft-Server/go-pproxit/proto"
)
func getFreePort() (int, error) {
addr, err := net.ResolveTCPAddr("tcp", "localhost:0")
if err != nil {
return 0, err
}
l, err := net.ListenTCP("tcp", addr)
if err != nil {
return 0, err
}
defer l.Close()
return l.Addr().(*net.TCPAddr).Port, nil
}
// Accept any agent in ramdom port
type DefaultCall struct{}
func (DefaultCall) AgentShutdown(Token [36]byte) error { return nil }
func (d DefaultCall) AgentInfo(Token [36]byte) (TunnelInfo, error) {
port, err := getFreePort()
if err == nil {
return TunnelInfo{
PortListen: uint16(port),
Proto: proto.ProtoBoth,
}, nil
}
return TunnelInfo{}, err
}

@ -3,6 +3,7 @@ package server
import (
"bytes"
"errors"
"fmt"
"io"
"log"
"net"
@ -39,35 +40,6 @@ type ServerCalls interface {
AgentShutdown(Token [36]byte) error
}
// Accept any agent in ramdom port
type DefaultCall struct{}
func (DefaultCall) getFreePort() (int, error) {
addr, err := net.ResolveTCPAddr("tcp", "localhost:0")
if err != nil {
return 0, err
}
l, err := net.ListenTCP("tcp", addr)
if err != nil {
return 0, err
}
defer l.Close()
return l.Addr().(*net.TCPAddr).Port, nil
}
func (DefaultCall) AgentShutdown(Token [36]byte) error { return nil }
func (d DefaultCall) AgentInfo(Token [36]byte) (TunnelInfo, error) {
port, err := d.getFreePort()
if err == nil {
return TunnelInfo{
PortListen: uint16(port),
Proto: proto.ProtoBoth,
}, nil
}
return TunnelInfo{}, err
}
type Server struct {
RequestBuffer uint64 // Request Buffer
Tunnels map[string]Tunnel // Tunnels listened
@ -322,7 +294,7 @@ func (server *Server) Listen(ControllerPort uint16) (err error) {
if err != nil {
if err == ErrNoAgent {
// Client not found
res.BadRequest = true
res.Unauthorized = true
} else {
// Cannot process request resend
res.SendAuth = true
@ -344,7 +316,7 @@ func (server *Server) Listen(ControllerPort uint16) (err error) {
go tun.TCPAccepts() // Make accepts new requests
}
if info.Proto == 3 || info.Proto == 2 {
tun.UDPListener, err = udplisterner.Listen("udp", netip.AddrPortFrom(netip.IPv4Unspecified(), info.PortListen), func() uint64 {return server.RequestBuffer})
tun.UDPListener, err = udplisterner.Listen("udp", fmt.Sprintf("0.0.0.0:%d", info.PortListen))
if err != nil {
if tun.TCPListener != nil {
tun.TCPListener.Close()