From 38d3c3cae5a43fe362c286835ab59c4d7347befe Mon Sep 17 00:00:00 2001 From: Chung-Ting Huang Date: Tue, 22 Aug 2023 15:47:33 +0100 Subject: [PATCH] TUN-7707: Use X25519Kyber768Draft00 curve when post-quantum feature is enabled --- cmd/cloudflared/tunnel/configuration.go | 8 ++----- supervisor/pqtunnels.go | 16 ++++++-------- supervisor/supervisor.go | 28 +++++++++++++++++++++++++ supervisor/tunnel.go | 16 +++----------- 4 files changed, 39 insertions(+), 29 deletions(-) diff --git a/cmd/cloudflared/tunnel/configuration.go b/cmd/cloudflared/tunnel/configuration.go index b905bdd8..427ac87f 100644 --- a/cmd/cloudflared/tunnel/configuration.go +++ b/cmd/cloudflared/tunnel/configuration.go @@ -3,7 +3,6 @@ package tunnel import ( "crypto/tls" "fmt" - mathRand "math/rand" "net" "net/netip" "os" @@ -203,12 +202,10 @@ func prepareTunnelConfig( log.Warn().Str("edgeIPVersion", edgeIPVersion.String()).Err(err).Msg("Overriding edge-ip-version") } - var pqKexIdx int if needPQ { - pqKexIdx = mathRand.Intn(len(supervisor.PQKexes)) log.Info().Msgf( - "Using experimental hybrid post-quantum key agreement %s", - supervisor.PQKexNames[supervisor.PQKexes[pqKexIdx]], + "Using hybrid post-quantum key agreement %s", + supervisor.PQKexName, ) } @@ -237,7 +234,6 @@ func prepareTunnelConfig( ProtocolSelector: protocolSelector, EdgeTLSConfigs: edgeTLSConfigs, NeedPQ: needPQ, - PQKexIdx: pqKexIdx, MaxEdgeAddrRetries: uint8(c.Int("max-edge-addr-retries")), UDPUnregisterSessionTimeout: c.Duration(udpUnregisterSessionTimeoutFlag), DisableQUICPathMTUDiscovery: c.Bool(quicDisablePathMTUDiscovery), diff --git a/supervisor/pqtunnels.go b/supervisor/pqtunnels.go index f682828c..67a02e07 100644 --- a/supervisor/pqtunnels.go +++ b/supervisor/pqtunnels.go @@ -12,16 +12,12 @@ import ( // issue creating the tunnel, we'll report the first error // to https://pqtunnels.cloudflareresearch.com. -var ( - PQKexes = [...]tls.CurveID{ - tls.CurveID(0xfe30), // X25519Kyber512Draft00 - tls.CurveID(0xfe31), // X25519Kyber768Draft00 - } - PQKexNames map[tls.CurveID]string = map[tls.CurveID]string{ - tls.CurveID(0xfe30): "X25519Kyber512Draft00", - tls.CurveID(0xfe31): "X25519Kyber768Draft00", - } +const ( + PQKex = tls.CurveID(0xfe31) // X25519Kyber768Draft00 + PQKexName = "X25519Kyber768Draft00" +) +var ( pqtMux sync.Mutex // protects pqtSubmitted and pqtWaitForMessage pqtSubmitted bool // whether an error has already been submitted @@ -70,7 +66,7 @@ func submitPQTunnelError(rep error, config *TunnelConfig) { Message string `json:"m"` Version string `json:"v"` }{ - Group: int(PQKexes[config.PQKexIdx]), + Group: int(PQKex), Message: rep.Error(), Version: config.ReportedVersion, }) diff --git a/supervisor/supervisor.go b/supervisor/supervisor.go index 60e915bf..e1c45a8c 100644 --- a/supervisor/supervisor.go +++ b/supervisor/supervisor.go @@ -2,6 +2,7 @@ package supervisor import ( "context" + "crypto/tls" "errors" "net" "strings" @@ -10,6 +11,8 @@ import ( "github.com/quic-go/quic-go" "github.com/rs/zerolog" + qtls120 "github.com/quic-go/qtls-go1-20" + "github.com/cloudflare/cloudflared/connection" "github.com/cloudflare/cloudflared/edgediscovery" "github.com/cloudflare/cloudflared/orchestration" @@ -78,6 +81,8 @@ func NewSupervisor(config *TunnelConfig, orchestrator *orchestration.Orchestrato reconnectCredentialManager := newReconnectCredentialManager(connection.MetricsNamespace, connection.TunnelSubsystem, config.HAConnections) + registerTLSEventLogger(config.Log) + tracker := tunnelstate.NewConnTracker(config.Log) log := NewConnAwareLogger(config.Log, tracker, config.Observer) @@ -336,3 +341,26 @@ func (s *Supervisor) waitForNextTunnel(index int) bool { func (s *Supervisor) unusedIPs() bool { return s.edgeIPs.AvailableAddrs() > s.config.HAConnections } + +func registerTLSEventLogger(logger *zerolog.Logger) { + qtls120.SetCFEventHandler(func(ev qtls120.CFEvent) { + logger.Debug().Bool("handshake", ev.IsHandshake()).Str("handshake_duration", ev.Duration().String()).Str("curve", tlsCurveName(ev.KEX())).Msg("QUIC TLS event") + }) +} + +func tlsCurveName(curve tls.CurveID) string { + switch curve { + case tls.CurveP256: + return "p256" + case tls.CurveP384: + return "p384" + case tls.CurveP521: + return "p521" + case tls.X25519: + return "X25519" + case PQKex: + return PQKexName + default: + return "unknown" + } +} diff --git a/supervisor/tunnel.go b/supervisor/tunnel.go index 3ba04050..463b7d2b 100644 --- a/supervisor/tunnel.go +++ b/supervisor/tunnel.go @@ -61,9 +61,6 @@ type TunnelConfig struct { NeedPQ bool - // Index into PQKexes of post-quantum kex to use if NeedPQ is set. - PQKexIdx int - NamedTunnel *connection.NamedTunnelProperties ProtocolSelector connection.ProtocolSelector EdgeTLSConfigs map[connection.Protocol]*tls.Config @@ -585,16 +582,9 @@ func (e *EdgeTunnelServer) serveQUIC( if e.config.NeedPQ { // If the user passes the -post-quantum flag, we override // CurvePreferences to only support hybrid post-quantum key agreements. - cs := make([]tls.CurveID, len(PQKexes)) - copy(cs, PQKexes[:]) - - // It is unclear whether Kyber512 or Kyber768 will become the standard. - // Kyber768 is a bit bigger (and doesn't fit in one initial - // datagram anymore). We're enabling both, but pick randomly which - // one to put first. (TLS will use the first one in the list - // and allows a fallback to the second.) - cs[0], cs[e.config.PQKexIdx] = cs[e.config.PQKexIdx], cs[0] - tlsConfig.CurvePreferences = cs + tlsConfig.CurvePreferences = []tls.CurveID{ + PQKex, + } } quicConfig := &quic.Config{