@@ -4,9 +4,12 @@ import (
44 "crypto/tls"
55 "crypto/x509"
66 "fmt"
7+ "net"
78 "net/url"
89 "os"
910 "strings"
11+
12+ utls "github.com/refraction-networking/utls"
1013)
1114
1215func ExpectPeerName (name string , roots * x509.CertPool ) func (cs tls.ConnectionState ) error {
@@ -222,3 +225,186 @@ func TLSConfigFromURL(u *url.URL) (*tls.Config, error) {
222225 }
223226 return tlsConfig , nil
224227}
228+
229+ func TLSFactoryFromURL (u * url.URL ) (func (c net.Conn , config * tls.Config ) net.Conn , error ) {
230+ params , err := url .ParseQuery (u .RawQuery )
231+ if err != nil {
232+ return nil , fmt .Errorf ("unable to parse query string of proxy specification URL %q: %w" , u .String (), err )
233+ }
234+ if params .Has ("utls-fp" ) {
235+ var fp utls.ClientHelloID
236+ switch params .Get ("utls-fp" ) {
237+ case "Hello360_11_0" :
238+ fp = utls .Hello360_11_0
239+ case "Hello360_7_5" :
240+ fp = utls .Hello360_7_5
241+ case "Hello360_Auto" :
242+ fp = utls .Hello360_Auto
243+ case "HelloAndroid_11_OkHttp" :
244+ fp = utls .HelloAndroid_11_OkHttp
245+ case "HelloChrome_100" :
246+ fp = utls .HelloChrome_100
247+ case "HelloChrome_100_PSK" :
248+ fp = utls .HelloChrome_100_PSK
249+ case "HelloChrome_102" :
250+ fp = utls .HelloChrome_102
251+ case "HelloChrome_106_Shuffle" :
252+ fp = utls .HelloChrome_106_Shuffle
253+ case "HelloChrome_112_PSK_Shuf" :
254+ fp = utls .HelloChrome_112_PSK_Shuf
255+ case "HelloChrome_114_Padding_PSK_Shuf" :
256+ fp = utls .HelloChrome_114_Padding_PSK_Shuf
257+ case "HelloChrome_115_PQ" :
258+ fp = utls .HelloChrome_115_PQ
259+ case "HelloChrome_115_PQ_PSK" :
260+ fp = utls .HelloChrome_115_PQ_PSK
261+ case "HelloChrome_120" :
262+ fp = utls .HelloChrome_120
263+ case "HelloChrome_120_PQ" :
264+ fp = utls .HelloChrome_120_PQ
265+ case "HelloChrome_131" :
266+ fp = utls .HelloChrome_131
267+ case "HelloChrome_133" :
268+ fp = utls .HelloChrome_133
269+ case "HelloChrome_58" :
270+ fp = utls .HelloChrome_58
271+ case "HelloChrome_62" :
272+ fp = utls .HelloChrome_62
273+ case "HelloChrome_70" :
274+ fp = utls .HelloChrome_70
275+ case "HelloChrome_72" :
276+ fp = utls .HelloChrome_72
277+ case "HelloChrome_83" :
278+ fp = utls .HelloChrome_83
279+ case "HelloChrome_87" :
280+ fp = utls .HelloChrome_87
281+ case "HelloChrome_96" :
282+ fp = utls .HelloChrome_96
283+ case "HelloChrome_Auto" :
284+ fp = utls .HelloChrome_Auto
285+ case "HelloCustom" :
286+ fp = utls .HelloCustom
287+ case "HelloEdge_106" :
288+ fp = utls .HelloEdge_106
289+ case "HelloEdge_85" :
290+ fp = utls .HelloEdge_85
291+ case "HelloEdge_Auto" :
292+ fp = utls .HelloEdge_Auto
293+ case "HelloFirefox_102" :
294+ fp = utls .HelloFirefox_102
295+ case "HelloFirefox_105" :
296+ fp = utls .HelloFirefox_105
297+ case "HelloFirefox_120" :
298+ fp = utls .HelloFirefox_120
299+ case "HelloFirefox_55" :
300+ fp = utls .HelloFirefox_55
301+ case "HelloFirefox_56" :
302+ fp = utls .HelloFirefox_56
303+ case "HelloFirefox_63" :
304+ fp = utls .HelloFirefox_63
305+ case "HelloFirefox_65" :
306+ fp = utls .HelloFirefox_65
307+ case "HelloFirefox_99" :
308+ fp = utls .HelloFirefox_99
309+ case "HelloFirefox_Auto" :
310+ fp = utls .HelloFirefox_Auto
311+ case "HelloGolang" :
312+ fp = utls .HelloGolang
313+ case "HelloIOS_11_1" :
314+ fp = utls .HelloIOS_11_1
315+ case "HelloIOS_12_1" :
316+ fp = utls .HelloIOS_12_1
317+ case "HelloIOS_13" :
318+ fp = utls .HelloIOS_13
319+ case "HelloIOS_14" :
320+ fp = utls .HelloIOS_14
321+ case "HelloIOS_Auto" :
322+ fp = utls .HelloIOS_Auto
323+ case "HelloQQ_11_1" :
324+ fp = utls .HelloQQ_11_1
325+ case "HelloQQ_Auto" :
326+ fp = utls .HelloQQ_Auto
327+ case "HelloRandomized" :
328+ fp = utls .HelloRandomized
329+ case "HelloRandomizedALPN" :
330+ fp = utls .HelloRandomizedALPN
331+ case "HelloRandomizedNoALPN" :
332+ fp = utls .HelloRandomizedNoALPN
333+ case "HelloSafari_16_0" :
334+ fp = utls .HelloSafari_16_0
335+ case "HelloSafari_Auto" :
336+ fp = utls .HelloSafari_Auto
337+ default :
338+ return nil , fmt .Errorf ("unknown uTLS client hello ID %q" , params .Get ("utls-fp" ))
339+ }
340+ return func (c net.Conn , config * tls.Config ) net.Conn {
341+ var ucfg * utls.Config
342+ if config != nil {
343+ ucfg = & utls.Config {
344+ Rand : config .Rand ,
345+ Time : config .Time ,
346+ Certificates : castCertsToUCerts (config .Certificates ),
347+ RootCAs : config .RootCAs ,
348+ NextProtos : config .NextProtos ,
349+ ServerName : config .ServerName ,
350+ ClientAuth : utls .ClientAuthType (config .ClientAuth ),
351+ ClientCAs : config .ClientCAs ,
352+ InsecureSkipVerify : config .InsecureSkipVerify ,
353+ CipherSuites : config .CipherSuites ,
354+ PreferServerCipherSuites : config .PreferServerCipherSuites ,
355+ SessionTicketsDisabled : config .SessionTicketsDisabled ,
356+ SessionTicketKey : config .SessionTicketKey ,
357+ MinVersion : config .MinVersion ,
358+ MaxVersion : config .MaxVersion ,
359+ CurvePreferences : castCurvesToUCurves (config .CurvePreferences ),
360+ DynamicRecordSizingDisabled : config .DynamicRecordSizingDisabled ,
361+ KeyLogWriter : config .KeyLogWriter ,
362+ }
363+ }
364+ return utls .UClient (c , ucfg , fp )
365+ }, nil
366+ }
367+ return func (c net.Conn , config * tls.Config ) net.Conn {
368+ return tls .Client (c , config )
369+ }, nil
370+ }
371+
372+ func castCertsToUCerts (certs []tls.Certificate ) []utls.Certificate {
373+ if certs == nil {
374+ return nil
375+ }
376+ ucerts := make ([]utls.Certificate , len (certs ))
377+ for i , cert := range certs {
378+ ucerts [i ] = utls.Certificate {
379+ Certificate : cert .Certificate ,
380+ PrivateKey : cert .PrivateKey ,
381+ SupportedSignatureAlgorithms : castSigSchemesToUSigSchemes (cert .SupportedSignatureAlgorithms ),
382+ OCSPStaple : cert .OCSPStaple ,
383+ SignedCertificateTimestamps : cert .SignedCertificateTimestamps ,
384+ Leaf : cert .Leaf ,
385+ }
386+ }
387+ return ucerts
388+ }
389+
390+ func castSigSchemesToUSigSchemes (schemes []tls.SignatureScheme ) []utls.SignatureScheme {
391+ if schemes == nil {
392+ return nil
393+ }
394+ uschemes := make ([]utls.SignatureScheme , len (schemes ))
395+ for i , scheme := range schemes {
396+ uschemes [i ] = utls .SignatureScheme (scheme )
397+ }
398+ return uschemes
399+ }
400+
401+ func castCurvesToUCurves (curves []tls.CurveID ) []utls.CurveID {
402+ if curves == nil {
403+ return nil
404+ }
405+ ucurves := make ([]utls.CurveID , len (curves ))
406+ for i , curve := range curves {
407+ ucurves [i ] = utls .CurveID (curve )
408+ }
409+ return ucurves
410+ }
0 commit comments