github.com/sagernet/sing-box@v1.9.0-rc.20/common/tls/client.go (about)

     1  package tls
     2  
     3  import (
     4  	"context"
     5  	"net"
     6  	"os"
     7  
     8  	"github.com/sagernet/sing-box/adapter"
     9  	"github.com/sagernet/sing-box/common/badtls"
    10  	C "github.com/sagernet/sing-box/constant"
    11  	"github.com/sagernet/sing-box/option"
    12  	M "github.com/sagernet/sing/common/metadata"
    13  	N "github.com/sagernet/sing/common/network"
    14  	aTLS "github.com/sagernet/sing/common/tls"
    15  )
    16  
    17  func NewDialerFromOptions(ctx context.Context, router adapter.Router, dialer N.Dialer, serverAddress string, options option.OutboundTLSOptions) (N.Dialer, error) {
    18  	if !options.Enabled {
    19  		return dialer, nil
    20  	}
    21  	config, err := NewClient(ctx, serverAddress, options)
    22  	if err != nil {
    23  		return nil, err
    24  	}
    25  	return NewDialer(dialer, config), nil
    26  }
    27  
    28  func NewClient(ctx context.Context, serverAddress string, options option.OutboundTLSOptions) (Config, error) {
    29  	if !options.Enabled {
    30  		return nil, nil
    31  	}
    32  	if options.ECH != nil && options.ECH.Enabled {
    33  		return NewECHClient(ctx, serverAddress, options)
    34  	} else if options.Reality != nil && options.Reality.Enabled {
    35  		return NewRealityClient(ctx, serverAddress, options)
    36  	} else if options.UTLS != nil && options.UTLS.Enabled {
    37  		return NewUTLSClient(ctx, serverAddress, options)
    38  	} else {
    39  		return NewSTDClient(ctx, serverAddress, options)
    40  	}
    41  }
    42  
    43  func ClientHandshake(ctx context.Context, conn net.Conn, config Config) (Conn, error) {
    44  	ctx, cancel := context.WithTimeout(ctx, C.TCPTimeout)
    45  	defer cancel()
    46  	tlsConn, err := aTLS.ClientHandshake(ctx, conn, config)
    47  	if err != nil {
    48  		return nil, err
    49  	}
    50  	readWaitConn, err := badtls.NewReadWaitConn(tlsConn)
    51  	if err == nil {
    52  		return readWaitConn, nil
    53  	} else if err != os.ErrInvalid {
    54  		return nil, err
    55  	}
    56  	return tlsConn, nil
    57  }
    58  
    59  type Dialer struct {
    60  	dialer N.Dialer
    61  	config Config
    62  }
    63  
    64  func NewDialer(dialer N.Dialer, config Config) N.Dialer {
    65  	return &Dialer{dialer, config}
    66  }
    67  
    68  func (d *Dialer) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
    69  	if network != N.NetworkTCP {
    70  		return nil, os.ErrInvalid
    71  	}
    72  	conn, err := d.dialer.DialContext(ctx, network, destination)
    73  	if err != nil {
    74  		return nil, err
    75  	}
    76  	return ClientHandshake(ctx, conn, d.config)
    77  }
    78  
    79  func (d *Dialer) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
    80  	return nil, os.ErrInvalid
    81  }