From 4e2c548e977d0f85b53da795a848b5ec40e254ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=9E=D0=BB=D0=B5=D0=B3=20=D0=91=D0=BE=D1=80=D0=BE=D0=B4?= =?UTF-8?q?=D0=B8=D0=BD?= Date: Fri, 29 May 2026 13:34:07 +0200 Subject: [PATCH] working commit --- .gitignore | 12 ++++---- Makefile.am | 2 +- Makefile.in | 2 +- app/config/config.go | 40 +-------------------------- app/handler/connect.go | 56 +++++++++++++++++++++++++++++++++----- app/handler/copywctx.go | 42 ++++++++++++++++++++++++++++ app/handler/plaincall.go | 59 ++++++++++++++++++++++++++++++++++++++++ app/proxoper/connect.go | 23 ---------------- app/router/context.go | 4 +++ app/router/pathc.go | 2 +- app/router/router.go | 3 ++ app/server/server.go | 2 -- app/service/service.go | 20 ++++++++------ etc/mproxy/mproxyd.yaml | 10 +++++-- go.mod | 2 +- 15 files changed, 188 insertions(+), 91 deletions(-) create mode 100644 app/handler/copywctx.go create mode 100644 app/handler/plaincall.go delete mode 100644 app/proxoper/connect.go diff --git a/.gitignore b/.gitignore index df83a18..1c47080 100644 --- a/.gitignore +++ b/.gitignore @@ -3,8 +3,8 @@ autom4te.cache Makefile config.status config.log -cmd/mbased/mbased -cmd/mbasectl/mbasectl +cmd/mproxyd/mproxyd +cmd/mproxyctl/mproxyctl *.db *.db-shm *.db-wal @@ -13,12 +13,12 @@ cmd/mbasectl/mbasectl *.tar *.bin tmp -mbased -mbasectl +mproxyd +mproxyctl DIST *.tar.gz *.deb *.rpm -mbased.service +mproxyd.service variant.go -initrc/mbased +initrc/mproxyd diff --git a/Makefile.am b/Makefile.am index 7107ee9..e2b5ce3 100644 --- a/Makefile.am +++ b/Makefile.am @@ -24,7 +24,7 @@ mproxyd$(EXEEXT): $(mproxyd_SOURCES) $(EXTRA_mproxyd_SOURCES) env CGO_ENABLED=1 $(GO) build $(GOFLAGS) -o mproxyd$(EXEEXT) $(mproxyd_SOURCES) run: $(mproxyd_SOURCES) - cd cmd/mproxyd && env CGO_ENABLED=1 $(GO) run . --asDaemon=false --port=443 + cd cmd/mproxyd && env CGO_ENABLED=1 $(GO) run . --asDaemon=false CWD=$(shell pwd) diff --git a/Makefile.in b/Makefile.in index 11def6f..5fe18f8 100644 --- a/Makefile.in +++ b/Makefile.in @@ -1010,7 +1010,7 @@ mproxyd$(EXEEXT): $(mproxyd_SOURCES) $(EXTRA_mproxyd_SOURCES) env CGO_ENABLED=1 $(GO) build $(GOFLAGS) -o mproxyd$(EXEEXT) $(mproxyd_SOURCES) run: $(mproxyd_SOURCES) - cd cmd/mproxyd && env CGO_ENABLED=1 $(GO) run . --asDaemon=false --port=443 + cd cmd/mproxyd && env CGO_ENABLED=1 $(GO) run . --asDaemon=false format: @dirs=$$($(FIND) $(CWD)/app $(CWD)/cmd $(CWD)/pkg \ diff --git a/app/config/config.go b/app/config/config.go index b77a650..6c9a5f5 100644 --- a/app/config/config.go +++ b/app/config/config.go @@ -19,18 +19,8 @@ type Service struct { Port uint32 `json:"port" yaml:"port"` } -type Database struct { - Basepath string `json:"basepath" yaml:"basepath"` -} - -type Storage struct { - Basepath string `json:"basepath" yaml:"basepath"` -} - type Config struct { Service Service `json:"service" yaml:"service"` - Database Database `json:"database" yaml:"database"` - Storage Storage `json:"storage" yaml:"storage"` AsDaemon bool `json:"asDaemon" yaml:"asDaemon"` Logpath string `json:"logpath" yaml:"logpath"` Runpath string `json:"runpath" yaml:"runpath"` @@ -53,23 +43,11 @@ func NewConfig() *Config { runfile := fmt.Sprintf("%s.pid", srvname) runpath := filepath.Join(rundir, runfile) - //certpath := fmt.Sprintf("%s.crt", srvname) - //certpath = filepath.Join(confdir, certpath) - - //keypath := fmt.Sprintf("%s.crt", srvname) - //keypath = filepath.Join(confdir, keypath) - return &Config{ Service: Service{ - Address: "0.0.0.0", + Address: "[::]", Port: 1025, }, - Database: Database{ - Basepath: datadir, - }, - Storage: Storage{ - Basepath: datadir, - }, AsDaemon: false, Logpath: logpath, Runpath: runpath, @@ -124,20 +102,6 @@ func (conf *Config) ReadX509Cert() error { conf.X509Key = string(keyBytes) return err } - /* - if conf.X509Cert != "" && conf.X509Key != "" { - x509Cert, err := base64.StdEncoding.DecodeString(conf.X509Cert) - if err != nil { - return err - } - conf.X509Cert = string(x509Cert) - x509Key, err := base64.StdEncoding.DecodeString(conf.X509Key) - if err != nil { - return err - } - conf.X509Key = string(x509Key) - } - */ if conf.X509Cert == "" || conf.X509Key == "" { if conf.Hostname == "" { conf.Hostname, err = os.Hostname() @@ -152,8 +116,6 @@ func (conf *Config) ReadX509Cert() error { conf.X509Cert = string(certBytes) conf.X509Key = string(keyBytes) return err - } - return err } diff --git a/app/handler/connect.go b/app/handler/connect.go index e320848..24e5070 100644 --- a/app/handler/connect.go +++ b/app/handler/connect.go @@ -5,23 +5,65 @@ package handler import ( "net/http" + "sync" + "io" + "net" - "mproxy/app/proxoper" "mproxy/app/router" ) func (hand *Handler) ConnectTo(rctx *router.Context) { - hostaddr, _ := rctx.GetSubpath("hostaddr") - params := &proxoper.ConnectToParams{ - Hostaddr: hostaddr, - } - ctx := rctx.GetContext() - _, err := hand.prop.ConnectTo(ctx, params) + hostaddr := rctx.GetHost() + hand.logg.Debugf("Hostaddr: [%s]", hostaddr) + + destConn, err := net.Dial("tcp", hostaddr) + if err != nil { + hand.logg.Errorf("ConnectTo error: %v", err) + rctx.SetStatus(http.StatusInternalServerError) + return + } + if err != nil { hand.logg.Errorf("ConnectTo error: %v", err) rctx.SetStatus(http.StatusInternalServerError) return } + defer destConn.Close() + hijacker, hijackerOk := rctx.Writer.(http.Hijacker) + if !hijackerOk { + hand.logg.Errorf("Hijacking not OK") + rctx.SetStatus(http.StatusInternalServerError) + return + + } rctx.SetStatus(http.StatusOK) + clientConn, _, err := hijacker.Hijack() + if err != nil { + hand.logg.Errorf("Hijacking error: %v", err) + rctx.SetStatus(http.StatusInternalServerError) + return + } + var wg sync.WaitGroup + copyTo := func() { + defer wg.Done() + _, err = io.Copy(clientConn, destConn) + if err != nil { + hand.logg.Errorf("CopyTo error: %v", err) + return + } + } + copyFrom := func() { + defer wg.Done() + _, err = io.Copy(destConn, clientConn) + if err != nil { + hand.logg.Errorf("CopyFrom error: %v", err) + return + } + } + wg.Add(1) + go copyTo() + wg.Add(1) + go copyFrom() + wg.Wait() return } diff --git a/app/handler/copywctx.go b/app/handler/copywctx.go new file mode 100644 index 0000000..2aa7b28 --- /dev/null +++ b/app/handler/copywctx.go @@ -0,0 +1,42 @@ +/* + * Copyright 2026 Oleg Borodin + */ +package handler + +import ( + "context" + "errors" + "io" +) + +func CopyWithContext(ctx context.Context, writer io.Writer, reader io.Reader) (int64, error) { + var err error + var size int64 + var halt bool + buffer := make([]byte, 1024*4) + for { + select { + case <-ctx.Done(): + err = errors.New("Break copy by context") + break + default: + } + rsize, err := reader.Read(buffer) + if err == io.EOF { + err = nil + halt = true + } + if err != nil { + return size, err + } + wsize, err := writer.Write(buffer[0:rsize]) + size += int64(wsize) + if err != nil { + return size, err + } + if halt { + break + } + } + return size, err +} diff --git a/app/handler/plaincall.go b/app/handler/plaincall.go new file mode 100644 index 0000000..aa4e1b8 --- /dev/null +++ b/app/handler/plaincall.go @@ -0,0 +1,59 @@ +/* + * Copyright 2026 Oleg Borodin + */ +package handler + +import ( + "net/http" + "io" + "context" + "time" + + "mproxy/app/router" +) + +func (hand *Handler) PlainCall(rctx *router.Context) { + hostaddr := rctx.GetHost() + hand.logg.Debugf("Hostaddr: [%s]", hostaddr) + + + ctx := rctx.GetContext() + ctx, _ = context.WithTimeout(ctx, 5*time.Second) + reqMethod := rctx.Request.Method + reqUrl := rctx.URL().String() + reqBody := rctx.Request.Body + + + req, err := http.NewRequestWithContext(ctx, reqMethod, reqUrl, reqBody) + if err != nil { + hand.logg.Errorf("Create request error: %v", err) + rctx.SetStatus(http.StatusInternalServerError) + return + } + for key := range rctx.Request.Header { + val := rctx.Request.Header.Get(key) + req.Header.Add(key, val) + } + + httpClient := &http.Client{} + resp, err := httpClient.Do(req) + if err != nil { + hand.logg.Errorf("Call request error: %v", err) + rctx.SetStatus(http.StatusInternalServerError) + return + } + // Copy headers from remote side + for key := range resp.Header { + val := resp.Header.Get(key) + rctx.Writer.Header().Set(key, val) + } + // Copy status code + rctx.SetStatus(resp.StatusCode) + // Copy body + _, err = io.Copy(rctx.Writer, resp.Body) + if err != nil { + hand.logg.Errorf("Copy resp body error: %v", err) + return + } + return +} diff --git a/app/proxoper/connect.go b/app/proxoper/connect.go deleted file mode 100644 index d5c606a..0000000 --- a/app/proxoper/connect.go +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2026 Oleg Borodin - */ -package proxoper - -import ( - "context" - "io" -) - -type ConnectToParams struct { - Hostaddr string -} - -type ConnectToResult struct { - Stream io.Writer -} - -func (oper *Operator) ConnectTo(ctx context.Context, param *ConnectToParams) (*ConnectToResult, error) { - var err error - res := &ConnectToResult{} - return res, err -} diff --git a/app/router/context.go b/app/router/context.go index ece21c7..d9e4ac1 100644 --- a/app/router/context.go +++ b/app/router/context.go @@ -68,6 +68,10 @@ func (rctx *Context) GetQuery(key string) string { return rctx.Request.URL.Query().Get(key) } +func (rctx *Context) GetHost() string { + return rctx.Request.Host +} + func (rctx *Context) GetHeader(key string) string { return rctx.Request.Header.Get(key) } diff --git a/app/router/pathc.go b/app/router/pathc.go index fab8e11..e229a04 100644 --- a/app/router/pathc.go +++ b/app/router/pathc.go @@ -15,7 +15,7 @@ const ( startRegex byte = '{' stopRegex byte = '}' - defaultRegexp = `[a-zA-Z0-9_\.]+` + defaultRegexp = `[a-zA-Z0-9_\.:]+` ) func pathCompiler(path string) (string, error) { diff --git a/app/router/router.go b/app/router/router.go index f5d8633..e12f759 100644 --- a/app/router/router.go +++ b/app/router/router.go @@ -158,6 +158,9 @@ func (route Route) Match(req *http.Request) bool { if req.Method != route.Method { return false } + if req.Method == http.MethodConnect { + return true + } match := route.Regexp.MatchString(req.URL.Path) if match { return true diff --git a/app/server/server.go b/app/server/server.go index 0c5eeee..07b4208 100644 --- a/app/server/server.go +++ b/app/server/server.go @@ -70,8 +70,6 @@ func (srv *Server) SetRundir(dir string) { } func (srv *Server) SetDatadir(dir string) { - srv.conf.Database.Basepath = dir - srv.conf.Storage.Basepath = dir srv.conf.Datadir = dir } diff --git a/app/service/service.go b/app/service/service.go index af56141..0ce5ca9 100644 --- a/app/service/service.go +++ b/app/service/service.go @@ -30,9 +30,9 @@ type Service struct { logg *logger.Logger hsrv *http.Server + listen net.Listener address string portnum uint32 - listen net.Listener x509cert string x509key string protocol string @@ -46,7 +46,7 @@ func NewService(params *ServiceParams) (*Service, error) { portnum: params.Portnum, x509cert: params.X509cert, x509key: params.X509key, - protocol: "TCP", + protocol: "tcp", } svc.logg = logger.NewLoggerWithSubject("service") return svc, err @@ -54,7 +54,7 @@ func NewService(params *ServiceParams) (*Service, error) { func (svc *Service) Build() error { var err error - svc.logg.Infof("Service build ") + svc.logg.Infof("Service build") svc.rout = router.NewRouter() @@ -64,7 +64,14 @@ func (svc *Service) Build() error { svc.rout.Use(svc.hand.AuthMiddleware) svc.rout.Get(`/v3/api/service/hello`, svc.hand.SendHello) - svc.rout.Connect(`{hostaddr}`, svc.hand.ConnectTo) + + svc.rout.Connect(``, svc.hand.ConnectTo) + + svc.rout.Delete(`{uri:.*}`, svc.hand.PlainCall) + svc.rout.Get(`{uri:.*}`, svc.hand.PlainCall) + svc.rout.Head(`{uri:.*}`, svc.hand.PlainCall) + svc.rout.Patch(`{uri:.*}`, svc.hand.PlainCall) + svc.rout.Post(`{uri:.*}`, svc.hand.PlainCall) svc.rout.NotFound(svc.hand.NotFound) @@ -73,26 +80,23 @@ func (svc *Service) Build() error { svc.logg.Infof("%s\t%s", item.Method, item.RawPath) } - const useTLS = true + const useTLS = false if useTLS { tlsCert, err := tls.X509KeyPair([]byte(svc.x509cert), []byte(svc.x509key)) if err != nil { return err } - tlsConfig := tls.Config{ Certificates: []tls.Certificate{tlsCert}, ClientAuth: tls.NoClientCert, InsecureSkipVerify: true, } - listenAddress := fmt.Sprintf("%s:%d", svc.address, svc.portnum) svc.listen, err = tls.Listen(svc.protocol, listenAddress, &tlsConfig) if err != nil { return err } - } else { listenAddress := fmt.Sprintf("%s:%d", svc.address, svc.portnum) svc.listen, err = net.Listen(svc.protocol, listenAddress) diff --git a/etc/mproxy/mproxyd.yaml b/etc/mproxy/mproxyd.yaml index 2e06593..e845ee8 100644 --- a/etc/mproxy/mproxyd.yaml +++ b/etc/mproxy/mproxyd.yaml @@ -1,5 +1,11 @@ -certpath: mbased.crt -keypath: mbased.key + +certpath: mproxyd.crt +keypath: mproxyd.key runUser: root +service: + address: 127.0.0.1 + port: 9000 + + diff --git a/go.mod b/go.mod index eab76c8..1afcc59 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,6 @@ module mproxy -go 1.26.1 +go 1.26.2 require ( github.com/google/uuid v1.6.0