@marcel91200 / caddy Mirror · read-only / commits / d64c7e67
Fork 0

Fast and extensible multi-platform HTTP/1-2-3 web server with automatic HTTPS

Mirrored from https://github.com/Slazee/caddy.git

Synced Nov 11, 16:00 UTC

caddyhttp: Option to disable 0-RTT (#7485)

Francis Lavoie committed Feb 16, 2026 at 12:20 UTC d64c7e67a4c6453bcdb3519f1a64e198a286ad9c
4 files changed +35 -4
caddyconfig/httpcaddyfile/serveroptions.go
+15
@@ -57,6 +57,9 @@ type serverOptions struct {
57 ShouldLogCredentials bool
58 Metrics *caddyhttp.Metrics
59 Trace bool // TODO: EXPERIMENTAL
60 + // If set, overrides whether QUIC listeners allow 0-RTT (early data).
61 + // If nil, the default behavior is used (currently allowed).
62 + Allow0RTT *bool
63 }
64
65 func unmarshalCaddyfileServerOptions(d *caddyfile.Dispenser) (any, error) {
@@ -309,6 +312,17 @@ func unmarshalCaddyfileServerOptions(d *caddyfile.Dispenser) (any, error) {
312 }
313 serverOpts.Trace = true
314
315 + case "0rtt":
316 + // only supports "off" for now
317 + if !d.NextArg() {
318 + return nil, d.ArgErr()
319 + }
320 + if d.Val() != "off" {
321 + return nil, d.Errf("unsupported 0rtt argument '%s' (only 'off' is supported)", d.Val())
322 + }
323 + boolVal := false
324 + serverOpts.Allow0RTT = &boolVal
325 +
326 default:
327 return nil, d.Errf("unrecognized servers option '%s'", d.Val())
328 }
@@ -373,6 +387,7 @@ func applyServerOptions(
387 server.TrustedProxiesStrict = opts.TrustedProxiesStrict
388 server.TrustedProxiesUnix = opts.TrustedProxiesUnix
389 server.Metrics = opts.Metrics
390 + server.Allow0RTT = opts.Allow0RTT
391 if opts.ShouldLogCredentials {
392 if server.Logs == nil {
393 server.Logs = new(caddyhttp.ServerLogConfig)
caddytest/integration/caddyfile_adapt/global_server_options_single.caddyfiletest
+3 -1
@@ -21,6 +21,7 @@
21 keepalive_interval 20s
22 keepalive_idle 20s
23 keepalive_count 10
24 + 0rtt off
25 }
26 }
27
@@ -90,7 +91,8 @@ foo.com {
91 "h2",
92 "h2c",
93 "h3"
93 - ]
94 + ],
95 + "allow_0rtt": false
96 }
97 }
98 }
listeners.go
+6 -2
@@ -511,7 +511,7 @@ func JoinNetworkAddress(network, host, port string) string {
511 //
512 // NOTE: This API is EXPERIMENTAL and may be changed or removed.
513 // NOTE: user should close the returned listener twice, once to stop accepting new connections, the second time to free up the packet conn.
514 -func (na NetworkAddress) ListenQUIC(ctx context.Context, portOffset uint, config net.ListenConfig, tlsConf *tls.Config, pcWrappers []PacketConnWrapper) (http3.QUICListener, error) {
514 +func (na NetworkAddress) ListenQUIC(ctx context.Context, portOffset uint, config net.ListenConfig, tlsConf *tls.Config, pcWrappers []PacketConnWrapper, allow0rttconf *bool) (http3.QUICListener, error) {
515 lnKey := listenerKey("quic"+na.Network, na.JoinHostPort(portOffset))
516
517 sharedEarlyListener, _, err := listenerPool.LoadOrNew(lnKey, func() (Destructor, error) {
@@ -550,10 +550,14 @@ func (na NetworkAddress) ListenQUIC(ctx context.Context, portOffset uint, config
550 Conn: h3ln,
551 VerifySourceAddress: func(addr net.Addr) bool { return !limiter.Allow() },
552 }
553 + allow0rtt := true
554 + if allow0rttconf != nil {
555 + allow0rtt = *allow0rttconf
556 + }
557 earlyLn, err := tr.ListenEarly(
558 http3.ConfigureTLSConfig(quicTlsConfig),
559 &quic.Config{
556 - Allow0RTT: true,
560 + Allow0RTT: allow0rtt,
561 Tracer: h3qlog.DefaultConnectionTracer,
562 },
563 )
modules/caddyhttp/server.go
+11 -1
@@ -253,6 +253,16 @@ type Server struct {
253 // A nil value or element indicates that Protocols will be used instead.
254 ListenProtocols [][]string `json:"listen_protocols,omitempty"`
255
256 + // If set, overrides whether QUIC listeners allow 0-RTT (early data).
257 + // If nil, the default behavior is used (currently allowed).
258 + //
259 + // One reason to disable 0-RTT is if a remote IP matcher is used,
260 + // which introduces a dependency on the remote address being verified
261 + // if routing happens before the TLS handshake completes. An HTTP 425
262 + // response is written in that case, but some clients misbehave and
263 + // don't perform a retry, so disabling 0-RTT can smooth it out.
264 + Allow0RTT *bool `json:"allow_0rtt,omitempty"`
265 +
266 // If set, metrics observations will be enabled.
267 // This setting is EXPERIMENTAL and subject to change.
268 // DEPRECATED: Use the app-level `metrics` field.
@@ -650,7 +660,7 @@ func (s *Server) serveHTTP3(addr caddy.NetworkAddress, tlsCfg *tls.Config) error
660 return fmt.Errorf("starting HTTP/3 QUIC listener: %v", err)
661 }
662 addr.Network = h3net
653 - h3ln, err := addr.ListenQUIC(s.ctx, 0, net.ListenConfig{}, tlsCfg, s.packetConnWrappers)
663 + h3ln, err := addr.ListenQUIC(s.ctx, 0, net.ListenConfig{}, tlsCfg, s.packetConnWrappers, s.Allow0RTT)
664 if err != nil {
665 return fmt.Errorf("starting HTTP/3 QUIC listener: %v", err)
666 }