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
}