mirror of
https://github.com/caddyserver/caddy.git
synced 2026-05-13 09:06:41 +00:00
core: propagate ECH keys to the QUIC listener (#7670)
This commit is contained in:
parent
441d5eb062
commit
41aee97386
2 changed files with 72 additions and 1 deletions
15
listeners.go
15
listeners.go
|
|
@ -462,7 +462,10 @@ func (na NetworkAddress) ListenQUIC(ctx context.Context, portOffset uint, config
|
|||
sqs := newSharedQUICState(tlsConf)
|
||||
// http3.ConfigureTLSConfig only uses this field and tls App sets this field as well
|
||||
//nolint:gosec
|
||||
quicTlsConfig := &tls.Config{GetConfigForClient: sqs.getConfigForClient}
|
||||
quicTlsConfig := &tls.Config{
|
||||
GetConfigForClient: sqs.getConfigForClient,
|
||||
GetEncryptedClientHelloKeys: sqs.getEncryptedClientHelloKeys,
|
||||
}
|
||||
// Require clients to verify their source address when we're handling more than 1000 handshakes per second.
|
||||
// TODO: make tunable?
|
||||
limiter := rate.NewLimiter(1000, 1000)
|
||||
|
|
@ -540,6 +543,16 @@ func (sqs *sharedQUICState) getConfigForClient(ch *tls.ClientHelloInfo) (*tls.Co
|
|||
return sqs.activeTlsConf.GetConfigForClient(ch)
|
||||
}
|
||||
|
||||
// getEncryptedClientHelloKeys is used as tls.Config's GetEncryptedClientHelloKeys field.
|
||||
func (sqs *sharedQUICState) getEncryptedClientHelloKeys(ch *tls.ClientHelloInfo) ([]tls.EncryptedClientHelloKey, error) {
|
||||
sqs.rmu.RLock()
|
||||
defer sqs.rmu.RUnlock()
|
||||
if sqs.activeTlsConf.GetEncryptedClientHelloKeys == nil {
|
||||
return nil, nil
|
||||
}
|
||||
return sqs.activeTlsConf.GetEncryptedClientHelloKeys(ch)
|
||||
}
|
||||
|
||||
// addState adds tls.Config and activeRequests to the map if not present and returns the corresponding context and its cancelFunc
|
||||
// so that when cancelled, the active tls.Config will change
|
||||
func (sqs *sharedQUICState) addState(tlsConfig *tls.Config) (context.Context, context.CancelCauseFunc) {
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
package caddy
|
||||
|
||||
import (
|
||||
"crypto/tls"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
|
|
@ -175,6 +176,63 @@ func TestJoinNetworkAddress(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestSharedQUICStateGetEncryptedClientHelloKeys(t *testing.T) {
|
||||
hello := &tls.ClientHelloInfo{ServerName: "example.com"}
|
||||
initialKeys := []tls.EncryptedClientHelloKey{{Config: []byte("initial"), PrivateKey: []byte("initial-key")}}
|
||||
updatedKeys := []tls.EncryptedClientHelloKey{{Config: []byte("updated"), PrivateKey: []byte("updated-key")}}
|
||||
|
||||
initialConfig := &tls.Config{
|
||||
GetConfigForClient: func(*tls.ClientHelloInfo) (*tls.Config, error) {
|
||||
return nil, nil
|
||||
},
|
||||
GetEncryptedClientHelloKeys: func(*tls.ClientHelloInfo) ([]tls.EncryptedClientHelloKey, error) {
|
||||
return initialKeys, nil
|
||||
},
|
||||
}
|
||||
|
||||
sqs := newSharedQUICState(initialConfig)
|
||||
|
||||
keys, err := sqs.getEncryptedClientHelloKeys(hello)
|
||||
if err != nil {
|
||||
t.Fatalf("getting initial ECH keys: %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(keys, initialKeys) {
|
||||
t.Fatalf("unexpected initial ECH keys: got %#v, want %#v", keys, initialKeys)
|
||||
}
|
||||
|
||||
updatedConfig := &tls.Config{
|
||||
GetConfigForClient: func(*tls.ClientHelloInfo) (*tls.Config, error) {
|
||||
return nil, nil
|
||||
},
|
||||
GetEncryptedClientHelloKeys: func(*tls.ClientHelloInfo) ([]tls.EncryptedClientHelloKey, error) {
|
||||
return updatedKeys, nil
|
||||
},
|
||||
}
|
||||
|
||||
_, cancel := sqs.addState(updatedConfig)
|
||||
sqs.rmu.Lock()
|
||||
sqs.activeTlsConf = updatedConfig
|
||||
sqs.rmu.Unlock()
|
||||
|
||||
keys, err = sqs.getEncryptedClientHelloKeys(hello)
|
||||
if err != nil {
|
||||
t.Fatalf("getting updated ECH keys: %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(keys, updatedKeys) {
|
||||
t.Fatalf("unexpected updated ECH keys: got %#v, want %#v", keys, updatedKeys)
|
||||
}
|
||||
|
||||
cancel(nil)
|
||||
|
||||
keys, err = sqs.getEncryptedClientHelloKeys(hello)
|
||||
if err != nil {
|
||||
t.Fatalf("getting restored ECH keys: %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(keys, initialKeys) {
|
||||
t.Fatalf("unexpected restored ECH keys: got %#v, want %#v", keys, initialKeys)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseNetworkAddress(t *testing.T) {
|
||||
for i, tc := range []struct {
|
||||
input string
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue