Add randomized clientHello generation in UTLSIdToSpec.

This commit is contained in:
f.gruzdev 2023-01-30 13:41:10 +03:00
parent d5cdf5dbe1
commit e8f6a8f7ee

View file

@ -1844,6 +1844,9 @@ func utlsIdToSpec(id ClientHelloID) (ClientHelloSpec, error) {
}, },
}, },
}, nil }, nil
case HelloRandomized, HelloRandomizedALPN, HelloRandomizedNoALPN:
// Use empty values as they can be filled later by UConn.ApplyPreset or manually.
return generateRandomizedSpec(id, "", nil, nil)
default: default:
return ClientHelloSpec{}, errors.New("ClientHello ID " + id.Str() + " is unknown") return ClientHelloSpec{}, errors.New("ClientHello ID " + id.Str() + " is unknown")
} }
@ -2072,23 +2075,30 @@ func (uconn *UConn) ApplyPreset(p *ClientHelloSpec) error {
} }
func (uconn *UConn) generateRandomizedSpec() (ClientHelloSpec, error) { func (uconn *UConn) generateRandomizedSpec() (ClientHelloSpec, error) {
return generateRandomizedSpec(uconn.ClientHelloID, uconn.serverName, uconn.HandshakeState.Session, uconn.config.NextProtos)
}
func generateRandomizedSpec(
id ClientHelloID,
serverName string,
session *ClientSessionState,
nextProtos []string,
) (ClientHelloSpec, error) {
p := ClientHelloSpec{} p := ClientHelloSpec{}
if uconn.ClientHelloID.Seed == nil { if id.Seed == nil {
seed, err := NewPRNGSeed() seed, err := NewPRNGSeed()
if err != nil { if err != nil {
return p, err return p, err
} }
uconn.ClientHelloID.Seed = seed id.Seed = seed
} }
r, err := newPRNGWithSeed(uconn.ClientHelloID.Seed) r, err := newPRNGWithSeed(id.Seed)
if err != nil { if err != nil {
return p, err return p, err
} }
id := uconn.ClientHelloID
var WithALPN bool var WithALPN bool
switch id.Client { switch id.Client {
case helloRandomizedALPN: case helloRandomizedALPN:
@ -2132,8 +2142,8 @@ func (uconn *UConn) generateRandomizedSpec() (ClientHelloSpec, error) {
p.CipherSuites = removeRandomCiphers(r, shuffledSuites, 0.4) p.CipherSuites = removeRandomCiphers(r, shuffledSuites, 0.4)
sni := SNIExtension{uconn.config.ServerName} sni := SNIExtension{serverName}
sessionTicket := SessionTicketExtension{Session: uconn.HandshakeState.Session} sessionTicket := SessionTicketExtension{Session: session}
sigAndHashAlgos := []SignatureScheme{ sigAndHashAlgos := []SignatureScheme{
ECDSAWithP256AndSHA256, ECDSAWithP256AndSHA256,
@ -2193,11 +2203,11 @@ func (uconn *UConn) generateRandomizedSpec() (ClientHelloSpec, error) {
} }
if WithALPN { if WithALPN {
if len(uconn.config.NextProtos) == 0 { if len(nextProtos) == 0 {
// if user didn't specify alpn yet, choose something popular // if user didn't specify alpn yet, choose something popular
uconn.config.NextProtos = []string{"h2", "http/1.1"} nextProtos = []string{"h2", "http/1.1"}
} }
alpn := ALPNExtension{AlpnProtocols: uconn.config.NextProtos} alpn := ALPNExtension{AlpnProtocols: nextProtos}
p.Extensions = append(p.Extensions, &alpn) p.Extensions = append(p.Extensions, &alpn)
} }
@ -2245,7 +2255,7 @@ func (uconn *UConn) generateRandomizedSpec() (ClientHelloSpec, error) {
// seed to create a new, independent PRNG, so that a seed used // seed to create a new, independent PRNG, so that a seed used
// with the previous version of generateRandomizedSpec will // with the previous version of generateRandomizedSpec will
// produce the exact same spec as long as ALPS isn't selected. // produce the exact same spec as long as ALPS isn't selected.
r, err := newPRNGWithSaltedSeed(uconn.ClientHelloID.Seed, "ALPS") r, err := newPRNGWithSaltedSeed(id.Seed, "ALPS")
if err != nil { if err != nil {
return p, err return p, err
} }