diff --git a/config.go b/config.go index dea118b3..49b9fc3f 100644 --- a/config.go +++ b/config.go @@ -53,9 +53,6 @@ func validateConfig(config *Config) error { // it may be called with nil func populateServerConfig(config *Config) *Config { config = populateConfig(config) - if config.MaxTokenAge == 0 { - config.MaxTokenAge = protocol.TokenValidity - } if config.RequireAddressValidation == nil { config.RequireAddressValidation = func(net.Addr) bool { return false } } @@ -114,7 +111,6 @@ func populateConfig(config *Config) *Config { Versions: versions, HandshakeIdleTimeout: handshakeIdleTimeout, MaxIdleTimeout: idleTimeout, - MaxTokenAge: config.MaxTokenAge, RequireAddressValidation: config.RequireAddressValidation, KeepAlivePeriod: config.KeepAlivePeriod, InitialStreamReceiveWindow: initialStreamReceiveWindow, diff --git a/config_test.go b/config_test.go index c5701608..e40c1cfc 100644 --- a/config_test.go +++ b/config_test.go @@ -78,8 +78,6 @@ var _ = Describe("Config", func() { f.Set(reflect.ValueOf(time.Second)) case "MaxIdleTimeout": f.Set(reflect.ValueOf(time.Hour)) - case "MaxTokenAge": - f.Set(reflect.ValueOf(2 * time.Hour)) case "TokenStore": f.Set(reflect.ValueOf(NewLRUTokenStore(2, 3))) case "InitialStreamReceiveWindow": diff --git a/interface.go b/interface.go index c7e53bdc..6eac385d 100644 --- a/interface.go +++ b/interface.go @@ -268,10 +268,6 @@ type Config struct { // See https://datatracker.ietf.org/doc/html/rfc9000#section-8 for details. // If not set, every client is forced to prove its remote address. RequireAddressValidation func(net.Addr) bool - // MaxTokenAge is the maximum age of the token presented during the handshake, - // for tokens that were issued on a previous connection. - // If not set, it defaults to 24 hours. Only valid for a server. - MaxTokenAge time.Duration // The TokenStore stores tokens received from the server. // Tokens are used to skip address validation on future connection attempts. // The key used to store tokens is the ServerName from the tls.Config, if set diff --git a/internal/handshake/token_protector.go b/internal/handshake/token_protector.go index 6dcf7f77..f3a99e41 100644 --- a/internal/handshake/token_protector.go +++ b/internal/handshake/token_protector.go @@ -61,7 +61,7 @@ func (s *tokenProtectorImpl) DecodeToken(p []byte) ([]byte, error) { } func (s *tokenProtectorImpl) createAEAD(nonce []byte) (cipher.AEAD, []byte, error) { - h := hkdf.New(sha256.New, s.key[:], nonce[:], []byte("quic-go token source")) + h := hkdf.New(sha256.New, s.key[:], nonce, []byte("quic-go token source")) key := make([]byte, 32) // use a 32 byte key, in order to select AES-256 if _, err := io.ReadFull(h, key); err != nil { return nil, nil, err diff --git a/server.go b/server.go index ebfb6afe..119289b3 100644 --- a/server.go +++ b/server.go @@ -67,6 +67,7 @@ type baseServer struct { conn rawConn tokenGenerator *handshake.TokenGenerator + maxTokenAge time.Duration connIDGenerator ConnectionIDGenerator connHandler packetHandlerManager @@ -227,6 +228,7 @@ func newServer( tracer *logging.Tracer, onClose func(), tokenGeneratorKey TokenGeneratorKey, + maxTokenAge time.Duration, disableVersionNegotiation bool, acceptEarly bool, ) *baseServer { @@ -235,6 +237,7 @@ func newServer( tlsConf: tlsConf, config: config, tokenGenerator: handshake.NewTokenGenerator(tokenGeneratorKey), + maxTokenAge: maxTokenAge, connIDGenerator: connIDGenerator, connHandler: connHandler, connQueue: make(chan quicConn), @@ -524,7 +527,7 @@ func (s *baseServer) validateToken(token *handshake.Token, addr net.Addr) bool { if !token.ValidateRemoteAddr(addr) { return false } - if !token.IsRetryToken && time.Since(token.SentTime) > s.config.MaxTokenAge { + if !token.IsRetryToken && time.Since(token.SentTime) > s.maxTokenAge { return false } if token.IsRetryToken && time.Since(token.SentTime) > s.config.maxRetryTokenAge() { diff --git a/server_test.go b/server_test.go index 71c968bd..6e50de82 100644 --- a/server_test.go +++ b/server_test.go @@ -901,7 +901,7 @@ var _ = Describe("Server", func() { It("sends an INVALID_TOKEN error, if an expired non-retry token is received", func() { serv.config.RequireAddressValidation = func(net.Addr) bool { return true } - serv.config.MaxTokenAge = time.Millisecond + serv.maxTokenAge = time.Millisecond raddr := &net.UDPAddr{IP: net.IPv4(127, 0, 0, 1), Port: 1337} token, err := serv.tokenGenerator.NewToken(raddr) Expect(err).ToNot(HaveOccurred()) diff --git a/transport.go b/transport.go index 0119d629..14d6b1fd 100644 --- a/transport.go +++ b/transport.go @@ -63,6 +63,13 @@ type Transport struct { // see section 8.1.3 of RFC 9000 for details. TokenGeneratorKey *TokenGeneratorKey + // MaxTokenAge is the maximum age of the resumption token presented during the handshake. + // These tokens allow skipping address resumption when resuming a QUIC connection, + // and are especially useful when using 0-RTT. + // If not set, it defaults to 24 hours. + // See section 8.1.3 of RFC 9000 for details. + MaxTokenAge time.Duration + // DisableVersionNegotiationPackets disables the sending of Version Negotiation packets. // This can be useful if version information is exchanged out-of-band. // It has no effect for clients. @@ -151,6 +158,7 @@ func (t *Transport) createServer(tlsConf *tls.Config, conf *Config, allow0RTT bo t.Tracer, t.closeServer, *t.TokenGeneratorKey, + t.MaxTokenAge, t.DisableVersionNegotiationPackets, allow0RTT, )