Bläddra i källkod

fix: apply idle timeout to domain fronting relay connections

Domain fronting relay (for non-Telegram traffic) had no idle timeout,
causing worker pool exhaustion under traffic spikes.

The ProxyOpts.IdleTimeout field existed but was never wired into the
proxy. Now domain fronting connections are wrapped with per-read/write
deadlines reset to the configured idle timeout (default 1m), so stale
or slowloris-style connections are reaped promptly.

Fixes #378
tags/v2.2.5^2^2
Alexey Dolotov 1 månad sedan
förälder
incheckning
836090ebdf
4 ändrade filer med 32 tillägg och 2 borttagningar
  1. 1
    0
      internal/cli/run_proxy.go
  2. 19
    0
      mtglib/conns.go
  3. 4
    2
      mtglib/proxy.go
  4. 8
    0
      mtglib/proxy_opts.go

+ 1
- 0
internal/cli/run_proxy.go Visa fil

@@ -262,6 +262,7 @@ func runProxy(conf *config.Config, version string) error { //nolint: funlen
262 262
 
263 263
 		AllowFallbackOnUnknownDC: conf.AllowFallbackOnUnknownDC.Get(false),
264 264
 		TolerateTimeSkewness:     conf.TolerateTimeSkewness.Value,
265
+		IdleTimeout:              conf.Network.Timeout.Idle.Get(mtglib.DefaultIdleTimeout),
265 266
 
266 267
 		DoppelGangerURLs:    doppelGangerURLs,
267 268
 		DoppelGangerPerRaid: conf.Defense.Doppelganger.Repeats.Get(mtglib.DoppelGangerPerRaid),

+ 19
- 0
mtglib/conns.go Visa fil

@@ -6,6 +6,7 @@ import (
6 6
 	"fmt"
7 7
 	"io"
8 8
 	"net"
9
+	"time"
9 10
 
10 11
 	"github.com/9seconds/mtg/v2/essentials"
11 12
 	"github.com/pires/go-proxyproto"
@@ -95,3 +96,21 @@ func newConnProxyProtocol(source, target essentials.Conn) *connProxyProtocol {
95 96
 		sourceAddr: source.RemoteAddr(),
96 97
 	}
97 98
 }
99
+
100
+type connIdleTimeout struct {
101
+	essentials.Conn
102
+
103
+	timeout time.Duration
104
+}
105
+
106
+func (c connIdleTimeout) Read(b []byte) (int, error) {
107
+	c.Conn.SetReadDeadline(time.Now().Add(c.timeout)) //nolint: errcheck
108
+
109
+	return c.Conn.Read(b) //nolint: wrapcheck
110
+}
111
+
112
+func (c connIdleTimeout) Write(b []byte) (int, error) {
113
+	c.Conn.SetWriteDeadline(time.Now().Add(c.timeout)) //nolint: errcheck
114
+
115
+	return c.Conn.Write(b) //nolint: wrapcheck
116
+}

+ 4
- 2
mtglib/proxy.go Visa fil

@@ -27,6 +27,7 @@ type Proxy struct {
27 27
 
28 28
 	allowFallbackOnUnknownDC    bool
29 29
 	tolerateTimeSkewness        time.Duration
30
+	idleTimeout                 time.Duration
30 31
 	domainFrontingPort          int
31 32
 	domainFrontingIP            string
32 33
 	domainFrontingProxyProtocol bool
@@ -306,8 +307,8 @@ func (p *Proxy) doDomainFronting(ctx *streamContext, conn *connRewind) {
306 307
 	relay.Relay(
307 308
 		ctx,
308 309
 		ctx.logger.Named("domain-fronting"),
309
-		frontConn,
310
-		conn,
310
+		connIdleTimeout{Conn: frontConn, timeout: p.idleTimeout},
311
+		connIdleTimeout{Conn: conn, timeout: p.idleTimeout},
311 312
 	)
312 313
 }
313 314
 
@@ -339,6 +340,7 @@ func NewProxy(opts ProxyOpts) (*Proxy, error) {
339 340
 		domainFrontingPort:       opts.getDomainFrontingPort(),
340 341
 		domainFrontingIP:         opts.DomainFrontingIP,
341 342
 		tolerateTimeSkewness:     opts.getTolerateTimeSkewness(),
343
+		idleTimeout:              opts.getIdleTimeout(),
342 344
 		allowFallbackOnUnknownDC: opts.AllowFallbackOnUnknownDC,
343 345
 		telegram:                 tg,
344 346
 		doppelGanger: doppel.NewGanger(

+ 8
- 0
mtglib/proxy_opts.go Visa fil

@@ -216,6 +216,14 @@ func (p ProxyOpts) getPreferIP() string {
216 216
 	return p.PreferIP
217 217
 }
218 218
 
219
+func (p ProxyOpts) getIdleTimeout() time.Duration {
220
+	if p.IdleTimeout == 0 {
221
+		return DefaultIdleTimeout
222
+	}
223
+
224
+	return p.IdleTimeout
225
+}
226
+
219 227
 func (p ProxyOpts) getLogger(name string) Logger {
220 228
 	return p.Logger.Named(name)
221 229
 }

Laddar…
Avbryt
Spara