diff --git a/handler/http/websocket.go b/handler/http/websocket.go index 0bba5d84..6fd4c6d8 100644 --- a/handler/http/websocket.go +++ b/handler/http/websocket.go @@ -51,6 +51,7 @@ func (h *httpHandler) copyWebsocketDirection(ctx context.Context, r io.Reader, w } ro2 := &xrecorder.HandlerRecorderObject{} *ro2 = *ro + ro2.HTTP = nil r2 := ro2 limiter := rate.NewLimiter(rate.Limit(sampleRate), int(sampleRate)) diff --git a/handler/tunnel/bind.go b/handler/tunnel/bind.go index 77bb47f2..ca0dfc93 100644 --- a/handler/tunnel/bind.go +++ b/handler/tunnel/bind.go @@ -41,9 +41,7 @@ func (h *tunnelHandler) handleBind(ctx context.Context, conn net.Conn, network, if host == "" || h.md.ingress == nil { host = endpoint } else if host != endpoint { - if rule := h.md.ingress.GetRule(ctx, host, ingress.WithService(h.options.Service)); rule != nil && rule.Endpoint != tunnelID.String() { - host = endpoint - } + host = endpoint } addr := net.JoinHostPort(host, port) diff --git a/handler/tunnel/entrypoint.go b/handler/tunnel/entrypoint.go index 3811bfd1..3aa825ca 100644 --- a/handler/tunnel/entrypoint.go +++ b/handler/tunnel/entrypoint.go @@ -278,6 +278,24 @@ func (ep *entrypoint) httpRoundTrip(ctx context.Context, rw io.ReadWriteCloser, } else { req.Header.Set(httpHeaderSID, ro.SID) } + + // Loop detection: if Gost-Forwarded-Node contains our own node ID, + // the request has already passed through this entrypoint and is looping. + for _, node := range strings.Split(req.Header.Get(httpHeaderForwardedNode), ",") { + if strings.TrimSpace(node) == ep.node { + log.Warn("forwarding loop detected, rejecting request") + res := &http.Response{ + ProtoMajor: req.ProtoMajor, + ProtoMinor: req.ProtoMinor, + Header: http.Header{}, + StatusCode: http.StatusServiceUnavailable, + } + ro.HTTP.StatusCode = res.StatusCode + res.Write(rw) + return nil + } + } + req.Header.Set(httpHeaderForwardedNode, ro.Node) host := req.Host diff --git a/internal/util/forwarder/sniffer_ws.go b/internal/util/forwarder/sniffer_ws.go index 42c167fb..7db35512 100644 --- a/internal/util/forwarder/sniffer_ws.go +++ b/internal/util/forwarder/sniffer_ws.go @@ -31,6 +31,7 @@ func (h *Sniffer) sniffingWebsocketFrame(ctx context.Context, rw, cc io.ReadWrit go func() { ro2 := &xrecorder.HandlerRecorderObject{} *ro2 = *ro + ro2.HTTP = nil ro := ro2 limiter := rate.NewLimiter(rate.Limit(sampleRate), int(sampleRate)) @@ -57,6 +58,7 @@ func (h *Sniffer) sniffingWebsocketFrame(ctx context.Context, rw, cc io.ReadWrit go func() { ro2 := &xrecorder.HandlerRecorderObject{} *ro2 = *ro + ro2.HTTP = nil ro := ro2 limiter := rate.NewLimiter(rate.Limit(sampleRate), int(sampleRate)) diff --git a/internal/util/sniffing/sniffer_ws.go b/internal/util/sniffing/sniffer_ws.go index d657f212..ae136bfb 100644 --- a/internal/util/sniffing/sniffer_ws.go +++ b/internal/util/sniffing/sniffer_ws.go @@ -30,6 +30,7 @@ func (h *Sniffer) sniffingWebsocketFrame(ctx context.Context, rw, cc io.ReadWrit go func() { ro2 := &xrecorder.HandlerRecorderObject{} *ro2 = *ro + ro2.HTTP = nil ro := ro2 limiter := rate.NewLimiter(rate.Limit(sampleRate), int(sampleRate)) @@ -56,6 +57,7 @@ func (h *Sniffer) sniffingWebsocketFrame(ctx context.Context, rw, cc io.ReadWrit go func() { ro2 := &xrecorder.HandlerRecorderObject{} *ro2 = *ro + ro2.HTTP = nil ro := ro2 limiter := rate.NewLimiter(rate.Limit(sampleRate), int(sampleRate))