diff --git a/app/geodata/download.go b/app/geodata/download.go index cc1498a0f..4e975c972 100644 --- a/app/geodata/download.go +++ b/app/geodata/download.go @@ -9,6 +9,7 @@ import ( "path/filepath" "time" + utls "github.com/refraction-networking/utls" "github.com/xtls/xray-core/common/errors" "github.com/xtls/xray-core/common/net" "github.com/xtls/xray-core/common/platform/filesystem" @@ -59,35 +60,50 @@ func newDownloader(ctx context.Context, dispatcher routing.Dispatcher, outbound } func newClient(baseCtx context.Context, dispatcher routing.Dispatcher, outbound string) *http.Client { + dial := func(ctx context.Context, network, address string) (net.Conn, error) { + var conn net.Conn + err := task.Run(ctx, func() error { + if tagged.Dialer == nil { + return errors.New("tagged dialer is not initialized") + } + dest, err := net.ParseDestination(network + ":" + address) + if err != nil { + return errors.New("cannot understand address").Base(err) + } + c, err := tagged.Dialer(baseCtx, dispatcher, dest, outbound) + if err != nil { + return errors.New("cannot dial remote address ", dest).Base(err) + } + conn = c + return nil + }) + if err != nil { + return nil, errors.New("cannot finish connection").Base(err) + } + return &idleConn{ + Conn: conn, + }, nil + } return &http.Client{ Transport: &http.Transport{ Proxy: nil, DisableKeepAlives: true, - DialContext: func(ctx context.Context, network, address string) (net.Conn, error) { - var conn net.Conn - err := task.Run(ctx, func() error { - if tagged.Dialer == nil { - return errors.New("tagged dialer is not initialized") - } - dest, err := net.ParseDestination(network + ":" + address) - if err != nil { - return errors.New("cannot understand address").Base(err) - } - c, err := tagged.Dialer(baseCtx, dispatcher, dest, outbound) - if err != nil { - return errors.New("cannot dial remote address ", dest).Base(err) - } - conn = c - return nil - }) + DialContext: dial, + DialTLSContext: func(ctx context.Context, network, address string) (net.Conn, error) { + conn, err := dial(ctx, network, address) if err != nil { - return nil, errors.New("cannot finish connection").Base(err) + return nil, err } - return &idleConn{ - Conn: conn, - }, nil + host, _, _ := net.SplitHostPort(address) + tlsConn := utls.UClient(conn, &utls.Config{ServerName: host}, utls.HelloChrome_Auto) + handshakeCtx, cancel := context.WithTimeout(ctx, idleTimeout) + defer cancel() + if err := tlsConn.HandshakeContext(handshakeCtx); err != nil { + conn.Close() + return nil, err + } + return tlsConn, nil }, - TLSHandshakeTimeout: idleTimeout, ResponseHeaderTimeout: idleTimeout, }, CheckRedirect: func(req *http.Request, via []*http.Request) error {