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 }