TUN-8861: Add session limiter to TCP session manager

## Summary
In order to make cloudflared behavior more predictable and
prevent an exhaustion of resources, we have decided to add
session limits that can be configured by the user. This commit
adds the session limiter to the HTTP/TCP handling path.
For now the limiter is set to run only in unlimited mode.
This commit is contained in:
João "Pisco" Fernandes
2025-01-14 14:05:18 +00:00
parent bf4954e96a
commit 8bfe111cab
12 changed files with 275 additions and 102 deletions

View File

@@ -9,10 +9,14 @@ import (
"time"
"github.com/pkg/errors"
pkgerrors "github.com/pkg/errors"
"github.com/rs/zerolog"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/trace"
"github.com/cloudflare/cloudflared/management"
cfdsession "github.com/cloudflare/cloudflared/session"
"github.com/cloudflare/cloudflared/carrier"
"github.com/cloudflare/cloudflared/cfio"
"github.com/cloudflare/cloudflared/connection"
@@ -30,11 +34,11 @@ const (
// Proxy represents a means to Proxy between cloudflared and the origin services.
type Proxy struct {
ingressRules ingress.Ingress
warpRouting *ingress.WarpRoutingService
management *ingress.ManagementService
tags []pogs.Tag
log *zerolog.Logger
ingressRules ingress.Ingress
warpRouting *ingress.WarpRoutingService
tags []pogs.Tag
sessionLimiter cfdsession.Limiter
log *zerolog.Logger
}
// NewOriginProxy returns a new instance of the Proxy struct.
@@ -42,13 +46,15 @@ func NewOriginProxy(
ingressRules ingress.Ingress,
warpRouting ingress.WarpRoutingConfig,
tags []pogs.Tag,
sessionLimiter cfdsession.Limiter,
writeTimeout time.Duration,
log *zerolog.Logger,
) *Proxy {
proxy := &Proxy{
ingressRules: ingressRules,
tags: tags,
log: log,
ingressRules: ingressRules,
tags: tags,
sessionLimiter: sessionLimiter,
log: log,
}
proxy.warpRouting = ingress.NewWarpRoutingService(warpRouting, writeTimeout)
@@ -64,7 +70,7 @@ func (p *Proxy) applyIngressMiddleware(rule *ingress.Rule, r *http.Request, w co
}
if result.ShouldFilterRequest {
w.WriteRespHeaders(result.StatusCode, nil)
_ = w.WriteRespHeaders(result.StatusCode, nil)
return fmt.Errorf("request filtered by middleware handler (%s) due to: %s", handler.Name(), result.Reason), true
}
}
@@ -152,10 +158,18 @@ func (p *Proxy) ProxyTCP(
return err
}
logger := newTCPLogger(p.log, req)
// Try to start a new session
if err := p.sessionLimiter.Acquire(management.TCP.String()); err != nil {
logger.Warn().Msg("Too many concurrent sessions being handled, rejecting tcp proxy")
return pkgerrors.Wrap(err, "failed to start tcp session due to rate limiting")
}
defer p.sessionLimiter.Release()
serveCtx, cancel := context.WithCancel(ctx)
defer cancel()
logger := newTCPLogger(p.log, req)
tracedCtx := tracing.NewTracedContext(serveCtx, req.CfTraceID, &logger)
logger.Debug().Msg("tcp proxy stream started")