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

This commit is contained in:
Francis Lavoie 2026-02-16 12:20:47 -05:00 committed by GitHub
parent ff4f79aebe
commit d64c7e67a4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 35 additions and 4 deletions

View File

@ -57,6 +57,9 @@ type serverOptions struct {
ShouldLogCredentials bool
Metrics *caddyhttp.Metrics
Trace bool // TODO: EXPERIMENTAL
// If set, overrides whether QUIC listeners allow 0-RTT (early data).
// If nil, the default behavior is used (currently allowed).
Allow0RTT *bool
}
func unmarshalCaddyfileServerOptions(d *caddyfile.Dispenser) (any, error) {
@ -309,6 +312,17 @@ func unmarshalCaddyfileServerOptions(d *caddyfile.Dispenser) (any, error) {
}
serverOpts.Trace = true
case "0rtt":
// only supports "off" for now
if !d.NextArg() {
return nil, d.ArgErr()
}
if d.Val() != "off" {
return nil, d.Errf("unsupported 0rtt argument '%s' (only 'off' is supported)", d.Val())
}
boolVal := false
serverOpts.Allow0RTT = &boolVal
default:
return nil, d.Errf("unrecognized servers option '%s'", d.Val())
}
@ -373,6 +387,7 @@ func applyServerOptions(
server.TrustedProxiesStrict = opts.TrustedProxiesStrict
server.TrustedProxiesUnix = opts.TrustedProxiesUnix
server.Metrics = opts.Metrics
server.Allow0RTT = opts.Allow0RTT
if opts.ShouldLogCredentials {
if server.Logs == nil {
server.Logs = new(caddyhttp.ServerLogConfig)

View File

@ -21,6 +21,7 @@
keepalive_interval 20s
keepalive_idle 20s
keepalive_count 10
0rtt off
}
}
@ -90,7 +91,8 @@ foo.com {
"h2",
"h2c",
"h3"
]
],
"allow_0rtt": false
}
}
}

View File

@ -511,7 +511,7 @@ func JoinNetworkAddress(network, host, port string) string {
//
// NOTE: This API is EXPERIMENTAL and may be changed or removed.
// NOTE: user should close the returned listener twice, once to stop accepting new connections, the second time to free up the packet conn.
func (na NetworkAddress) ListenQUIC(ctx context.Context, portOffset uint, config net.ListenConfig, tlsConf *tls.Config, pcWrappers []PacketConnWrapper) (http3.QUICListener, error) {
func (na NetworkAddress) ListenQUIC(ctx context.Context, portOffset uint, config net.ListenConfig, tlsConf *tls.Config, pcWrappers []PacketConnWrapper, allow0rttconf *bool) (http3.QUICListener, error) {
lnKey := listenerKey("quic"+na.Network, na.JoinHostPort(portOffset))
sharedEarlyListener, _, err := listenerPool.LoadOrNew(lnKey, func() (Destructor, error) {
@ -550,10 +550,14 @@ func (na NetworkAddress) ListenQUIC(ctx context.Context, portOffset uint, config
Conn: h3ln,
VerifySourceAddress: func(addr net.Addr) bool { return !limiter.Allow() },
}
allow0rtt := true
if allow0rttconf != nil {
allow0rtt = *allow0rttconf
}
earlyLn, err := tr.ListenEarly(
http3.ConfigureTLSConfig(quicTlsConfig),
&quic.Config{
Allow0RTT: true,
Allow0RTT: allow0rtt,
Tracer: h3qlog.DefaultConnectionTracer,
},
)

View File

@ -253,6 +253,16 @@ type Server struct {
// A nil value or element indicates that Protocols will be used instead.
ListenProtocols [][]string `json:"listen_protocols,omitempty"`
// If set, overrides whether QUIC listeners allow 0-RTT (early data).
// If nil, the default behavior is used (currently allowed).
//
// One reason to disable 0-RTT is if a remote IP matcher is used,
// which introduces a dependency on the remote address being verified
// if routing happens before the TLS handshake completes. An HTTP 425
// response is written in that case, but some clients misbehave and
// don't perform a retry, so disabling 0-RTT can smooth it out.
Allow0RTT *bool `json:"allow_0rtt,omitempty"`
// If set, metrics observations will be enabled.
// This setting is EXPERIMENTAL and subject to change.
// DEPRECATED: Use the app-level `metrics` field.
@ -650,7 +660,7 @@ func (s *Server) serveHTTP3(addr caddy.NetworkAddress, tlsCfg *tls.Config) error
return fmt.Errorf("starting HTTP/3 QUIC listener: %v", err)
}
addr.Network = h3net
h3ln, err := addr.ListenQUIC(s.ctx, 0, net.ListenConfig{}, tlsCfg, s.packetConnWrappers)
h3ln, err := addr.ListenQUIC(s.ctx, 0, net.ListenConfig{}, tlsCfg, s.packetConnWrappers, s.Allow0RTT)
if err != nil {
return fmt.Errorf("starting HTTP/3 QUIC listener: %v", err)
}