mirror of
https://github.com/caddyserver/caddy.git
synced 2026-04-23 17:39:33 -04:00
core: propagate ECH keys to the QUIC listener (#7670)
Some checks failed
Tests / test (./cmd/caddy/caddy, ~1.26.0, macos-14, 0, 1.26, mac) (push) Waiting to run
Tests / test (./cmd/caddy/caddy.exe, ~1.26.0, windows-latest, True, 1.26, windows) (push) Waiting to run
Lint / lint (macos-14, mac) (push) Waiting to run
Lint / lint (windows-latest, windows) (push) Waiting to run
Tests / test (./cmd/caddy/caddy, ~1.26.0, ubuntu-latest, 0, 1.26, linux) (push) Failing after 1m19s
Tests / test (s390x on IBM Z) (push) Has been skipped
Tests / goreleaser-check (push) Has been skipped
Cross-Build / build (~1.26.0, 1.26, aix) (push) Successful in 1m27s
Cross-Build / build (~1.26.0, 1.26, darwin) (push) Successful in 1m25s
Cross-Build / build (~1.26.0, 1.26, dragonfly) (push) Successful in 1m26s
Cross-Build / build (~1.26.0, 1.26, freebsd) (push) Successful in 1m23s
Cross-Build / build (~1.26.0, 1.26, illumos) (push) Successful in 1m25s
Cross-Build / build (~1.26.0, 1.26, linux) (push) Successful in 1m22s
Cross-Build / build (~1.26.0, 1.26, netbsd) (push) Successful in 1m23s
Cross-Build / build (~1.26.0, 1.26, openbsd) (push) Successful in 1m22s
Cross-Build / build (~1.26.0, 1.26, solaris) (push) Successful in 1m24s
Cross-Build / build (~1.26.0, 1.26, windows) (push) Successful in 1m34s
Lint / lint (ubuntu-latest, linux) (push) Successful in 2m2s
Lint / govulncheck (push) Successful in 1m20s
Lint / dependency-review (push) Failing after 22s
OpenSSF Scorecard supply-chain security / Scorecard analysis (push) Failing after 24s
Some checks failed
Tests / test (./cmd/caddy/caddy, ~1.26.0, macos-14, 0, 1.26, mac) (push) Waiting to run
Tests / test (./cmd/caddy/caddy.exe, ~1.26.0, windows-latest, True, 1.26, windows) (push) Waiting to run
Lint / lint (macos-14, mac) (push) Waiting to run
Lint / lint (windows-latest, windows) (push) Waiting to run
Tests / test (./cmd/caddy/caddy, ~1.26.0, ubuntu-latest, 0, 1.26, linux) (push) Failing after 1m19s
Tests / test (s390x on IBM Z) (push) Has been skipped
Tests / goreleaser-check (push) Has been skipped
Cross-Build / build (~1.26.0, 1.26, aix) (push) Successful in 1m27s
Cross-Build / build (~1.26.0, 1.26, darwin) (push) Successful in 1m25s
Cross-Build / build (~1.26.0, 1.26, dragonfly) (push) Successful in 1m26s
Cross-Build / build (~1.26.0, 1.26, freebsd) (push) Successful in 1m23s
Cross-Build / build (~1.26.0, 1.26, illumos) (push) Successful in 1m25s
Cross-Build / build (~1.26.0, 1.26, linux) (push) Successful in 1m22s
Cross-Build / build (~1.26.0, 1.26, netbsd) (push) Successful in 1m23s
Cross-Build / build (~1.26.0, 1.26, openbsd) (push) Successful in 1m22s
Cross-Build / build (~1.26.0, 1.26, solaris) (push) Successful in 1m24s
Cross-Build / build (~1.26.0, 1.26, windows) (push) Successful in 1m34s
Lint / lint (ubuntu-latest, linux) (push) Successful in 2m2s
Lint / govulncheck (push) Successful in 1m20s
Lint / dependency-review (push) Failing after 22s
OpenSSF Scorecard supply-chain security / Scorecard analysis (push) Failing after 24s
This commit is contained in:
parent
441d5eb062
commit
41aee97386
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…
x
Reference in New Issue
Block a user