From 5ea06d05b18da841727760b166399a3580ed2e13 Mon Sep 17 00:00:00 2001 From: Ox Cart Date: Wed, 23 Aug 2023 11:29:17 -0500 Subject: [PATCH] When dialing a proxy that requires session tickets, skip client hellos that don't support session tickets --- chained/common.go | 1 + chained/hello_roller.go | 18 ++++++++++++++++++ chained/https_impl.go | 15 +++++++++++++++ 3 files changed, 34 insertions(+) diff --git a/chained/common.go b/chained/common.go index 74ded6a40b..22ea3e5ecb 100644 --- a/chained/common.go +++ b/chained/common.go @@ -188,6 +188,7 @@ var availableClientHelloIDs = map[string]tls.ClientHelloID{ "HelloChrome_58": tls.HelloChrome_58, "HelloChrome_62": tls.HelloChrome_62, "HelloChrome_102": tls.HelloChrome_102, + "HelloChrome_106": tls.HelloChrome_106_Shuffle, "HelloEdge_Auto": tls.HelloEdge_Auto, "Hello360_Auto": tls.Hello360_Auto, "HelloQQ_Auto": tls.HelloQQ_Auto, diff --git a/chained/hello_roller.go b/chained/hello_roller.go index 82f7392a9a..a95cf46b71 100644 --- a/chained/hello_roller.go +++ b/chained/hello_roller.go @@ -65,6 +65,24 @@ func (hs helloSpec) uconn(transport net.Conn, cfg *tls.Config) (*tls.UConn, erro return uconn, nil } +func (hs helloSpec) supportsSessionTickets(spec *tls.ClientHelloSpec) (bool, error) { + if spec == nil { + // this can happen if we're not using a custom spec + _spec, err := tls.UTLSIdToSpec(hs.id) + if err != nil { + return false, errors.New("failed to get spec for hello %v: %v", hs.id, err) + } + spec = &_spec + } + for _, extension := range spec.Extensions { + _, isSessionTicket := extension.(*tls.SessionTicketExtension) + if isSessionTicket { + return true, nil + } + } + return false, nil +} + type helloRoller struct { hellos []helloSpec index, advances int diff --git a/chained/https_impl.go b/chained/https_impl.go index dbe6a5ec8e..5e29bfbdf4 100644 --- a/chained/https_impl.go +++ b/chained/https_impl.go @@ -23,6 +23,7 @@ type httpsImpl struct { tlsConfig *tls.Config roller *helloRoller tlsClientHelloSplitting bool + requiresSessionTickets bool sync.Mutex } @@ -45,6 +46,7 @@ func newHTTPSImpl(configDir, name, addr string, pc *config.ProxyConfig, uc commo tlsConfig: tlsConfig, roller: &helloRoller{hellos: hellos}, tlsClientHelloSplitting: pc.TLSClientHelloSplitting, + requiresSessionTickets: pc.TLSClientSessionState != "", }, nil } @@ -59,6 +61,19 @@ func (impl *httpsImpl) dialServer(op *ops.Op, ctx context.Context) (net.Conn, er r.advance() return nil, errors.New("failed to generate valid utls hello spec: %v", err) } + + if impl.requiresSessionTickets && helloID != tls.HelloGolang { + supportsSessionTickets, err := currentHello.supportsSessionTickets(helloSpec) + if err != nil { + r.advance() + return nil, err + } + if !supportsSessionTickets { + r.advance() + return nil, errors.New("session ticket is required, but hello %v does not support them; advancing roller", helloID) + } + } + d := tlsdialer.Dialer{ DoDial: func(network, addr string, timeout time.Duration) (net.Conn, error) { tcpConn, err := impl.dialCore(op, ctx, impl.addr)