From db469978f6d885c1356b236d6161ff8cf74761d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Kowal?= Date: Wed, 13 Mar 2024 17:17:38 +0100 Subject: [PATCH] #10 add outline of webscoket visualizer --- cmd/proxy/server/server.go | 5 ++++- go.mod | 2 ++ go.sum | 6 ++++-- internal/request/wrapper.go | 5 +++++ internal/visualize/server.go | 31 +++++++++++++++++++++++++++++-- internal/visualize/visualizer.go | 17 +++++++++++++++++ internal/waf/handler.go | 23 ++++++++++++----------- 7 files changed, 73 insertions(+), 16 deletions(-) create mode 100644 internal/visualize/visualizer.go diff --git a/cmd/proxy/server/server.go b/cmd/proxy/server/server.go index b2aa0f4..77c23b2 100644 --- a/cmd/proxy/server/server.go +++ b/cmd/proxy/server/server.go @@ -7,6 +7,7 @@ import ( "os" "os/signal" "time" + "waffle/internal/visualize" "waffle/internal/certificate" "waffle/internal/config" @@ -44,7 +45,9 @@ func Run(ctx context.Context, yamlConfigBytes []byte, certificates embed.FS) err limiter := ratelimit.NewInMemoryLimiter(time.Minute * 5) - guardHandler := waf.NewHandler(redirect.NewHandler(yamlDnsProvider), defender, limiter) + visualizeServer := visualize.NewServer(":8081") + + guardHandler := waf.NewHandler(redirect.NewHandler(yamlDnsProvider), defender, limiter, visualizeServer.GetVisualizer()) proxyServer := proxy.NewServer(":8080", certificateProvider, guardHandler) diff --git a/go.mod b/go.mod index 0da559c..08f0997 100644 --- a/go.mod +++ b/go.mod @@ -9,12 +9,14 @@ require ( github.com/goccy/go-yaml v1.11.3 github.com/google/uuid v1.6.0 github.com/patrickmn/go-cache v2.1.0+incompatible + nhooyr.io/websocket v1.8.10 ) require ( github.com/fatih/color v1.16.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect + golang.org/x/crypto v0.14.0 // indirect golang.org/x/sys v0.17.0 // indirect golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect ) diff --git a/go.sum b/go.sum index c95766c..bc5d758 100644 --- a/go.sum +++ b/go.sum @@ -27,11 +27,13 @@ github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWE github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= -golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= -golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= +golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= +golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU= golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= +nhooyr.io/websocket v1.8.10 h1:mv4p+MnGrLDcPlBoWsvPP7XCzTYMXP9F9eIGoKbgx7Q= +nhooyr.io/websocket v1.8.10/go.mod h1:rN9OFWIUwuxg4fR5tELlYC04bXYowCP9GX47ivo2l+c= diff --git a/internal/request/wrapper.go b/internal/request/wrapper.go index b50aafe..f52c536 100644 --- a/internal/request/wrapper.go +++ b/internal/request/wrapper.go @@ -3,6 +3,9 @@ package request import ( "net" "net/http" + "time" + + "waffle/internal/clock" ) // Wrapper is used to wrap request, in order to not pass it every time. @@ -11,11 +14,13 @@ type Wrapper struct { // IPAddress is a real ip address of the client. The difference between this one and request remoteAddr is // that it can be read from the headers (i.e. if request was forwarded by some kind of proxy). IPAddress *net.IP + IssuedAt time.Time } func NewRequestWrapper(r *http.Request, ipAddress *net.IP) *Wrapper { return &Wrapper{ Request: r, IPAddress: ipAddress, + IssuedAt: clock.Now(), } } diff --git a/internal/visualize/server.go b/internal/visualize/server.go index 473e0c6..67e0745 100644 --- a/internal/visualize/server.go +++ b/internal/visualize/server.go @@ -1,11 +1,38 @@ package visualize +import ( + "context" + "net/http" + + "nhooyr.io/websocket" +) + type Server struct { - port string + port string + visualizer *Visualizer + clients map[] } func NewServer(port string) *Server { return &Server{ - port: port, + port: port, + visualizer: NewVisualizer(), + } +} + +func (s *Server) GetVisualizer() *Visualizer { + return s.visualizer +} + +func (s *Server) Start(ctx context.Context) { + handlerFunc := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + c, err := websocket.Accept(w,r, nil) + if err != nil { + + } + }) + + if err := http.ListenAndServe(s.port, handlerFunc); err != nil { + } } diff --git a/internal/visualize/visualizer.go b/internal/visualize/visualizer.go new file mode 100644 index 0000000..ce10037 --- /dev/null +++ b/internal/visualize/visualizer.go @@ -0,0 +1,17 @@ +package visualize + +import "waffle/internal/request" + +type Visualizer struct { + requestWrappersChan chan request.Wrapper +} + +func NewVisualizer() *Visualizer { + return &Visualizer{ + requestWrappersChan: make(chan request.Wrapper), + } +} + +func (v *Visualizer) VisualizeRequestWrapper(rw request.Wrapper) { + v.requestWrappersChan <- rw +} diff --git a/internal/waf/handler.go b/internal/waf/handler.go index 0267b2e..673dc85 100644 --- a/internal/waf/handler.go +++ b/internal/waf/handler.go @@ -4,6 +4,7 @@ import ( "fmt" "net/http" "time" + "waffle/internal/visualize" "waffle/internal/ratelimit" "waffle/internal/request" @@ -11,20 +12,18 @@ import ( ) type Handler struct { - next http.Handler - defender guard.Defender - limiter ratelimit.Limiter + next http.Handler + defender guard.Defender + limiter ratelimit.Limiter + visualizer *visualize.Visualizer } -func NewHandler( - next http.Handler, - defender guard.Defender, - limiter ratelimit.Limiter, -) *Handler { +func NewHandler(next http.Handler, defender guard.Defender, limiter ratelimit.Limiter, visualizer *visualize.Visualizer) *Handler { return &Handler{ - next: next, - defender: defender, - limiter: limiter, + next: next, + defender: defender, + limiter: limiter, + visualizer: visualizer, } } @@ -51,6 +50,8 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request) { requestWrapper := request.NewRequestWrapper(r, &ipAddr) + go h.visualizer.VisualizeRequestWrapper(*requestWrapper) + if err := h.defender.Validate(ctx, requestWrapper); err != nil { w.WriteHeader(http.StatusForbidden) _, _ = w.Write([]byte(err.Error()))