github.com/inazumav/sing-box@v0.0.0-20230926072359-ab51429a14f1/outbound/shadowtls.go (about)

     1  package outbound
     2  
     3  import (
     4  	"context"
     5  	"net"
     6  	"os"
     7  
     8  	"github.com/inazumav/sing-box/adapter"
     9  	"github.com/inazumav/sing-box/common/dialer"
    10  	"github.com/inazumav/sing-box/common/tls"
    11  	C "github.com/inazumav/sing-box/constant"
    12  	"github.com/inazumav/sing-box/log"
    13  	"github.com/inazumav/sing-box/option"
    14  	"github.com/sagernet/sing-shadowtls"
    15  	"github.com/sagernet/sing/common"
    16  	M "github.com/sagernet/sing/common/metadata"
    17  	N "github.com/sagernet/sing/common/network"
    18  )
    19  
    20  var _ adapter.Outbound = (*ShadowTLS)(nil)
    21  
    22  type ShadowTLS struct {
    23  	myOutboundAdapter
    24  	client *shadowtls.Client
    25  }
    26  
    27  func NewShadowTLS(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.ShadowTLSOutboundOptions) (*ShadowTLS, error) {
    28  	outbound := &ShadowTLS{
    29  		myOutboundAdapter: myOutboundAdapter{
    30  			protocol:     C.TypeShadowTLS,
    31  			network:      []string{N.NetworkTCP},
    32  			router:       router,
    33  			logger:       logger,
    34  			tag:          tag,
    35  			dependencies: withDialerDependency(options.DialerOptions),
    36  		},
    37  	}
    38  	if options.TLS == nil || !options.TLS.Enabled {
    39  		return nil, C.ErrTLSRequired
    40  	}
    41  
    42  	if options.Version == 0 {
    43  		options.Version = 1
    44  	}
    45  
    46  	if options.Version == 1 {
    47  		options.TLS.MinVersion = "1.2"
    48  		options.TLS.MaxVersion = "1.2"
    49  	}
    50  	tlsConfig, err := tls.NewClient(ctx, options.Server, common.PtrValueOrDefault(options.TLS))
    51  	if err != nil {
    52  		return nil, err
    53  	}
    54  
    55  	var tlsHandshakeFunc shadowtls.TLSHandshakeFunc
    56  	switch options.Version {
    57  	case 1, 2:
    58  		tlsHandshakeFunc = func(ctx context.Context, conn net.Conn, _ shadowtls.TLSSessionIDGeneratorFunc) error {
    59  			return common.Error(tls.ClientHandshake(ctx, conn, tlsConfig))
    60  		}
    61  	case 3:
    62  		if idConfig, loaded := tlsConfig.(tls.WithSessionIDGenerator); loaded {
    63  			tlsHandshakeFunc = func(ctx context.Context, conn net.Conn, sessionIDGenerator shadowtls.TLSSessionIDGeneratorFunc) error {
    64  				idConfig.SetSessionIDGenerator(sessionIDGenerator)
    65  				return common.Error(tls.ClientHandshake(ctx, conn, tlsConfig))
    66  			}
    67  		} else {
    68  			stdTLSConfig, err := tlsConfig.Config()
    69  			if err != nil {
    70  				return nil, err
    71  			}
    72  			tlsHandshakeFunc = shadowtls.DefaultTLSHandshakeFunc(options.Password, stdTLSConfig)
    73  		}
    74  	}
    75  	outboundDialer, err := dialer.New(router, options.DialerOptions)
    76  	if err != nil {
    77  		return nil, err
    78  	}
    79  	client, err := shadowtls.NewClient(shadowtls.ClientConfig{
    80  		Version:      options.Version,
    81  		Password:     options.Password,
    82  		Server:       options.ServerOptions.Build(),
    83  		Dialer:       outboundDialer,
    84  		TLSHandshake: tlsHandshakeFunc,
    85  		Logger:       logger,
    86  	})
    87  	if err != nil {
    88  		return nil, err
    89  	}
    90  	outbound.client = client
    91  	return outbound, nil
    92  }
    93  
    94  func (h *ShadowTLS) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
    95  	ctx, metadata := adapter.AppendContext(ctx)
    96  	metadata.Outbound = h.tag
    97  	metadata.Destination = destination
    98  	switch N.NetworkName(network) {
    99  	case N.NetworkTCP:
   100  		return h.client.DialContext(ctx)
   101  	default:
   102  		return nil, os.ErrInvalid
   103  	}
   104  }
   105  
   106  func (h *ShadowTLS) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
   107  	return nil, os.ErrInvalid
   108  }
   109  
   110  func (h *ShadowTLS) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
   111  	return NewConnection(ctx, h, conn, metadata)
   112  }
   113  
   114  func (h *ShadowTLS) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
   115  	return os.ErrInvalid
   116  }