mirror of
https://github.com/coredns/coredns.git
synced 2025-10-27 08:14:18 -04:00
feat: limit concurrent DoQ streams and goroutines (#7296)
This commit is contained in:
@@ -58,6 +58,14 @@ type Config struct {
|
||||
// TLSConfig when listening for encrypted connections (gRPC, DNS-over-TLS).
|
||||
TLSConfig *tls.Config
|
||||
|
||||
// MaxQUICStreams defines the maximum number of concurrent QUIC streams for a QUIC server.
|
||||
// This is nil if not specified, allowing for a default to be used.
|
||||
MaxQUICStreams *int
|
||||
|
||||
// MaxQUICWorkerPoolSize defines the size of the worker pool for processing QUIC streams.
|
||||
// This is nil if not specified, allowing for a default to be used.
|
||||
MaxQUICWorkerPoolSize *int
|
||||
|
||||
// Timeouts for TCP, TLS and HTTPS servers.
|
||||
ReadTimeout time.Duration
|
||||
WriteTimeout time.Duration
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"math"
|
||||
"net"
|
||||
|
||||
"github.com/coredns/coredns/plugin/metrics/vars"
|
||||
@@ -32,15 +31,26 @@ const (
|
||||
// DoQCodeProtocolError signals that the DoQ implementation encountered
|
||||
// a protocol error and is forcibly aborting the connection.
|
||||
DoQCodeProtocolError quic.ApplicationErrorCode = 2
|
||||
|
||||
// DefaultMaxQUICStreams is the default maximum number of concurrent QUIC streams
|
||||
// on a per-connection basis. RFC 9250 (DNS-over-QUIC) does not require a high
|
||||
// concurrent-stream limit; normal stub or recursive resolvers open only a handful
|
||||
// of streams in parallel. This default (256) is a safe upper bound.
|
||||
DefaultMaxQUICStreams = 256
|
||||
|
||||
// DefaultQUICStreamWorkers is the default number of workers for processing QUIC streams.
|
||||
DefaultQUICStreamWorkers = 1024
|
||||
)
|
||||
|
||||
// ServerQUIC represents an instance of a DNS-over-QUIC server.
|
||||
type ServerQUIC struct {
|
||||
*Server
|
||||
listenAddr net.Addr
|
||||
tlsConfig *tls.Config
|
||||
quicConfig *quic.Config
|
||||
quicListener *quic.Listener
|
||||
listenAddr net.Addr
|
||||
tlsConfig *tls.Config
|
||||
quicConfig *quic.Config
|
||||
quicListener *quic.Listener
|
||||
maxStreams int
|
||||
streamProcessPool chan struct{}
|
||||
}
|
||||
|
||||
// NewServerQUIC returns a new CoreDNS QUIC server and compiles all plugin in to it.
|
||||
@@ -63,15 +73,31 @@ func NewServerQUIC(addr string, group []*Config) (*ServerQUIC, error) {
|
||||
tlsConfig.NextProtos = []string{"doq"}
|
||||
}
|
||||
|
||||
maxStreams := DefaultMaxQUICStreams
|
||||
if len(group) > 0 && group[0] != nil && group[0].MaxQUICStreams != nil {
|
||||
maxStreams = *group[0].MaxQUICStreams
|
||||
}
|
||||
|
||||
streamProcessPoolSize := DefaultQUICStreamWorkers
|
||||
if len(group) > 0 && group[0] != nil && group[0].MaxQUICWorkerPoolSize != nil {
|
||||
streamProcessPoolSize = *group[0].MaxQUICWorkerPoolSize
|
||||
}
|
||||
|
||||
var quicConfig = &quic.Config{
|
||||
MaxIdleTimeout: s.idleTimeout,
|
||||
MaxIncomingStreams: math.MaxUint16,
|
||||
MaxIncomingUniStreams: math.MaxUint16,
|
||||
MaxIncomingStreams: int64(maxStreams),
|
||||
MaxIncomingUniStreams: int64(maxStreams),
|
||||
// Enable 0-RTT by default for all connections on the server-side.
|
||||
Allow0RTT: true,
|
||||
}
|
||||
|
||||
return &ServerQUIC{Server: s, tlsConfig: tlsConfig, quicConfig: quicConfig}, nil
|
||||
return &ServerQUIC{
|
||||
Server: s,
|
||||
tlsConfig: tlsConfig,
|
||||
quicConfig: quicConfig,
|
||||
maxStreams: maxStreams,
|
||||
streamProcessPool: make(chan struct{}, streamProcessPoolSize),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// ServePacket implements caddy.UDPServer interface.
|
||||
@@ -119,7 +145,12 @@ func (s *ServerQUIC) serveQUICConnection(conn quic.Connection) {
|
||||
return
|
||||
}
|
||||
|
||||
go s.serveQUICStream(stream, conn)
|
||||
// Use a bounded worker pool
|
||||
s.streamProcessPool <- struct{}{} // Acquire a worker slot, may block
|
||||
go func(st quic.Stream, cn quic.Connection) {
|
||||
defer func() { <-s.streamProcessPool }() // Release worker slot
|
||||
s.serveQUICStream(st, cn)
|
||||
}(stream, conn)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ var Directives = []string{
|
||||
"geoip",
|
||||
"cancel",
|
||||
"tls",
|
||||
"quic",
|
||||
"timeouts",
|
||||
"multisocket",
|
||||
"reload",
|
||||
|
||||
Reference in New Issue
Block a user