From 2ac1c2ff245c32f0a85328ae08f29e95fb215391 Mon Sep 17 00:00:00 2001 From: vnxme <46669194+vnxme@users.noreply.github.com> Date: Wed, 24 Jul 2024 15:48:30 +0300 Subject: [PATCH 01/14] Fix warnings: unhandled errors --- layer4/app.go | 4 ++-- layer4/connection_test.go | 10 +++++----- layer4/listener.go | 2 +- layer4/matchers_test.go | 2 +- layer4/routes_test.go | 6 +++--- layer4/server.go | 2 +- modules/l4http/httpmatcher_test.go | 8 ++++---- modules/l4proxy/healthchecks.go | 2 +- modules/l4proxy/proxy.go | 11 +++++------ modules/l4proxyprotocol/handler_test.go | 6 +++--- modules/l4proxyprotocol/matcher_test.go | 6 +++--- modules/l4socks/socks5_handler_test.go | 2 +- modules/l4tee/tee.go | 2 +- 13 files changed, 31 insertions(+), 32 deletions(-) diff --git a/layer4/app.go b/layer4/app.go index 4183044..4b8fa56 100644 --- a/layer4/app.go +++ b/layer4/app.go @@ -76,11 +76,11 @@ func (a *App) Start() error { case net.Listener: a.listeners = append(a.listeners, ln) lnAddr = caddy.JoinNetworkAddress(ln.Addr().Network(), ln.Addr().String(), "") - go s.serve(ln) + go func() { _ = s.serve(ln) }() case net.PacketConn: a.packetConns = append(a.packetConns, ln) lnAddr = caddy.JoinNetworkAddress(ln.LocalAddr().Network(), ln.LocalAddr().String(), "") - go s.servePacket(ln) + go func() { _ = s.servePacket(ln) }() } s.logger.Debug("listening", zap.String("address", lnAddr)) } diff --git a/layer4/connection_test.go b/layer4/connection_test.go index d7626e6..306745f 100644 --- a/layer4/connection_test.go +++ b/layer4/connection_test.go @@ -10,11 +10,11 @@ import ( func TestConnection_FreezeAndUnfreeze(t *testing.T) { in, out := net.Pipe() - defer in.Close() - defer out.Close() + defer func() { _ = in.Close() }() + defer func() { _ = out.Close() }() cx := WrapConnection(out, []byte{}, zap.NewNop()) - defer cx.Close() + defer func() { _ = cx.Close() }() matcherData := []byte("foo") consumeData := []byte("bar") @@ -22,8 +22,8 @@ func TestConnection_FreezeAndUnfreeze(t *testing.T) { buf := make([]byte, len(matcherData)) go func() { - in.Write(matcherData) - in.Write(consumeData) + _, _ = in.Write(matcherData) + _, _ = in.Write(consumeData) }() // prefetch like server handler would diff --git a/layer4/listener.go b/layer4/listener.go index 451e749..e35c11e 100644 --- a/layer4/listener.go +++ b/layer4/listener.go @@ -145,7 +145,7 @@ func (l *listener) loop() { close(l.connChan) }() for conn := range l.connChan { - conn.Close() + _ = conn.Close() } } diff --git a/layer4/matchers_test.go b/layer4/matchers_test.go index 3d61cb3..73a192b 100644 --- a/layer4/matchers_test.go +++ b/layer4/matchers_test.go @@ -48,7 +48,7 @@ type provisionableMatcher interface { } func provision(in provisionableMatcher) ConnMatcher { - in.Provision(caddy.Context{}) + _ = in.Provision(caddy.Context{}) return in } func TestNotMatcher(t *testing.T) { diff --git a/layer4/routes_test.go b/layer4/routes_test.go index 1db54c7..9024756 100644 --- a/layer4/routes_test.go +++ b/layer4/routes_test.go @@ -33,11 +33,11 @@ func TestMatchingTimeoutWorks(t *testing.T) { })) in, out := net.Pipe() - defer in.Close() - defer out.Close() + defer func() { _ = in.Close() }() + defer func() { _ = out.Close() }() cx := WrapConnection(out, []byte{}, zap.NewNop()) - defer cx.Close() + defer func() { _ = cx.Close() }() err = compiledRoutes.Handle(cx) if err != nil { diff --git a/layer4/server.go b/layer4/server.go index 6c5fd2c..a35780f 100644 --- a/layer4/server.go +++ b/layer4/server.go @@ -154,7 +154,7 @@ func (s Server) servePacket(pc net.PacketConn) error { } func (s Server) handle(conn net.Conn) { - defer conn.Close() + defer func() { _ = conn.Close() }() buf := bufPool.Get().([]byte) buf = buf[:0] diff --git a/modules/l4http/httpmatcher_test.go b/modules/l4http/httpmatcher_test.go index 19d1e0a..0cefa81 100644 --- a/modules/l4http/httpmatcher_test.go +++ b/modules/l4http/httpmatcher_test.go @@ -24,8 +24,8 @@ func assertNoError(t *testing.T, err error) { func httpMatchTester(t *testing.T, matchers json.RawMessage, data []byte) (bool, error) { in, out := net.Pipe() - defer in.Close() - defer out.Close() + defer func() { _ = in.Close() }() + defer func() { _ = out.Close() }() cx := layer4.WrapConnection(in, make([]byte, 0), zap.NewNop()) go func() { @@ -211,8 +211,8 @@ func TestHttpMatchingByProtocolWithHttps(t *testing.T) { })) in, out := net.Pipe() - defer in.Close() - defer out.Close() + defer func() { _ = in.Close() }() + defer func() { _ = out.Close() }() cx := layer4.WrapConnection(in, []byte{}, zap.NewNop()) go func() { diff --git a/modules/l4proxy/healthchecks.go b/modules/l4proxy/healthchecks.go index cfdf118..3f0c2c2 100644 --- a/modules/l4proxy/healthchecks.go +++ b/modules/l4proxy/healthchecks.go @@ -152,7 +152,7 @@ func (h *Handler) doActiveHealthCheck(p *peer) error { } return nil } - conn.Close() + _ = conn.Close() // connection succeeded, so mark as healthy swapped, err := p.setHealthy(true) diff --git a/modules/l4proxy/proxy.go b/modules/l4proxy/proxy.go index 36a1eb5..9536448 100644 --- a/modules/l4proxy/proxy.go +++ b/modules/l4proxy/proxy.go @@ -19,7 +19,6 @@ import ( "fmt" "github.com/caddyserver/caddy/v2/caddyconfig" "io" - "io/ioutil" "log" "net" "runtime/debug" @@ -178,7 +177,7 @@ func (h Handler) Handle(down *layer4.Connection, _ layer4.Handler) error { // make sure upstream connections all get closed defer func() { for _, conn := range upConns { - conn.Close() + _ = conn.Close() } }() @@ -235,7 +234,7 @@ func (h *Handler) dialPeers(upstream *Upstream, repl *caddy.Replacer, down *laye if err != nil { h.countFailure(p) for _, conn := range upConns { - conn.Close() + _ = conn.Close() } return nil, err } @@ -285,7 +284,7 @@ func (h *Handler) proxy(down *layer4.Connection, upConns []net.Conn) { go func() { // read from downstream until connection is closed; // TODO: this pumps the reader, but writing into discard is a weird way to do it; could be avoided if we used io.Pipe - see _gitignore/oldtee.go.txt - io.Copy(ioutil.Discard, downTee) + _, _ = io.Copy(io.Discard, downTee) downConnClosedCh <- struct{}{} // Shut down the writing side of all upstream connections, in case @@ -301,7 +300,7 @@ func (h *Handler) proxy(down *layer4.Connection, upConns []net.Conn) { if conn, ok := up.(closeWriter); ok { _ = conn.CloseWrite() } else { - up.Close() + _ = up.Close() } } }() @@ -365,7 +364,7 @@ func (h *Handler) Cleanup() error { // remove hosts from our config from the pool for _, upstream := range h.Upstreams { for _, dialAddr := range upstream.Dial { - peers.Delete(dialAddr) + _, _ = peers.Delete(dialAddr) } } return nil diff --git a/modules/l4proxyprotocol/handler_test.go b/modules/l4proxyprotocol/handler_test.go index 741592a..b20e2a6 100644 --- a/modules/l4proxyprotocol/handler_test.go +++ b/modules/l4proxyprotocol/handler_test.go @@ -28,7 +28,7 @@ func TestProxyProtocolHandleV1(t *testing.T) { go func() { wg.Add(1) defer wg.Done() - defer out.Close() + defer func() { _ = out.Close() }() _, err := out.Write(ProxyV1Example) assertNoError(t, err) }() @@ -66,7 +66,7 @@ func TestProxyProtocolHandleV2(t *testing.T) { go func() { wg.Add(1) defer wg.Done() - defer out.Close() + defer func() { _ = out.Close() }() _, err := out.Write(ProxyV2Example) assertNoError(t, err) }() @@ -104,7 +104,7 @@ func TestProxyProtocolHandleGarbage(t *testing.T) { go func() { wg.Add(1) defer wg.Done() - defer out.Close() + defer func() { _ = out.Close() }() _, err := out.Write([]byte("some garbage")) assertNoError(t, err) }() diff --git a/modules/l4proxyprotocol/matcher_test.go b/modules/l4proxyprotocol/matcher_test.go index c34d33c..8e27691 100644 --- a/modules/l4proxyprotocol/matcher_test.go +++ b/modules/l4proxyprotocol/matcher_test.go @@ -36,7 +36,7 @@ func TestProxyProtocolMatchV1(t *testing.T) { go func() { wg.Add(1) defer wg.Done() - defer out.Close() + defer func() { _ = out.Close() }() _, err := out.Write(ProxyV1Example) assertNoError(t, err) }() @@ -62,7 +62,7 @@ func TestProxyProtocolMatchV2(t *testing.T) { go func() { wg.Add(1) defer wg.Done() - defer out.Close() + defer func() { _ = out.Close() }() _, err := out.Write(ProxyV2Example) assertNoError(t, err) }() @@ -88,7 +88,7 @@ func TestProxyProtocolMatchGarbage(t *testing.T) { go func() { wg.Add(1) defer wg.Done() - defer out.Close() + defer func() { _ = out.Close() }() _, err := out.Write([]byte("Hello World Hello World Hello World Hello World")) assertNoError(t, err) }() diff --git a/modules/l4socks/socks5_handler_test.go b/modules/l4socks/socks5_handler_test.go index a85f02e..2a35534 100644 --- a/modules/l4socks/socks5_handler_test.go +++ b/modules/l4socks/socks5_handler_test.go @@ -62,7 +62,7 @@ func TestSocks5Handler_Defaults(t *testing.T) { // target for the socks handler to connect to (using free random port) listener, err := net.Listen("tcp", "127.0.0.1:0") assertNoError(t, err) - defer listener.Close() + defer func() { _ = listener.Close() }() // transform random listening port into bytes _, portStr, err := net.SplitHostPort(listener.Addr().String()) diff --git a/modules/l4tee/tee.go b/modules/l4tee/tee.go index 3193630..c86eae4 100644 --- a/modules/l4tee/tee.go +++ b/modules/l4tee/tee.go @@ -155,7 +155,7 @@ type nextConn struct { func (nc nextConn) Read(p []byte) (n int, err error) { n, err = nc.Reader.Read(p) if err == io.EOF { - nc.pipe.Close() + _ = nc.pipe.Close() } return } From 504d6c67bb02f55119e258637071149f87483c7e Mon Sep 17 00:00:00 2001 From: vnxme <46669194+vnxme@users.noreply.github.com> Date: Wed, 24 Jul 2024 15:49:14 +0300 Subject: [PATCH 02/14] Fix warnings: redundant type conversions --- modules/l4tls/alpn_matcher.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/l4tls/alpn_matcher.go b/modules/l4tls/alpn_matcher.go index 0574317..6818b0f 100644 --- a/modules/l4tls/alpn_matcher.go +++ b/modules/l4tls/alpn_matcher.go @@ -40,7 +40,7 @@ func (m MatchALPN) Match(hello *tls.ClientHelloInfo) bool { clientProtocols := hello.SupportedProtos for _, alpn := range m { for _, clientProtocol := range clientProtocols { - if alpn == string(clientProtocol) { + if alpn == clientProtocol { return true } } From c0578edcd972f7499784b9072f4bbb0bd38ecb44 Mon Sep 17 00:00:00 2001 From: vnxme <46669194+vnxme@users.noreply.github.com> Date: Wed, 24 Jul 2024 15:52:04 +0300 Subject: [PATCH 03/14] Fix warnings: errors comparison and type conversion --- layer4/listener.go | 9 +++++---- layer4/server.go | 7 +++++-- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/layer4/listener.go b/layer4/listener.go index e35c11e..24bd033 100644 --- a/layer4/listener.go +++ b/layer4/listener.go @@ -126,7 +126,8 @@ type listener struct { func (l *listener) loop() { for { conn, err := l.Listener.Accept() - if nerr, ok := err.(net.Error); ok && nerr.Temporary() { + var nerr net.Error + if errors.As(err, &nerr) && nerr.Temporary() { l.logger.Error("temporary error accepting connection", zap.Error(err)) continue } @@ -156,8 +157,8 @@ func (l *listener) handle(conn net.Conn) { var err error defer func() { l.wg.Done() - if err != errHijacked { - conn.Close() + if !errors.Is(err, errHijacked) { + _ = conn.Close() } }() @@ -171,7 +172,7 @@ func (l *listener) handle(conn net.Conn) { start := time.Now() err = l.compiledRoute.Handle(cx) duration := time.Since(start) - if err != nil && err != errHijacked { + if err != nil && !errors.Is(err, errHijacked) { l.logger.Error("handling connection", zap.Error(err)) } diff --git a/layer4/server.go b/layer4/server.go index a35780f..c56dbbb 100644 --- a/layer4/server.go +++ b/layer4/server.go @@ -16,6 +16,7 @@ package layer4 import ( "bytes" + "errors" "fmt" "io" "net" @@ -75,7 +76,8 @@ func (s *Server) Provision(ctx caddy.Context, logger *zap.Logger) error { func (s Server) serve(ln net.Listener) error { for { conn, err := ln.Accept() - if nerr, ok := err.(net.Error); ok && nerr.Timeout() { + var nerr net.Error + if errors.As(err, &nerr) && nerr.Timeout() { s.logger.Error("timeout accepting connection", zap.Error(err)) continue } @@ -95,7 +97,8 @@ func (s Server) servePacket(pc net.PacketConn) error { buf := udpBufPool.Get().([]byte) n, addr, err := pc.ReadFrom(buf) if err != nil { - if netErr, ok := err.(net.Error); ok && netErr.Timeout() { + var netErr net.Error + if errors.As(err, &netErr) && netErr.Timeout() { continue } packets <- packet{err: err} From bc45e5e217b8b7c8408c8db6e8a7b35a91b97266 Mon Sep 17 00:00:00 2001 From: vnxme <46669194+vnxme@users.noreply.github.com> Date: Wed, 24 Jul 2024 15:53:39 +0300 Subject: [PATCH 04/14] Fix warnings: redundant function arguments --- layer4/matchers.go | 2 +- modules/l4proxy/loadbalancing.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/layer4/matchers.go b/layer4/matchers.go index 12ea4bb..60d548e 100644 --- a/layer4/matchers.go +++ b/layer4/matchers.go @@ -206,7 +206,7 @@ func (MatchLocalIP) CaddyModule() caddy.ModuleInfo { } // Provision parses m's IP ranges, either from IP or CIDR expressions. -func (m *MatchLocalIP) Provision(ctx caddy.Context) error { +func (m *MatchLocalIP) Provision(_ caddy.Context) error { ipnets, err := ParseNetworks(m.Ranges) if err != nil { return err diff --git a/modules/l4proxy/loadbalancing.go b/modules/l4proxy/loadbalancing.go index f246617..50f8808 100644 --- a/modules/l4proxy/loadbalancing.go +++ b/modules/l4proxy/loadbalancing.go @@ -99,7 +99,7 @@ func (RandomSelection) CaddyModule() caddy.ModuleInfo { } // Select returns an available host, if any. -func (r RandomSelection) Select(pool UpstreamPool, conn *layer4.Connection) *Upstream { +func (r RandomSelection) Select(pool UpstreamPool, _ *layer4.Connection) *Upstream { // use reservoir sampling because the number of available // hosts isn't known: https://en.wikipedia.org/wiki/Reservoir_sampling var randomHost *Upstream @@ -156,7 +156,7 @@ func (RandomChoiceSelection) CaddyModule() caddy.ModuleInfo { } // Provision sets up r. -func (r *RandomChoiceSelection) Provision(ctx caddy.Context) error { +func (r *RandomChoiceSelection) Provision(_ caddy.Context) error { if r.Choose == 0 { r.Choose = 2 } From 6d6779591193f400b9c207d124aed0355c9f6942 Mon Sep 17 00:00:00 2001 From: vnxme <46669194+vnxme@users.noreply.github.com> Date: Wed, 24 Jul 2024 15:54:24 +0300 Subject: [PATCH 05/14] Fix warnings: built-in function name collisions --- modules/l4postgres/matcher.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/l4postgres/matcher.go b/modules/l4postgres/matcher.go index d5dfc94..419400d 100644 --- a/modules/l4postgres/matcher.go +++ b/modules/l4postgres/matcher.go @@ -59,8 +59,8 @@ func (b *message) ReadUint32() (r uint32) { func (b *message) ReadString() (r string) { end := b.offset - max := uint32(len(b.data)) - for ; end != max && b.data[end] != 0; end++ { + maximum := uint32(len(b.data)) + for ; end != maximum && b.data[end] != 0; end++ { } r = string(b.data[b.offset:end]) b.offset = end + 1 From d57572821cda16d09495a8e68c2aaaae403ff9bd Mon Sep 17 00:00:00 2001 From: vnxme <46669194+vnxme@users.noreply.github.com> Date: Wed, 24 Jul 2024 15:57:01 +0300 Subject: [PATCH 06/14] Fix warnings: typos in comments --- layer4/connection.go | 2 +- layer4/routes.go | 2 +- layer4/server.go | 2 +- modules/l4proxy/loadbalancing.go | 2 +- modules/l4proxy/upstream.go | 2 +- modules/l4proxyprotocol/handler.go | 2 +- modules/l4socks/socks4_matcher.go | 2 +- modules/l4socks/socks5_handler.go | 2 +- modules/l4socks/socks5_matcher.go | 2 +- modules/l4tee/tee.go | 4 ++-- 10 files changed, 11 insertions(+), 11 deletions(-) diff --git a/layer4/connection.go b/layer4/connection.go index 7bd0184..1a1104b 100644 --- a/layer4/connection.go +++ b/layer4/connection.go @@ -212,7 +212,7 @@ func (cx *Connection) GetVar(key string) interface{} { } // MatchingBytes returns all bytes currently available for matching. This is only intended for reading. -// Do not write into the slice. It's a view of the internal buffer and you will likely mess up the connection. +// Do not write into the slice. It's a view of the internal buffer, and you will likely mess up the connection. func (cx *Connection) MatchingBytes() []byte { return cx.buf[cx.offset:] } diff --git a/layer4/routes.go b/layer4/routes.go index cfa4003..bba6f0d 100644 --- a/layer4/routes.go +++ b/layer4/routes.go @@ -35,7 +35,7 @@ type Route struct { // Matchers define the conditions upon which to execute the handlers. // All matchers within the same set must match, and at least one set // must match; in other words, matchers are AND'ed together within a - // set, but multiple sets are OR'ed together. No matchers matches all. + // set, but multiple sets are OR'ed together. No matchers match all. MatcherSetsRaw []caddy.ModuleMap `json:"match,omitempty" caddy:"namespace=layer4.matchers"` // Handlers define the behavior for handling the stream. They are diff --git a/layer4/server.go b/layer4/server.go index c56dbbb..e907e50 100644 --- a/layer4/server.go +++ b/layer4/server.go @@ -116,7 +116,7 @@ func (s Server) servePacket(pc net.PacketConn) error { // be removed from this map after being closed. udpConns := make(map[string]*packetConn) // closeCh is used to receive notifications of socket closures from - // packetConn, which allows us to to remove stale connections (whose + // packetConn, which allows us to remove stale connections (whose // proxy handlers have completed) from the udpConns map. closeCh := make(chan string, 10) for { diff --git a/modules/l4proxy/loadbalancing.go b/modules/l4proxy/loadbalancing.go index 50f8808..cb46373 100644 --- a/modules/l4proxy/loadbalancing.go +++ b/modules/l4proxy/loadbalancing.go @@ -108,7 +108,7 @@ func (r RandomSelection) Select(pool UpstreamPool, _ *layer4.Connection) *Upstre if !upstream.available() { continue } - // (n % 1 == 0) holds for all n, therefore a + // (n % 1 == 0) holds for all n, therefore an // upstream will always be chosen if there is at // least one available count++ diff --git a/modules/l4proxy/upstream.go b/modules/l4proxy/upstream.go index d49eaa9..051733f 100644 --- a/modules/l4proxy/upstream.go +++ b/modules/l4proxy/upstream.go @@ -85,7 +85,7 @@ func (u *Upstream) provision(ctx caddy.Context, h *Handler) error { // if the passive health checker has a non-zero UnhealthyConnectionCount // but the upstream has no MaxConnections set (they are the same thing, - // but the passive health checker is a default value for for upstreams + // but the passive health checker is a default value for upstreams // without MaxConnections), copy the value into this upstream, since the // value in the upstream (MaxConnections) is what is used during // availability checks diff --git a/modules/l4proxyprotocol/handler.go b/modules/l4proxyprotocol/handler.go index ad28be0..6b14a7c 100644 --- a/modules/l4proxyprotocol/handler.go +++ b/modules/l4proxyprotocol/handler.go @@ -91,7 +91,7 @@ func (h *Handler) tidyRules() { }) if len(rules) > 0 { - // dedup + // deduplication last := rules[0] nf := rules[1:1] for _, f := range rules[1:] { diff --git a/modules/l4socks/socks4_matcher.go b/modules/l4socks/socks4_matcher.go index efbae5e..6dbcac1 100644 --- a/modules/l4socks/socks4_matcher.go +++ b/modules/l4socks/socks4_matcher.go @@ -20,7 +20,7 @@ func init() { // Socks4Matcher matches SOCKSv4 connections according to https://www.openssh.com/txt/socks4.protocol. // Since the SOCKSv4 header is very short it could produce a lot of false positives. // To improve the matching use Commands, Ports and Networks to specify to which destinations you expect clients to connect to. -// By default CONNECT & BIND commands are matched with any destination ip and port. +// By default, CONNECT & BIND commands are matched with any destination ip and port. type Socks4Matcher struct { // Only match on these commands. Default: ["CONNECT", "BIND"] Commands []string `json:"commands,omitempty"` diff --git a/modules/l4socks/socks5_handler.go b/modules/l4socks/socks5_handler.go index 62c1515..d6afd37 100644 --- a/modules/l4socks/socks5_handler.go +++ b/modules/l4socks/socks5_handler.go @@ -40,7 +40,7 @@ func (h *Socks5Handler) Provision(ctx caddy.Context) error { if len(h.Commands) == 0 { rule.EnableConnect = true rule.EnableAssociate = true - // BIND is currently not supported so we dont allow it by default + // BIND is currently not supported, so we don't allow it by default } else { for _, c := range h.Commands { switch strings.ToUpper(c) { diff --git a/modules/l4socks/socks5_matcher.go b/modules/l4socks/socks5_matcher.go index 4dc80c7..1c15b33 100644 --- a/modules/l4socks/socks5_matcher.go +++ b/modules/l4socks/socks5_matcher.go @@ -16,7 +16,7 @@ func init() { // Socks5Matcher matches SOCKSv5 connections according to RFC 1928 (https://www.rfc-editor.org/rfc/rfc1928.html). // Since the SOCKSv5 header is very short it could produce a lot of false positives, // use AuthMethods to exactly specify which METHODS you expect your clients to send. -// By default only the most common methods are matched NO AUTH, GSSAPI & USERNAME/PASSWORD. +// By default, only the most common methods are matched NO AUTH, GSSAPI & USERNAME/PASSWORD. type Socks5Matcher struct { AuthMethods []uint16 `json:"auth_methods,omitempty"` } diff --git a/modules/l4tee/tee.go b/modules/l4tee/tee.go index c86eae4..bc1c81a 100644 --- a/modules/l4tee/tee.go +++ b/modules/l4tee/tee.go @@ -31,7 +31,7 @@ func init() { // Handler is a layer4 handler that replicates a connection so // that a branch of handlers can concurrently handle it. Reads -// happen in lock-step with all concurrent branches so as to +// happen in lock-step with all concurrent branches to // avoid buffering: if one of the branches (including the main // handler chain) stops reading from the connection, it will // block all branches. @@ -83,7 +83,7 @@ func (t Handler) Handle(cx *layer4.Connection, next layer4.Handler) error { // this is the conn we pass to the next handler; // anything read by it will be teed into the pipe - // (it also needs a pointer to the pipe so it can + // (it also needs a pointer to the pipe, so it can // close the pipe when the connection closes, // otherwise we'll leak the goroutine, yikes!) nextc := *cx From 26e05cc40b50b843d978304c92380e6bb787b16b Mon Sep 17 00:00:00 2001 From: vnxme <46669194+vnxme@users.noreply.github.com> Date: Wed, 24 Jul 2024 16:12:08 +0300 Subject: [PATCH 07/14] Fix warnings: potential nil pointer dereference --- modules/l4http/httpmatcher.go | 9 ++++----- modules/l4tee/tee.go | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/modules/l4http/httpmatcher.go b/modules/l4http/httpmatcher.go index ed9ac33..c57801b 100644 --- a/modules/l4http/httpmatcher.go +++ b/modules/l4http/httpmatcher.go @@ -164,20 +164,19 @@ func (m MatchHTTP) handleHttp2WithPriorKnowledge(reader io.Reader, req *http.Req // read the first 10 frames until we get a headers frame (skipping settings, window update & priority frames) var frame http2.Frame - for i := 0; i < 10; i++ { + maxAttempts := 10 + for i := 0; i < maxAttempts; i++ { frame, err = framer.ReadFrame() if err != nil { return err } if frame.Header().Type == http2.FrameHeaders { break + } else if i == maxAttempts-1 { + return fmt.Errorf("failed to read a http2 headers frame after %d attempts", maxAttempts) } } - if frame.Header().Type != http2.FrameHeaders { - return fmt.Errorf("failed to read a http2 headers frame after 10 attempts") - } - decoder := hpack.NewDecoder(4096, nil) // max table size 4096 from http2.initialHeaderTableSize headers, err := decoder.DecodeFull((frame.(*http2.HeadersFrame)).HeaderBlockFragment()) if err != nil { diff --git a/modules/l4tee/tee.go b/modules/l4tee/tee.go index bc1c81a..859b12f 100644 --- a/modules/l4tee/tee.go +++ b/modules/l4tee/tee.go @@ -64,7 +64,7 @@ func (t *Handler) Provision(ctx caddy.Context) error { if err != nil { return err } - var handlers layer4.Handlers + handlers := make(layer4.Handlers, 0) for _, mod := range mods.([]interface{}) { handlers = append(handlers, mod.(layer4.NextHandler)) } From 1b79b20415dc8bf7800054928b48d1db49de1ebc Mon Sep 17 00:00:00 2001 From: vnxme <46669194+vnxme@users.noreply.github.com> Date: Wed, 24 Jul 2024 17:03:23 +0300 Subject: [PATCH 08/14] Fix warnings: mixed value and pointer receivers --- layer4/app.go | 6 ++--- layer4/listener.go | 4 ++-- layer4/matchers.go | 30 ++++++++++++------------- layer4/server.go | 10 ++++----- modules/l4echo/echo.go | 6 ++--- modules/l4http/httpmatcher.go | 12 +++++----- modules/l4http/httpmatcher_test.go | 2 +- modules/l4postgres/matcher.go | 6 ++--- modules/l4proxy/loadbalancing.go | 36 +++++++++++++++--------------- modules/l4proxy/proxy.go | 8 +++---- modules/l4proxy/upstream.go | 2 +- modules/l4proxyprotocol/handler.go | 4 ++-- modules/l4proxyprotocol/matcher.go | 6 ++--- modules/l4socks/socks4_matcher.go | 4 ++-- modules/l4socks/socks5_handler.go | 4 ++-- modules/l4socks/socks5_matcher.go | 4 ++-- modules/l4ssh/matcher.go | 6 ++--- modules/l4subroute/handler.go | 4 ++-- modules/l4tee/tee.go | 6 ++--- modules/l4throttle/throttle.go | 6 ++--- modules/l4tls/alpn_matcher.go | 8 +++---- modules/l4tls/handler.go | 4 ++-- modules/l4tls/matcher.go | 8 +++---- modules/l4xmpp/matcher.go | 6 ++--- 24 files changed, 96 insertions(+), 96 deletions(-) diff --git a/layer4/app.go b/layer4/app.go index 4b8fa56..5a5c55e 100644 --- a/layer4/app.go +++ b/layer4/app.go @@ -23,7 +23,7 @@ import ( ) func init() { - caddy.RegisterModule(App{}) + caddy.RegisterModule(&App{}) } // App is a Caddy app that operates closest to layer 4 of the OSI model. @@ -40,7 +40,7 @@ type App struct { } // CaddyModule returns the Caddy module information. -func (App) CaddyModule() caddy.ModuleInfo { +func (*App) CaddyModule() caddy.ModuleInfo { return caddy.ModuleInfo{ ID: "layer4", New: func() caddy.Module { return new(App) }, @@ -90,7 +90,7 @@ func (a *App) Start() error { } // Stop stops the servers and closes all listeners. -func (a App) Stop() error { +func (a *App) Stop() error { for _, pc := range a.packetConns { err := pc.Close() if err != nil { diff --git a/layer4/listener.go b/layer4/listener.go index 24bd033..70c2733 100644 --- a/layer4/listener.go +++ b/layer4/listener.go @@ -15,7 +15,7 @@ import ( ) func init() { - caddy.RegisterModule(ListenerWrapper{}) + caddy.RegisterModule(&ListenerWrapper{}) } // ListenerWrapper is a Caddy module that wraps App as a listener wrapper, it doesn't support udp. @@ -33,7 +33,7 @@ type ListenerWrapper struct { } // CaddyModule returns the Caddy module information. -func (ListenerWrapper) CaddyModule() caddy.ModuleInfo { +func (*ListenerWrapper) CaddyModule() caddy.ModuleInfo { return caddy.ModuleInfo{ ID: "caddy.listeners.layer4", New: func() caddy.Module { return new(ListenerWrapper) }, diff --git a/layer4/matchers.go b/layer4/matchers.go index 60d548e..1a26321 100644 --- a/layer4/matchers.go +++ b/layer4/matchers.go @@ -27,9 +27,9 @@ import ( ) func init() { - caddy.RegisterModule(MatchRemoteIP{}) - caddy.RegisterModule(MatchLocalIP{}) - caddy.RegisterModule(MatchNot{}) + caddy.RegisterModule(&MatchRemoteIP{}) + caddy.RegisterModule(&MatchLocalIP{}) + caddy.RegisterModule(&MatchNot{}) } // ConnMatcher is a type that can match a connection. @@ -83,14 +83,14 @@ type MatcherSets []MatcherSet // AnyMatch returns true if the connection matches any of the matcher sets // in mss or if there are no matchers, in which case the request always // matches. Any error terminates matching. -func (mss MatcherSets) AnyMatch(cx *Connection) (matched bool, err error) { - for _, m := range mss { +func (mss *MatcherSets) AnyMatch(cx *Connection) (matched bool, err error) { + for _, m := range *mss { matched, err = m.Match(cx) if matched || err != nil { return } } - matched = len(mss) == 0 + matched = len(*mss) == 0 return } @@ -117,7 +117,7 @@ type MatchRemoteIP struct { } // CaddyModule returns the Caddy module information. -func (MatchRemoteIP) CaddyModule() caddy.ModuleInfo { +func (*MatchRemoteIP) CaddyModule() caddy.ModuleInfo { return caddy.ModuleInfo{ ID: "layer4.matchers.remote_ip", New: func() caddy.Module { return new(MatchRemoteIP) }, @@ -134,7 +134,7 @@ func (m *MatchRemoteIP) Provision(_ caddy.Context) (err error) { } // Match returns true if the connection is from one of the designated IP ranges. -func (m MatchRemoteIP) Match(cx *Connection) (bool, error) { +func (m *MatchRemoteIP) Match(cx *Connection) (bool, error) { clientIP, err := m.getRemoteIP(cx) if err != nil { return false, fmt.Errorf("getting remote IP: %v", err) @@ -147,7 +147,7 @@ func (m MatchRemoteIP) Match(cx *Connection) (bool, error) { return false, nil } -func (m MatchRemoteIP) getRemoteIP(cx *Connection) (netip.Addr, error) { +func (m *MatchRemoteIP) getRemoteIP(cx *Connection) (netip.Addr, error) { remote := cx.Conn.RemoteAddr().String() ipStr, _, err := net.SplitHostPort(remote) @@ -198,7 +198,7 @@ type MatchLocalIP struct { } // CaddyModule returns the Caddy module information. -func (MatchLocalIP) CaddyModule() caddy.ModuleInfo { +func (*MatchLocalIP) CaddyModule() caddy.ModuleInfo { return caddy.ModuleInfo{ ID: "layer4.matchers.local_ip", New: func() caddy.Module { return new(MatchLocalIP) }, @@ -216,7 +216,7 @@ func (m *MatchLocalIP) Provision(_ caddy.Context) error { } // Match returns true if the connection is from one of the designated IP ranges. -func (m MatchLocalIP) Match(cx *Connection) (bool, error) { +func (m *MatchLocalIP) Match(cx *Connection) (bool, error) { localIP, err := m.getLocalIP(cx) if err != nil { return false, fmt.Errorf("getting local IP: %v", err) @@ -229,7 +229,7 @@ func (m MatchLocalIP) Match(cx *Connection) (bool, error) { return false, nil } -func (m MatchLocalIP) getLocalIP(cx *Connection) (netip.Addr, error) { +func (m *MatchLocalIP) getLocalIP(cx *Connection) (netip.Addr, error) { remote := cx.Conn.LocalAddr().String() ipStr, _, err := net.SplitHostPort(remote) @@ -300,7 +300,7 @@ type MatchNot struct { } // CaddyModule implements caddy.Module. -func (MatchNot) CaddyModule() caddy.ModuleInfo { +func (*MatchNot) CaddyModule() caddy.ModuleInfo { return caddy.ModuleInfo{ ID: "layer4.matchers.not", New: func() caddy.Module { return new(MatchNot) }, @@ -315,7 +315,7 @@ func (m *MatchNot) UnmarshalJSON(data []byte) error { // MarshalJSON satisfies json.Marshaler by marshaling // m's raw matcher sets. -func (m MatchNot) MarshalJSON() ([]byte, error) { +func (m *MatchNot) MarshalJSON() ([]byte, error) { return json.Marshal(m.MatcherSetsRaw) } @@ -338,7 +338,7 @@ func (m *MatchNot) Provision(ctx caddy.Context) error { // Match returns true if r matches m. Since this matcher negates // the embedded matchers, false is returned if any of its matcher // sets return true. -func (m MatchNot) Match(r *Connection) (bool, error) { +func (m *MatchNot) Match(r *Connection) (bool, error) { for _, ms := range m.MatcherSets { match, err := ms.Match(r) if err != nil { diff --git a/layer4/server.go b/layer4/server.go index e907e50..092f501 100644 --- a/layer4/server.go +++ b/layer4/server.go @@ -73,7 +73,7 @@ func (s *Server) Provision(ctx caddy.Context, logger *zap.Logger) error { return nil } -func (s Server) serve(ln net.Listener) error { +func (s *Server) serve(ln net.Listener) error { for { conn, err := ln.Accept() var nerr net.Error @@ -88,7 +88,7 @@ func (s Server) serve(ln net.Listener) error { } } -func (s Server) servePacket(pc net.PacketConn) error { +func (s *Server) servePacket(pc net.PacketConn) error { // Spawn a goroutine whose only job is to consume packets from the socket // and send to the packets channel. packets := make(chan packet, 10) @@ -156,7 +156,7 @@ func (s Server) servePacket(pc net.PacketConn) error { } } -func (s Server) handle(conn net.Conn) { +func (s *Server) handle(conn net.Conn) { defer func() { _ = conn.Close() }() buf := bufPool.Get().([]byte) @@ -288,7 +288,7 @@ func (pc *packetConn) Read(b []byte) (n int, err error) { return 0, io.EOF } -func (pc packetConn) Write(b []byte) (n int, err error) { +func (pc *packetConn) Write(b []byte) (n int, err error) { return pc.PacketConn.WriteTo(b, pc.addr) } @@ -311,7 +311,7 @@ func (pc *packetConn) Close() error { return nil } -func (pc packetConn) RemoteAddr() net.Addr { return pc.addr } +func (pc *packetConn) RemoteAddr() net.Addr { return pc.addr } var udpBufPool = sync.Pool{ New: func() interface{} { diff --git a/modules/l4echo/echo.go b/modules/l4echo/echo.go index e425d6c..3dc9ea0 100644 --- a/modules/l4echo/echo.go +++ b/modules/l4echo/echo.go @@ -23,14 +23,14 @@ import ( ) func init() { - caddy.RegisterModule(Handler{}) + caddy.RegisterModule(&Handler{}) } // Handler is a simple handler that writes what it reads. type Handler struct{} // CaddyModule returns the Caddy module information. -func (Handler) CaddyModule() caddy.ModuleInfo { +func (*Handler) CaddyModule() caddy.ModuleInfo { return caddy.ModuleInfo{ ID: "layer4.handlers.echo", New: func() caddy.Module { return new(Handler) }, @@ -38,7 +38,7 @@ func (Handler) CaddyModule() caddy.ModuleInfo { } // Handle handles the connection. -func (Handler) Handle(cx *layer4.Connection, _ layer4.Handler) error { +func (*Handler) Handle(cx *layer4.Connection, _ layer4.Handler) error { _, err := io.Copy(cx, cx) return err } diff --git a/modules/l4http/httpmatcher.go b/modules/l4http/httpmatcher.go index c57801b..0878639 100644 --- a/modules/l4http/httpmatcher.go +++ b/modules/l4http/httpmatcher.go @@ -33,7 +33,7 @@ import ( ) func init() { - caddy.RegisterModule(MatchHTTP{}) + caddy.RegisterModule(&MatchHTTP{}) } // MatchHTTP is able to match HTTP connections. The auto-generated @@ -45,7 +45,7 @@ type MatchHTTP struct { } // CaddyModule returns the Caddy module information. -func (MatchHTTP) CaddyModule() caddy.ModuleInfo { +func (*MatchHTTP) CaddyModule() caddy.ModuleInfo { return caddy.ModuleInfo{ ID: "layer4.matchers.http", New: func() caddy.Module { return new(MatchHTTP) }, @@ -58,7 +58,7 @@ func (m *MatchHTTP) UnmarshalJSON(b []byte) error { } // MarshalJSON satisfies the json.Marshaler interface. -func (m MatchHTTP) MarshalJSON() ([]byte, error) { +func (m *MatchHTTP) MarshalJSON() ([]byte, error) { return json.Marshal(m.MatcherSetsRaw) } @@ -76,7 +76,7 @@ func (m *MatchHTTP) Provision(ctx caddy.Context) error { } // Match returns true if the conn starts with an HTTP request. -func (m MatchHTTP) Match(cx *layer4.Connection) (bool, error) { +func (m *MatchHTTP) Match(cx *layer4.Connection) (bool, error) { // TODO: do we need a more standardized way to amortize matchers? or at least to remember decoded results from previous matchers? req, ok := cx.GetVar("http_request").(*http.Request) if !ok { @@ -123,7 +123,7 @@ func (m MatchHTTP) Match(cx *layer4.Connection) (bool, error) { return m.matcherSets.AnyMatch(req), nil } -func (m MatchHTTP) isHttp(data []byte) bool { +func (m *MatchHTTP) isHttp(data []byte) bool { // try to find the end of a http request line, for example " HTTP/1.1\r\n" i := bytes.IndexByte(data, 0x0a) // find first new line if i < 10 { @@ -141,7 +141,7 @@ func (m MatchHTTP) isHttp(data []byte) bool { } // Parses information from a http2 request with prior knowledge (RFC 7540 Section 3.4) -func (m MatchHTTP) handleHttp2WithPriorKnowledge(reader io.Reader, req *http.Request) error { +func (m *MatchHTTP) handleHttp2WithPriorKnowledge(reader io.Reader, req *http.Request) error { // Does req contain a valid http2 magic? // https://github.com/golang/net/blob/a630d4f3e7a22f21271532b4b88e1693824a838f/http2/h2c/h2c.go#L74 if req.Method != "PRI" || len(req.Header) != 0 || req.URL.Path != "*" || req.Proto != "HTTP/2.0" { diff --git a/modules/l4http/httpmatcher_test.go b/modules/l4http/httpmatcher_test.go index 0cefa81..5b4f14a 100644 --- a/modules/l4http/httpmatcher_test.go +++ b/modules/l4http/httpmatcher_test.go @@ -290,7 +290,7 @@ func TestMatchHTTP_isHttp(t *testing.T) { }, } { t.Run(tc.name, func(t *testing.T) { - matched := MatchHTTP{}.isHttp(tc.data) + matched := (&MatchHTTP{}).isHttp(tc.data) if matched != tc.shouldMatch { t.Fatalf("test %v | matched: %v != shouldMatch: %v", tc.name, matched, tc.shouldMatch) } diff --git a/modules/l4postgres/matcher.go b/modules/l4postgres/matcher.go index 419400d..99c4e48 100644 --- a/modules/l4postgres/matcher.go +++ b/modules/l4postgres/matcher.go @@ -34,7 +34,7 @@ import ( ) func init() { - caddy.RegisterModule(MatchPostgres{}) + caddy.RegisterModule(&MatchPostgres{}) } const ( @@ -82,7 +82,7 @@ type startupMessage struct { type MatchPostgres struct{} // CaddyModule returns the Caddy module information. -func (MatchPostgres) CaddyModule() caddy.ModuleInfo { +func (*MatchPostgres) CaddyModule() caddy.ModuleInfo { return caddy.ModuleInfo{ ID: "layer4.matchers.postgres", New: func() caddy.Module { return new(MatchPostgres) }, @@ -90,7 +90,7 @@ func (MatchPostgres) CaddyModule() caddy.ModuleInfo { } // Match returns true if the connection looks like the Postgres protocol. -func (m MatchPostgres) Match(cx *layer4.Connection) (bool, error) { +func (m *MatchPostgres) Match(cx *layer4.Connection) (bool, error) { // Get bytes containing the message length head := make([]byte, initMessageSizeLength) if _, err := io.ReadFull(cx, head); err != nil { diff --git a/modules/l4proxy/loadbalancing.go b/modules/l4proxy/loadbalancing.go index cb46373..a1a0fe2 100644 --- a/modules/l4proxy/loadbalancing.go +++ b/modules/l4proxy/loadbalancing.go @@ -76,12 +76,12 @@ type Selector interface { } func init() { - caddy.RegisterModule(RandomSelection{}) - caddy.RegisterModule(RandomChoiceSelection{}) - caddy.RegisterModule(LeastConnSelection{}) - caddy.RegisterModule(RoundRobinSelection{}) - caddy.RegisterModule(FirstSelection{}) - caddy.RegisterModule(IPHashSelection{}) + caddy.RegisterModule(&RandomSelection{}) + caddy.RegisterModule(&RandomChoiceSelection{}) + caddy.RegisterModule(&LeastConnSelection{}) + caddy.RegisterModule(&RoundRobinSelection{}) + caddy.RegisterModule(&FirstSelection{}) + caddy.RegisterModule(&IPHashSelection{}) weakrand.Seed(time.Now().UTC().UnixNano()) } @@ -91,7 +91,7 @@ func init() { type RandomSelection struct{} // CaddyModule returns the Caddy module information. -func (RandomSelection) CaddyModule() caddy.ModuleInfo { +func (*RandomSelection) CaddyModule() caddy.ModuleInfo { return caddy.ModuleInfo{ ID: "layer4.proxy.selection_policies.random", New: func() caddy.Module { return new(RandomSelection) }, @@ -99,7 +99,7 @@ func (RandomSelection) CaddyModule() caddy.ModuleInfo { } // Select returns an available host, if any. -func (r RandomSelection) Select(pool UpstreamPool, _ *layer4.Connection) *Upstream { +func (r *RandomSelection) Select(pool UpstreamPool, _ *layer4.Connection) *Upstream { // use reservoir sampling because the number of available // hosts isn't known: https://en.wikipedia.org/wiki/Reservoir_sampling var randomHost *Upstream @@ -148,7 +148,7 @@ type RandomChoiceSelection struct { } // CaddyModule returns the Caddy module information. -func (RandomChoiceSelection) CaddyModule() caddy.ModuleInfo { +func (*RandomChoiceSelection) CaddyModule() caddy.ModuleInfo { return caddy.ModuleInfo{ ID: "layer4.proxy.selection_policies.random_choose", New: func() caddy.Module { return new(RandomChoiceSelection) }, @@ -164,7 +164,7 @@ func (r *RandomChoiceSelection) Provision(_ caddy.Context) error { } // Validate ensures that r's configuration is valid. -func (r RandomChoiceSelection) Validate() error { +func (r *RandomChoiceSelection) Validate() error { if r.Choose < 2 { return fmt.Errorf("choose must be at least 2") } @@ -172,7 +172,7 @@ func (r RandomChoiceSelection) Validate() error { } // Select returns an available host, if any. -func (r RandomChoiceSelection) Select(pool UpstreamPool, _ *layer4.Connection) *Upstream { +func (r *RandomChoiceSelection) Select(pool UpstreamPool, _ *layer4.Connection) *Upstream { k := r.Choose if k > len(pool) { k = len(pool) @@ -224,7 +224,7 @@ func (r *RandomChoiceSelection) UnmarshalCaddyfile(d *caddyfile.Dispenser) error type LeastConnSelection struct{} // CaddyModule returns the Caddy module information. -func (LeastConnSelection) CaddyModule() caddy.ModuleInfo { +func (*LeastConnSelection) CaddyModule() caddy.ModuleInfo { return caddy.ModuleInfo{ ID: "layer4.proxy.selection_policies.least_conn", New: func() caddy.Module { return new(LeastConnSelection) }, @@ -234,7 +234,7 @@ func (LeastConnSelection) CaddyModule() caddy.ModuleInfo { // Select selects the up host with the least number of connections in the // pool. If more than one host has the same least number of connections, // one of the hosts is chosen at random. -func (LeastConnSelection) Select(pool UpstreamPool, _ *layer4.Connection) *Upstream { +func (*LeastConnSelection) Select(pool UpstreamPool, _ *layer4.Connection) *Upstream { var best *Upstream var count int leastConns := -1 @@ -288,7 +288,7 @@ type RoundRobinSelection struct { } // CaddyModule returns the Caddy module information. -func (RoundRobinSelection) CaddyModule() caddy.ModuleInfo { +func (*RoundRobinSelection) CaddyModule() caddy.ModuleInfo { return caddy.ModuleInfo{ ID: "layer4.proxy.selection_policies.round_robin", New: func() caddy.Module { return new(RoundRobinSelection) }, @@ -335,7 +335,7 @@ func (r *RoundRobinSelection) UnmarshalCaddyfile(d *caddyfile.Dispenser) error { type FirstSelection struct{} // CaddyModule returns the Caddy module information. -func (FirstSelection) CaddyModule() caddy.ModuleInfo { +func (*FirstSelection) CaddyModule() caddy.ModuleInfo { return caddy.ModuleInfo{ ID: "layer4.proxy.selection_policies.first", New: func() caddy.Module { return new(FirstSelection) }, @@ -343,7 +343,7 @@ func (FirstSelection) CaddyModule() caddy.ModuleInfo { } // Select returns an available host, if any. -func (FirstSelection) Select(pool UpstreamPool, _ *layer4.Connection) *Upstream { +func (*FirstSelection) Select(pool UpstreamPool, _ *layer4.Connection) *Upstream { for _, host := range pool { if host.available() { return host @@ -376,7 +376,7 @@ func (r *FirstSelection) UnmarshalCaddyfile(d *caddyfile.Dispenser) error { type IPHashSelection struct{} // CaddyModule returns the Caddy module information. -func (IPHashSelection) CaddyModule() caddy.ModuleInfo { +func (*IPHashSelection) CaddyModule() caddy.ModuleInfo { return caddy.ModuleInfo{ ID: "layer4.proxy.selection_policies.ip_hash", New: func() caddy.Module { return new(IPHashSelection) }, @@ -384,7 +384,7 @@ func (IPHashSelection) CaddyModule() caddy.ModuleInfo { } // Select returns an available host, if any. -func (IPHashSelection) Select(pool UpstreamPool, conn *layer4.Connection) *Upstream { +func (*IPHashSelection) Select(pool UpstreamPool, conn *layer4.Connection) *Upstream { remoteAddr := conn.Conn.RemoteAddr().String() clientIP, _, err := net.SplitHostPort(remoteAddr) if err != nil { diff --git a/modules/l4proxy/proxy.go b/modules/l4proxy/proxy.go index 9536448..ee8184e 100644 --- a/modules/l4proxy/proxy.go +++ b/modules/l4proxy/proxy.go @@ -37,7 +37,7 @@ import ( ) func init() { - caddy.RegisterModule(Handler{}) + caddy.RegisterModule(&Handler{}) } // Handler is a handler that can proxy connections. @@ -61,7 +61,7 @@ type Handler struct { } // CaddyModule returns the Caddy module information. -func (Handler) CaddyModule() caddy.ModuleInfo { +func (*Handler) CaddyModule() caddy.ModuleInfo { return caddy.ModuleInfo{ ID: "layer4.handlers.proxy", New: func() caddy.Module { return new(Handler) }, @@ -126,7 +126,7 @@ func (h *Handler) Provision(ctx caddy.Context) error { h.LoadBalancing = new(LoadBalancing) } if h.LoadBalancing.SelectionPolicy == nil { - h.LoadBalancing.SelectionPolicy = RandomSelection{} + h.LoadBalancing.SelectionPolicy = &RandomSelection{} } if h.LoadBalancing.TryDuration > 0 && h.LoadBalancing.TryInterval == 0 { // a non-zero try_duration with a zero try_interval @@ -140,7 +140,7 @@ func (h *Handler) Provision(ctx caddy.Context) error { } // Handle handles the downstream connection. -func (h Handler) Handle(down *layer4.Connection, _ layer4.Handler) error { +func (h *Handler) Handle(down *layer4.Connection, _ layer4.Handler) error { repl := down.Context.Value(layer4.ReplacerCtxKey).(*caddy.Replacer) start := time.Now() diff --git a/modules/l4proxy/upstream.go b/modules/l4proxy/upstream.go index 051733f..47223bd 100644 --- a/modules/l4proxy/upstream.go +++ b/modules/l4proxy/upstream.go @@ -50,7 +50,7 @@ type Upstream struct { healthCheckPolicy *PassiveHealthChecks } -func (u Upstream) String() string { +func (u *Upstream) String() string { return strings.Join(u.Dial, ",") } diff --git a/modules/l4proxyprotocol/handler.go b/modules/l4proxyprotocol/handler.go index 6b14a7c..5a9c432 100644 --- a/modules/l4proxyprotocol/handler.go +++ b/modules/l4proxyprotocol/handler.go @@ -28,7 +28,7 @@ import ( ) func init() { - caddy.RegisterModule(Handler{}) + caddy.RegisterModule(&Handler{}) } // Handler is a connection handler that accepts the PROXY protocol. @@ -45,7 +45,7 @@ type Handler struct { } // CaddyModule returns the Caddy module information. -func (Handler) CaddyModule() caddy.ModuleInfo { +func (*Handler) CaddyModule() caddy.ModuleInfo { return caddy.ModuleInfo{ ID: "layer4.handlers.proxy_protocol", New: func() caddy.Module { return new(Handler) }, diff --git a/modules/l4proxyprotocol/matcher.go b/modules/l4proxyprotocol/matcher.go index e40028c..89e1a5a 100644 --- a/modules/l4proxyprotocol/matcher.go +++ b/modules/l4proxyprotocol/matcher.go @@ -30,13 +30,13 @@ var ( ) func init() { - caddy.RegisterModule(MatchProxyProtocol{}) + caddy.RegisterModule(&MatchProxyProtocol{}) } type MatchProxyProtocol struct{} // CaddyModule returns the Caddy module information. -func (MatchProxyProtocol) CaddyModule() caddy.ModuleInfo { +func (*MatchProxyProtocol) CaddyModule() caddy.ModuleInfo { return caddy.ModuleInfo{ ID: "layer4.matchers.proxy_protocol", New: func() caddy.Module { return new(MatchProxyProtocol) }, @@ -44,7 +44,7 @@ func (MatchProxyProtocol) CaddyModule() caddy.ModuleInfo { } // Match returns true if the connection looks like it is using the Proxy Protocol. -func (m MatchProxyProtocol) Match(cx *layer4.Connection) (bool, error) { +func (m *MatchProxyProtocol) Match(cx *layer4.Connection) (bool, error) { buf := make([]byte, len(headerV2Prefix)) _, err := io.ReadFull(cx, buf) if err != nil { diff --git a/modules/l4socks/socks4_matcher.go b/modules/l4socks/socks4_matcher.go index 6dbcac1..782c1b1 100644 --- a/modules/l4socks/socks4_matcher.go +++ b/modules/l4socks/socks4_matcher.go @@ -14,7 +14,7 @@ import ( ) func init() { - caddy.RegisterModule(Socks4Matcher{}) + caddy.RegisterModule(&Socks4Matcher{}) } // Socks4Matcher matches SOCKSv4 connections according to https://www.openssh.com/txt/socks4.protocol. @@ -33,7 +33,7 @@ type Socks4Matcher struct { cidrs []netip.Prefix } -func (Socks4Matcher) CaddyModule() caddy.ModuleInfo { +func (*Socks4Matcher) CaddyModule() caddy.ModuleInfo { return caddy.ModuleInfo{ ID: "layer4.matchers.socks4", New: func() caddy.Module { return new(Socks4Matcher) }, diff --git a/modules/l4socks/socks5_handler.go b/modules/l4socks/socks5_handler.go index d6afd37..69a6eee 100644 --- a/modules/l4socks/socks5_handler.go +++ b/modules/l4socks/socks5_handler.go @@ -13,7 +13,7 @@ import ( ) func init() { - caddy.RegisterModule(Socks5Handler{}) + caddy.RegisterModule(&Socks5Handler{}) } // Socks5Handler is a connection handler that terminates SOCKSv5 connection. @@ -28,7 +28,7 @@ type Socks5Handler struct { server *socks5.Server } -func (Socks5Handler) CaddyModule() caddy.ModuleInfo { +func (*Socks5Handler) CaddyModule() caddy.ModuleInfo { return caddy.ModuleInfo{ ID: "layer4.handlers.socks5", New: func() caddy.Module { return new(Socks5Handler) }, diff --git a/modules/l4socks/socks5_matcher.go b/modules/l4socks/socks5_matcher.go index 1c15b33..4a2f39d 100644 --- a/modules/l4socks/socks5_matcher.go +++ b/modules/l4socks/socks5_matcher.go @@ -10,7 +10,7 @@ import ( ) func init() { - caddy.RegisterModule(Socks5Matcher{}) + caddy.RegisterModule(&Socks5Matcher{}) } // Socks5Matcher matches SOCKSv5 connections according to RFC 1928 (https://www.rfc-editor.org/rfc/rfc1928.html). @@ -21,7 +21,7 @@ type Socks5Matcher struct { AuthMethods []uint16 `json:"auth_methods,omitempty"` } -func (Socks5Matcher) CaddyModule() caddy.ModuleInfo { +func (*Socks5Matcher) CaddyModule() caddy.ModuleInfo { return caddy.ModuleInfo{ ID: "layer4.matchers.socks5", New: func() caddy.Module { return new(Socks5Matcher) }, diff --git a/modules/l4ssh/matcher.go b/modules/l4ssh/matcher.go index 7efbbfa..21e465b 100644 --- a/modules/l4ssh/matcher.go +++ b/modules/l4ssh/matcher.go @@ -24,14 +24,14 @@ import ( ) func init() { - caddy.RegisterModule(MatchSSH{}) + caddy.RegisterModule(&MatchSSH{}) } // MatchSSH is able to match SSH connections. type MatchSSH struct{} // CaddyModule returns the Caddy module information. -func (MatchSSH) CaddyModule() caddy.ModuleInfo { +func (*MatchSSH) CaddyModule() caddy.ModuleInfo { return caddy.ModuleInfo{ ID: "layer4.matchers.ssh", New: func() caddy.Module { return new(MatchSSH) }, @@ -39,7 +39,7 @@ func (MatchSSH) CaddyModule() caddy.ModuleInfo { } // Match returns true if the connection looks like SSH. -func (m MatchSSH) Match(cx *layer4.Connection) (bool, error) { +func (m *MatchSSH) Match(cx *layer4.Connection) (bool, error) { p := make([]byte, len(sshPrefix)) n, err := io.ReadFull(cx, p) if err != nil || n < len(sshPrefix) { diff --git a/modules/l4subroute/handler.go b/modules/l4subroute/handler.go index 2c5cb5e..8d86a77 100644 --- a/modules/l4subroute/handler.go +++ b/modules/l4subroute/handler.go @@ -25,7 +25,7 @@ import ( ) func init() { - caddy.RegisterModule(Handler{}) + caddy.RegisterModule(&Handler{}) } // Handler implements a handler that compiles and executes routes. @@ -43,7 +43,7 @@ type Handler struct { } // CaddyModule returns the Caddy module information. -func (Handler) CaddyModule() caddy.ModuleInfo { +func (*Handler) CaddyModule() caddy.ModuleInfo { return caddy.ModuleInfo{ ID: "layer4.handlers.subroute", New: func() caddy.Module { return new(Handler) }, diff --git a/modules/l4tee/tee.go b/modules/l4tee/tee.go index 859b12f..b4942a5 100644 --- a/modules/l4tee/tee.go +++ b/modules/l4tee/tee.go @@ -26,7 +26,7 @@ import ( ) func init() { - caddy.RegisterModule(Handler{}) + caddy.RegisterModule(&Handler{}) } // Handler is a layer4 handler that replicates a connection so @@ -48,7 +48,7 @@ type Handler struct { } // CaddyModule returns the Caddy module information. -func (Handler) CaddyModule() caddy.ModuleInfo { +func (*Handler) CaddyModule() caddy.ModuleInfo { return caddy.ModuleInfo{ ID: "layer4.handlers.tee", New: func() caddy.Module { return new(Handler) }, @@ -74,7 +74,7 @@ func (t *Handler) Provision(ctx caddy.Context) error { } // Handle handles the connection. -func (t Handler) Handle(cx *layer4.Connection, next layer4.Handler) error { +func (t *Handler) Handle(cx *layer4.Connection, next layer4.Handler) error { // what is read by the next handler will also be // read by the branch handlers; this is done by // writing conn's reads into a pipe, and having diff --git a/modules/l4throttle/throttle.go b/modules/l4throttle/throttle.go index 712642c..fae47b6 100644 --- a/modules/l4throttle/throttle.go +++ b/modules/l4throttle/throttle.go @@ -29,7 +29,7 @@ import ( ) func init() { - caddy.RegisterModule(Handler{}) + caddy.RegisterModule(&Handler{}) } // Handler throttles connections using leaky bucket rate limiting. @@ -58,7 +58,7 @@ type Handler struct { } // CaddyModule returns the Caddy module information. -func (Handler) CaddyModule() caddy.ModuleInfo { +func (*Handler) CaddyModule() caddy.ModuleInfo { return caddy.ModuleInfo{ ID: "layer4.handlers.throttle", New: func() caddy.Module { return new(Handler) }, @@ -93,7 +93,7 @@ func (h *Handler) Provision(ctx caddy.Context) error { } // Handle handles the connection. -func (h Handler) Handle(cx *layer4.Connection, next layer4.Handler) error { +func (h *Handler) Handle(cx *layer4.Connection, next layer4.Handler) error { var localLimiter *rate.Limiter if h.ReadBytesPerSecond > 0 || h.ReadBurstSize > 0 { localLimiter = rate.NewLimiter(rate.Limit(h.ReadBytesPerSecond), h.ReadBurstSize) diff --git a/modules/l4tls/alpn_matcher.go b/modules/l4tls/alpn_matcher.go index 6818b0f..3ae55e5 100644 --- a/modules/l4tls/alpn_matcher.go +++ b/modules/l4tls/alpn_matcher.go @@ -23,22 +23,22 @@ import ( ) func init() { - caddy.RegisterModule(MatchALPN{}) + caddy.RegisterModule(&MatchALPN{}) } type MatchALPN []string // CaddyModule returns the Caddy module information. -func (MatchALPN) CaddyModule() caddy.ModuleInfo { +func (*MatchALPN) CaddyModule() caddy.ModuleInfo { return caddy.ModuleInfo{ ID: "tls.handshake_match.alpn", New: func() caddy.Module { return new(MatchALPN) }, } } -func (m MatchALPN) Match(hello *tls.ClientHelloInfo) bool { +func (m *MatchALPN) Match(hello *tls.ClientHelloInfo) bool { clientProtocols := hello.SupportedProtos - for _, alpn := range m { + for _, alpn := range *m { for _, clientProtocol := range clientProtocols { if alpn == clientProtocol { return true diff --git a/modules/l4tls/handler.go b/modules/l4tls/handler.go index dd467df..53b37a7 100644 --- a/modules/l4tls/handler.go +++ b/modules/l4tls/handler.go @@ -28,7 +28,7 @@ import ( ) func init() { - caddy.RegisterModule(Handler{}) + caddy.RegisterModule(&Handler{}) } // Handler is a connection handler that terminates TLS. @@ -40,7 +40,7 @@ type Handler struct { } // CaddyModule returns the Caddy module information. -func (Handler) CaddyModule() caddy.ModuleInfo { +func (*Handler) CaddyModule() caddy.ModuleInfo { return caddy.ModuleInfo{ ID: "layer4.handlers.tls", New: func() caddy.Module { return new(Handler) }, diff --git a/modules/l4tls/matcher.go b/modules/l4tls/matcher.go index eaea266..81c4793 100644 --- a/modules/l4tls/matcher.go +++ b/modules/l4tls/matcher.go @@ -27,7 +27,7 @@ import ( ) func init() { - caddy.RegisterModule(MatchTLS{}) + caddy.RegisterModule(&MatchTLS{}) } // MatchTLS is able to match TLS connections. Its structure @@ -41,7 +41,7 @@ type MatchTLS struct { } // CaddyModule returns the Caddy module information. -func (MatchTLS) CaddyModule() caddy.ModuleInfo { +func (*MatchTLS) CaddyModule() caddy.ModuleInfo { return caddy.ModuleInfo{ ID: "layer4.matchers.tls", New: func() caddy.Module { return new(MatchTLS) }, @@ -54,7 +54,7 @@ func (m *MatchTLS) UnmarshalJSON(b []byte) error { } // MarshalJSON satisfies the json.Marshaler interface. -func (m MatchTLS) MarshalJSON() ([]byte, error) { +func (m *MatchTLS) MarshalJSON() ([]byte, error) { return json.Marshal(m.MatchersRaw) } @@ -72,7 +72,7 @@ func (m *MatchTLS) Provision(ctx caddy.Context) error { } // Match returns true if the connection is a TLS handshake. -func (m MatchTLS) Match(cx *layer4.Connection) (bool, error) { +func (m *MatchTLS) Match(cx *layer4.Connection) (bool, error) { // read the header bytes const recordHeaderLen = 5 hdr := make([]byte, recordHeaderLen) diff --git a/modules/l4xmpp/matcher.go b/modules/l4xmpp/matcher.go index 55ce1b1..f9409f0 100644 --- a/modules/l4xmpp/matcher.go +++ b/modules/l4xmpp/matcher.go @@ -24,14 +24,14 @@ import ( ) func init() { - caddy.RegisterModule(MatchXMPP{}) + caddy.RegisterModule(&MatchXMPP{}) } // MatchXMPP is able to match XMPP connections. type MatchXMPP struct{} // CaddyModule returns the Caddy module information. -func (MatchXMPP) CaddyModule() caddy.ModuleInfo { +func (*MatchXMPP) CaddyModule() caddy.ModuleInfo { return caddy.ModuleInfo{ ID: "layer4.matchers.xmpp", New: func() caddy.Module { return new(MatchXMPP) }, @@ -39,7 +39,7 @@ func (MatchXMPP) CaddyModule() caddy.ModuleInfo { } // Match returns true if the connection looks like XMPP. -func (m MatchXMPP) Match(cx *layer4.Connection) (bool, error) { +func (m *MatchXMPP) Match(cx *layer4.Connection) (bool, error) { p := make([]byte, minXmppLength) n, err := io.ReadFull(cx, p) if err != nil || n < minXmppLength { // needs at least 50 (fix for adium/pidgin) From ab2e0f444cf243ee16c4c1dff4f8c7859c77f757 Mon Sep 17 00:00:00 2001 From: vnxme <46669194+vnxme@users.noreply.github.com> Date: Wed, 24 Jul 2024 17:42:11 +0300 Subject: [PATCH 09/14] Fix warnings: remove deprecated weekrand.Seed() call --- modules/l4proxy/loadbalancing.go | 2 -- 1 file changed, 2 deletions(-) diff --git a/modules/l4proxy/loadbalancing.go b/modules/l4proxy/loadbalancing.go index a1a0fe2..0c1f828 100644 --- a/modules/l4proxy/loadbalancing.go +++ b/modules/l4proxy/loadbalancing.go @@ -82,8 +82,6 @@ func init() { caddy.RegisterModule(&RoundRobinSelection{}) caddy.RegisterModule(&FirstSelection{}) caddy.RegisterModule(&IPHashSelection{}) - - weakrand.Seed(time.Now().UTC().UnixNano()) } // RandomSelection is a policy that selects From 1021230e434fcf5de0b111880022bd36aa799dde Mon Sep 17 00:00:00 2001 From: vnxme <46669194+vnxme@users.noreply.github.com> Date: Wed, 24 Jul 2024 16:29:33 +0300 Subject: [PATCH 10/14] Fix possible linter failures: imports order --- integration/caddyfile_adapt_test.go | 1 + modules/l4echo/echo.go | 1 + modules/l4http/httpmatcher.go | 5 +++-- modules/l4http/httpmatcher_test.go | 3 ++- modules/l4postgres/matcher.go | 1 + modules/l4proxy/loadbalancing.go | 1 + modules/l4proxy/proxy.go | 5 +++-- modules/l4proxy/upstream.go | 1 + modules/l4proxyprotocol/handler.go | 3 ++- modules/l4proxyprotocol/handler_test.go | 3 ++- modules/l4proxyprotocol/matcher.go | 1 + modules/l4proxyprotocol/matcher_test.go | 3 ++- modules/l4rdp/matcher.go | 1 + modules/l4rdp/matcher_test.go | 3 ++- modules/l4socks/socks4_matcher.go | 1 + modules/l4socks/socks4_matcher_test.go | 3 ++- modules/l4socks/socks5_handler.go | 3 ++- modules/l4socks/socks5_handler_test.go | 3 ++- modules/l4socks/socks5_matcher.go | 1 + modules/l4socks/socks5_matcher_test.go | 3 ++- modules/l4ssh/matcher.go | 1 + modules/l4subroute/handler.go | 3 ++- modules/l4tee/tee.go | 3 ++- modules/l4throttle/throttle.go | 3 ++- modules/l4tls/handler.go | 3 ++- modules/l4tls/matcher.go | 3 ++- modules/l4xmpp/matcher.go | 1 + 27 files changed, 45 insertions(+), 18 deletions(-) diff --git a/integration/caddyfile_adapt_test.go b/integration/caddyfile_adapt_test.go index b138b0c..14537b1 100644 --- a/integration/caddyfile_adapt_test.go +++ b/integration/caddyfile_adapt_test.go @@ -10,6 +10,7 @@ import ( "testing" "github.com/caddyserver/caddy/v2/caddytest" + _ "github.com/mholt/caddy-l4" ) diff --git a/modules/l4echo/echo.go b/modules/l4echo/echo.go index 3dc9ea0..6ab0fab 100644 --- a/modules/l4echo/echo.go +++ b/modules/l4echo/echo.go @@ -19,6 +19,7 @@ import ( "github.com/caddyserver/caddy/v2" "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" + "github.com/mholt/caddy-l4/layer4" ) diff --git a/modules/l4http/httpmatcher.go b/modules/l4http/httpmatcher.go index 0878639..104c195 100644 --- a/modules/l4http/httpmatcher.go +++ b/modules/l4http/httpmatcher.go @@ -26,10 +26,11 @@ import ( "github.com/caddyserver/caddy/v2" "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" "github.com/caddyserver/caddy/v2/modules/caddyhttp" - "github.com/mholt/caddy-l4/layer4" - "github.com/mholt/caddy-l4/modules/l4tls" "golang.org/x/net/http2" "golang.org/x/net/http2/hpack" + + "github.com/mholt/caddy-l4/layer4" + "github.com/mholt/caddy-l4/modules/l4tls" ) func init() { diff --git a/modules/l4http/httpmatcher_test.go b/modules/l4http/httpmatcher_test.go index 5b4f14a..7028436 100644 --- a/modules/l4http/httpmatcher_test.go +++ b/modules/l4http/httpmatcher_test.go @@ -11,8 +11,9 @@ import ( "github.com/caddyserver/caddy/v2" "github.com/caddyserver/caddy/v2/modules/caddyhttp" - "github.com/mholt/caddy-l4/layer4" "go.uber.org/zap" + + "github.com/mholt/caddy-l4/layer4" ) func assertNoError(t *testing.T, err error) { diff --git a/modules/l4postgres/matcher.go b/modules/l4postgres/matcher.go index 99c4e48..c97d18e 100644 --- a/modules/l4postgres/matcher.go +++ b/modules/l4postgres/matcher.go @@ -30,6 +30,7 @@ import ( "github.com/caddyserver/caddy/v2" "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" + "github.com/mholt/caddy-l4/layer4" ) diff --git a/modules/l4proxy/loadbalancing.go b/modules/l4proxy/loadbalancing.go index 0c1f828..5b80955 100644 --- a/modules/l4proxy/loadbalancing.go +++ b/modules/l4proxy/loadbalancing.go @@ -26,6 +26,7 @@ import ( "github.com/caddyserver/caddy/v2" "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" + "github.com/mholt/caddy-l4/layer4" ) diff --git a/modules/l4proxy/proxy.go b/modules/l4proxy/proxy.go index ee8184e..f1a8e50 100644 --- a/modules/l4proxy/proxy.go +++ b/modules/l4proxy/proxy.go @@ -17,7 +17,6 @@ package l4proxy import ( "crypto/tls" "fmt" - "github.com/caddyserver/caddy/v2/caddyconfig" "io" "log" "net" @@ -28,12 +27,14 @@ import ( "time" "github.com/caddyserver/caddy/v2" + "github.com/caddyserver/caddy/v2/caddyconfig" "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" "github.com/mastercactapus/proxyprotocol" + "go.uber.org/zap" + "github.com/mholt/caddy-l4/layer4" "github.com/mholt/caddy-l4/modules/l4proxyprotocol" "github.com/mholt/caddy-l4/modules/l4tls" - "go.uber.org/zap" ) func init() { diff --git a/modules/l4proxy/upstream.go b/modules/l4proxy/upstream.go index 47223bd..63dc7cf 100644 --- a/modules/l4proxy/upstream.go +++ b/modules/l4proxy/upstream.go @@ -26,6 +26,7 @@ import ( "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" "github.com/caddyserver/caddy/v2/modules/caddyhttp/reverseproxy" "github.com/caddyserver/caddy/v2/modules/caddytls" + "github.com/mholt/caddy-l4/layer4" ) diff --git a/modules/l4proxyprotocol/handler.go b/modules/l4proxyprotocol/handler.go index 5a9c432..aa3242a 100644 --- a/modules/l4proxyprotocol/handler.go +++ b/modules/l4proxyprotocol/handler.go @@ -23,8 +23,9 @@ import ( "github.com/caddyserver/caddy/v2" "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" "github.com/mastercactapus/proxyprotocol" - "github.com/mholt/caddy-l4/layer4" "go.uber.org/zap" + + "github.com/mholt/caddy-l4/layer4" ) func init() { diff --git a/modules/l4proxyprotocol/handler_test.go b/modules/l4proxyprotocol/handler_test.go index b20e2a6..3a8997a 100644 --- a/modules/l4proxyprotocol/handler_test.go +++ b/modules/l4proxyprotocol/handler_test.go @@ -8,8 +8,9 @@ import ( "testing" "github.com/caddyserver/caddy/v2" - "github.com/mholt/caddy-l4/layer4" "go.uber.org/zap" + + "github.com/mholt/caddy-l4/layer4" ) func assertString(t *testing.T, expected string, value string) { diff --git a/modules/l4proxyprotocol/matcher.go b/modules/l4proxyprotocol/matcher.go index 89e1a5a..b4a4e15 100644 --- a/modules/l4proxyprotocol/matcher.go +++ b/modules/l4proxyprotocol/matcher.go @@ -20,6 +20,7 @@ import ( "github.com/caddyserver/caddy/v2" "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" + "github.com/mholt/caddy-l4/layer4" ) diff --git a/modules/l4proxyprotocol/matcher_test.go b/modules/l4proxyprotocol/matcher_test.go index 8e27691..1e48cfb 100644 --- a/modules/l4proxyprotocol/matcher_test.go +++ b/modules/l4proxyprotocol/matcher_test.go @@ -7,8 +7,9 @@ import ( "sync" "testing" - "github.com/mholt/caddy-l4/layer4" "go.uber.org/zap" + + "github.com/mholt/caddy-l4/layer4" ) var ProxyV1Example = []byte("PROXY TCP4 192.168.0.1 192.168.0.11 56324 443\r\n") diff --git a/modules/l4rdp/matcher.go b/modules/l4rdp/matcher.go index 3be133b..5f99ec1 100644 --- a/modules/l4rdp/matcher.go +++ b/modules/l4rdp/matcher.go @@ -27,6 +27,7 @@ import ( "github.com/caddyserver/caddy/v2" "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" + "github.com/mholt/caddy-l4/layer4" ) diff --git a/modules/l4rdp/matcher_test.go b/modules/l4rdp/matcher_test.go index 223d5a9..594cdb3 100644 --- a/modules/l4rdp/matcher_test.go +++ b/modules/l4rdp/matcher_test.go @@ -22,8 +22,9 @@ import ( "testing" "github.com/caddyserver/caddy/v2" - "github.com/mholt/caddy-l4/layer4" "go.uber.org/zap" + + "github.com/mholt/caddy-l4/layer4" ) func assertNoError(t *testing.T, err error) { diff --git a/modules/l4socks/socks4_matcher.go b/modules/l4socks/socks4_matcher.go index 782c1b1..f869f3c 100644 --- a/modules/l4socks/socks4_matcher.go +++ b/modules/l4socks/socks4_matcher.go @@ -10,6 +10,7 @@ import ( "github.com/caddyserver/caddy/v2" "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" + "github.com/mholt/caddy-l4/layer4" ) diff --git a/modules/l4socks/socks4_matcher_test.go b/modules/l4socks/socks4_matcher_test.go index 6757b70..9adafe1 100644 --- a/modules/l4socks/socks4_matcher_test.go +++ b/modules/l4socks/socks4_matcher_test.go @@ -7,8 +7,9 @@ import ( "testing" "github.com/caddyserver/caddy/v2" - "github.com/mholt/caddy-l4/layer4" "go.uber.org/zap" + + "github.com/mholt/caddy-l4/layer4" ) func assertNoError(t *testing.T, err error) { diff --git a/modules/l4socks/socks5_handler.go b/modules/l4socks/socks5_handler.go index 69a6eee..3c9bb9f 100644 --- a/modules/l4socks/socks5_handler.go +++ b/modules/l4socks/socks5_handler.go @@ -7,9 +7,10 @@ import ( "github.com/caddyserver/caddy/v2" "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" - "github.com/mholt/caddy-l4/layer4" "github.com/things-go/go-socks5" "go.uber.org/zap" + + "github.com/mholt/caddy-l4/layer4" ) func init() { diff --git a/modules/l4socks/socks5_handler_test.go b/modules/l4socks/socks5_handler_test.go index 2a35534..601bbf4 100644 --- a/modules/l4socks/socks5_handler_test.go +++ b/modules/l4socks/socks5_handler_test.go @@ -10,8 +10,9 @@ import ( "testing" "github.com/caddyserver/caddy/v2" - "github.com/mholt/caddy-l4/layer4" "go.uber.org/zap" + + "github.com/mholt/caddy-l4/layer4" ) func replay(t *testing.T, handler *Socks5Handler, expectedError string, messages [][]byte) { diff --git a/modules/l4socks/socks5_matcher.go b/modules/l4socks/socks5_matcher.go index 4a2f39d..a96f6ac 100644 --- a/modules/l4socks/socks5_matcher.go +++ b/modules/l4socks/socks5_matcher.go @@ -6,6 +6,7 @@ import ( "github.com/caddyserver/caddy/v2" "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" + "github.com/mholt/caddy-l4/layer4" ) diff --git a/modules/l4socks/socks5_matcher_test.go b/modules/l4socks/socks5_matcher_test.go index b1ff95d..f5c5bd2 100644 --- a/modules/l4socks/socks5_matcher_test.go +++ b/modules/l4socks/socks5_matcher_test.go @@ -7,8 +7,9 @@ import ( "testing" "github.com/caddyserver/caddy/v2" - "github.com/mholt/caddy-l4/layer4" "go.uber.org/zap" + + "github.com/mholt/caddy-l4/layer4" ) func TestSocks5Matcher_Match(t *testing.T) { diff --git a/modules/l4ssh/matcher.go b/modules/l4ssh/matcher.go index 21e465b..3fb5e17 100644 --- a/modules/l4ssh/matcher.go +++ b/modules/l4ssh/matcher.go @@ -20,6 +20,7 @@ import ( "github.com/caddyserver/caddy/v2" "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" + "github.com/mholt/caddy-l4/layer4" ) diff --git a/modules/l4subroute/handler.go b/modules/l4subroute/handler.go index 8d86a77..b36c5e2 100644 --- a/modules/l4subroute/handler.go +++ b/modules/l4subroute/handler.go @@ -20,8 +20,9 @@ import ( "github.com/caddyserver/caddy/v2" "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" - "github.com/mholt/caddy-l4/layer4" "go.uber.org/zap" + + "github.com/mholt/caddy-l4/layer4" ) func init() { diff --git a/modules/l4tee/tee.go b/modules/l4tee/tee.go index b4942a5..f0cf766 100644 --- a/modules/l4tee/tee.go +++ b/modules/l4tee/tee.go @@ -21,8 +21,9 @@ import ( "github.com/caddyserver/caddy/v2" "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" - "github.com/mholt/caddy-l4/layer4" "go.uber.org/zap" + + "github.com/mholt/caddy-l4/layer4" ) func init() { diff --git a/modules/l4throttle/throttle.go b/modules/l4throttle/throttle.go index fae47b6..9794c56 100644 --- a/modules/l4throttle/throttle.go +++ b/modules/l4throttle/throttle.go @@ -23,9 +23,10 @@ import ( "github.com/caddyserver/caddy/v2" "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" - "github.com/mholt/caddy-l4/layer4" "go.uber.org/zap" "golang.org/x/time/rate" + + "github.com/mholt/caddy-l4/layer4" ) func init() { diff --git a/modules/l4tls/handler.go b/modules/l4tls/handler.go index 53b37a7..49e8afa 100644 --- a/modules/l4tls/handler.go +++ b/modules/l4tls/handler.go @@ -23,8 +23,9 @@ import ( "github.com/caddyserver/caddy/v2" "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" "github.com/caddyserver/caddy/v2/modules/caddytls" - "github.com/mholt/caddy-l4/layer4" "go.uber.org/zap" + + "github.com/mholt/caddy-l4/layer4" ) func init() { diff --git a/modules/l4tls/matcher.go b/modules/l4tls/matcher.go index 81c4793..ca12a26 100644 --- a/modules/l4tls/matcher.go +++ b/modules/l4tls/matcher.go @@ -22,8 +22,9 @@ import ( "github.com/caddyserver/caddy/v2" "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" "github.com/caddyserver/caddy/v2/modules/caddytls" - "github.com/mholt/caddy-l4/layer4" "go.uber.org/zap" + + "github.com/mholt/caddy-l4/layer4" ) func init() { diff --git a/modules/l4xmpp/matcher.go b/modules/l4xmpp/matcher.go index f9409f0..e930f24 100644 --- a/modules/l4xmpp/matcher.go +++ b/modules/l4xmpp/matcher.go @@ -20,6 +20,7 @@ import ( "github.com/caddyserver/caddy/v2" "github.com/caddyserver/caddy/v2/caddyconfig/caddyfile" + "github.com/mholt/caddy-l4/layer4" ) From 364833f6877d2b7a92b7a457120b702c755bde37 Mon Sep 17 00:00:00 2001 From: vnxme <46669194+vnxme@users.noreply.github.com> Date: Wed, 24 Jul 2024 18:03:18 +0300 Subject: [PATCH 11/14] Fix README: caddyfile support --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 76b2e8c..f7e74e9 100644 --- a/README.md +++ b/README.md @@ -74,7 +74,7 @@ Alternatively, to hack on the plugin code, you can clone it down, then build and ## Writing config -Since this app does not support Caddyfile (yet?), you will have to use Caddy's native JSON format to configure it. I highly recommend [this caddy-json-schema plugin by @abiosoft](https://github.com/abiosoft/caddy-json-schema) which can give you auto-complete and documentation right in your editor as you write your config! +This app supports Caddyfile, but you may also use Caddy's native JSON format to configure it. I highly recommend [this caddy-json-schema plugin by @abiosoft](https://github.com/abiosoft/caddy-json-schema) which can give you auto-complete and documentation right in your editor as you write your config! See below for some examples to help you get started. From 9ba9e08f5be0ab4189157f966c96ed7f631adc26 Mon Sep 17 00:00:00 2001 From: vnxme <46669194+vnxme@users.noreply.github.com> Date: Thu, 1 Aug 2024 23:40:01 +0300 Subject: [PATCH 12/14] Fix README: sort matchers and handlers by name --- README.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index f7e74e9..a0b05db 100644 --- a/README.md +++ b/README.md @@ -31,29 +31,29 @@ This app works similarly to the `http` app. You define servers, and each server Current matchers: - **layer4.matchers.http** - matches connections that start with HTTP requests. In addition, any [`http.matchers` modules](https://caddyserver.com/docs/modules/) can be used for matching on HTTP-specific properties of requests, such as header or path. Note that only the first request of each connection can be used for matching. -- **layer4.matchers.tls** - matches connections that start with TLS handshakes. In addition, any [`tls.handshake_match` modules](https://caddyserver.com/docs/modules/) can be used for matching on TLS-specific properties of the ClientHello, such as ServerName (SNI). -- **layer4.matchers.ssh** - matches connections that look like SSH connections. -- **layer4.matchers.postgres** - matches connections that look like Postgres connections. -- **layer4.matchers.remote_ip** - matches connections based on remote IP (or CIDR range). - **layer4.matchers.local_ip** - matches connections based on local IP (or CIDR range). - **layer4.matchers.not** - matches connections that aren't matched by inner matcher sets. +- **layer4.matchers.postgres** - matches connections that look like Postgres connections. - **layer4.matchers.proxy_protocol** - matches connections that start with [HAPROXY proxy protocol](https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt). - **layer4.matchers.rdp** - matches connections that look like [RDP](https://winprotocoldoc.blob.core.windows.net/productionwindowsarchives/MS-RDPBCGR/%5BMS-RDPBCGR%5D.pdf). - **layer4.matchers.regexp** - matches connections that have the first packet bytes matching a regular expression. +- **layer4.matchers.remote_ip** - matches connections based on remote IP (or CIDR range). - **layer4.matchers.socks4** - matches connections that look like [SOCKSv4](https://www.openssh.com/txt/socks4.protocol). - **layer4.matchers.socks5** - matches connections that look like [SOCKSv5](https://www.rfc-editor.org/rfc/rfc1928.html). +- **layer4.matchers.ssh** - matches connections that look like SSH connections. +- **layer4.matchers.tls** - matches connections that start with TLS handshakes. In addition, any [`tls.handshake_match` modules](https://caddyserver.com/docs/modules/) can be used for matching on TLS-specific properties of the ClientHello, such as ServerName (SNI). - **layer4.matchers.xmpp** - matches connections that look like [XMPP](https://xmpp.org/about/technology-overview/). Current handlers: - **layer4.handlers.echo** - An echo server. - **layer4.handlers.proxy** - Powerful layer 4 proxy, capable of multiple upstreams (with load balancing and health checks) and establishing new TLS connections to backends. Optionally supports sending the [HAProxy proxy protocol](https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt). +- **layer4.handlers.proxy_protocol** - Accepts the [HAPROXY proxy protocol](https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt) on the receiving side. +- **layer4.handlers.socks5** - Handles [SOCKSv5](https://www.rfc-editor.org/rfc/rfc1928.html) proxy protocol connections. - **layer4.handlers.subroute** - Implements recursion logic, i.e. allows to match and handle already matched connections. - **layer4.handlers.tee** - Branches the handling of a connection into a concurrent handler chain. - **layer4.handlers.throttle** - Throttle connections to simulate slowness and latency. - **layer4.handlers.tls** - TLS termination. -- **layer4.handlers.proxy_protocol** - Accepts the [HAPROXY proxy protocol](https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt) on the receiving side. -- **layer4.handlers.socks5** - Handles [SOCKSv5](https://www.rfc-editor.org/rfc/rfc1928.html) proxy protocol connections. Like the `http` app, some handlers are "terminal" meaning that they don't call the next handler in the chain. For example: `echo` and `proxy` are terminal handlers because they consume the client's input. From ad9feb3045a01b53e0ce5d6aaa7b87a596b1e1ec Mon Sep 17 00:00:00 2001 From: vnxme <46669194+vnxme@users.noreply.github.com> Date: Thu, 1 Aug 2024 23:44:03 +0300 Subject: [PATCH 13/14] Fix warnings: one more typo in comments --- layer4/matchers.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/layer4/matchers.go b/layer4/matchers.go index 1a26321..8409cf1 100644 --- a/layer4/matchers.go +++ b/layer4/matchers.go @@ -164,7 +164,7 @@ func (m *MatchRemoteIP) getRemoteIP(cx *Connection) (netip.Addr, error) { // UnmarshalCaddyfile sets up the MatchRemoteIP from Caddyfile tokens. Syntax: // -// ip +// remote_ip func (m *MatchRemoteIP) UnmarshalCaddyfile(d *caddyfile.Dispenser) error { _, wrapper := d.Next(), d.Val() // consume wrapper name From cbf58884880473a40812eebaff35329044fd1aff Mon Sep 17 00:00:00 2001 From: vnxme <46669194+vnxme@users.noreply.github.com> Date: Fri, 2 Aug 2024 10:33:09 +0300 Subject: [PATCH 14/14] Fix warnings: potential nil pointer dereference, optimized --- modules/l4http/httpmatcher.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/modules/l4http/httpmatcher.go b/modules/l4http/httpmatcher.go index 104c195..ffbd54c 100644 --- a/modules/l4http/httpmatcher.go +++ b/modules/l4http/httpmatcher.go @@ -172,11 +172,13 @@ func (m *MatchHTTP) handleHttp2WithPriorKnowledge(reader io.Reader, req *http.Re return err } if frame.Header().Type == http2.FrameHeaders { + maxAttempts = 0 break - } else if i == maxAttempts-1 { - return fmt.Errorf("failed to read a http2 headers frame after %d attempts", maxAttempts) } } + if maxAttempts != 0 { + return fmt.Errorf("failed to read a http2 headers frame after %d attempts", maxAttempts) + } decoder := hpack.NewDecoder(4096, nil) // max table size 4096 from http2.initialHeaderTableSize headers, err := decoder.DecodeFull((frame.(*http2.HeadersFrame)).HeaderBlockFragment())