github.com/sagernet/sing-box@v1.2.7/outbound/shadowtls.go (about) 1 package outbound 2 3 import ( 4 "context" 5 "net" 6 "os" 7 8 "github.com/sagernet/sing-box/adapter" 9 "github.com/sagernet/sing-box/common/dialer" 10 "github.com/sagernet/sing-box/common/tls" 11 C "github.com/sagernet/sing-box/constant" 12 "github.com/sagernet/sing-box/log" 13 "github.com/sagernet/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 }, 36 } 37 if options.TLS == nil || !options.TLS.Enabled { 38 return nil, C.ErrTLSRequired 39 } 40 41 if options.Version == 0 { 42 options.Version = 1 43 } 44 45 if options.Version == 1 { 46 options.TLS.MinVersion = "1.2" 47 options.TLS.MaxVersion = "1.2" 48 } 49 tlsConfig, err := tls.NewClient(router, options.Server, common.PtrValueOrDefault(options.TLS)) 50 if err != nil { 51 return nil, err 52 } 53 54 var tlsHandshakeFunc shadowtls.TLSHandshakeFunc 55 switch options.Version { 56 case 1, 2: 57 tlsHandshakeFunc = func(ctx context.Context, conn net.Conn, _ shadowtls.TLSSessionIDGeneratorFunc) error { 58 return common.Error(tls.ClientHandshake(ctx, conn, tlsConfig)) 59 } 60 case 3: 61 if idConfig, loaded := tlsConfig.(tls.WithSessionIDGenerator); loaded { 62 tlsHandshakeFunc = func(ctx context.Context, conn net.Conn, sessionIDGenerator shadowtls.TLSSessionIDGeneratorFunc) error { 63 idConfig.SetSessionIDGenerator(sessionIDGenerator) 64 return common.Error(tls.ClientHandshake(ctx, conn, tlsConfig)) 65 } 66 } else { 67 stdTLSConfig, err := tlsConfig.Config() 68 if err != nil { 69 return nil, err 70 } 71 tlsHandshakeFunc = shadowtls.DefaultTLSHandshakeFunc(options.Password, stdTLSConfig) 72 } 73 } 74 client, err := shadowtls.NewClient(shadowtls.ClientConfig{ 75 Version: options.Version, 76 Password: options.Password, 77 Server: options.ServerOptions.Build(), 78 Dialer: dialer.New(router, options.DialerOptions), 79 TLSHandshake: tlsHandshakeFunc, 80 Logger: logger, 81 }) 82 if err != nil { 83 return nil, err 84 } 85 outbound.client = client 86 return outbound, nil 87 } 88 89 func (h *ShadowTLS) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) { 90 ctx, metadata := adapter.AppendContext(ctx) 91 metadata.Outbound = h.tag 92 metadata.Destination = destination 93 switch N.NetworkName(network) { 94 case N.NetworkTCP: 95 return h.client.DialContext(ctx) 96 default: 97 return nil, os.ErrInvalid 98 } 99 } 100 101 func (h *ShadowTLS) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) { 102 return nil, os.ErrInvalid 103 } 104 105 func (h *ShadowTLS) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error { 106 return NewConnection(ctx, h, conn, metadata) 107 } 108 109 func (h *ShadowTLS) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error { 110 return os.ErrInvalid 111 }