outbound.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. package shadowtls
  2. import (
  3. "context"
  4. "crypto/tls"
  5. "github.com/sagernet/sing-shadowtls"
  6. sing_common "github.com/sagernet/sing/common"
  7. utls "github.com/sagernet/utls"
  8. "github.com/xtls/xray-core/common"
  9. "github.com/xtls/xray-core/common/net"
  10. "github.com/xtls/xray-core/common/session"
  11. "github.com/xtls/xray-core/common/singbridge"
  12. "github.com/xtls/xray-core/transport"
  13. "github.com/xtls/xray-core/transport/internet"
  14. internet_tls "github.com/xtls/xray-core/transport/internet/tls"
  15. )
  16. func init() {
  17. common.Must(common.RegisterConfig((*ClientConfig)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
  18. return NewClient(ctx, config.(*ClientConfig))
  19. }))
  20. }
  21. type Outbound struct {
  22. ctx context.Context
  23. clientConfig shadowtls.ClientConfig
  24. }
  25. func NewClient(ctx context.Context, config *ClientConfig) (*Outbound, error) {
  26. return &Outbound{
  27. ctx: ctx,
  28. clientConfig: shadowtls.ClientConfig{
  29. Version: int(config.Version),
  30. Password: config.Password,
  31. Server: singbridge.ToSocksaddr(net.Destination{
  32. Address: config.Address.AsAddress(),
  33. Port: net.Port(config.Port),
  34. }),
  35. Logger: singbridge.NewLogger(newError),
  36. },
  37. }, nil
  38. }
  39. func (o *Outbound) Process(ctx context.Context, link *transport.Link, dialer internet.Dialer) error {
  40. var inboundConn net.Conn
  41. inbound := session.InboundFromContext(ctx)
  42. if inbound != nil {
  43. inboundConn = inbound.Conn
  44. }
  45. outbound := session.OutboundFromContext(ctx)
  46. if outbound == nil || !outbound.Target.IsValid() {
  47. return newError("target not specified")
  48. }
  49. destination := outbound.Target
  50. if destination.Network != net.Network_TCP {
  51. return newError("only TCP is supported")
  52. }
  53. newError("tunneling request to ", destination, " via ", o.clientConfig.Server).WriteToLog(session.ExportIDToError(ctx))
  54. var client *shadowtls.Client
  55. clientConfig := o.clientConfig
  56. clientConfig.Dialer = singbridge.NewTLSDialer(dialer, func(conn net.Conn, xrayConfig *internet_tls.Config, config *tls.Config) net.Conn {
  57. if fingerprint := GetFingerprint(xrayConfig.Fingerprint); fingerprint != nil {
  58. client.SetHandshakeFunc(uTLSHandshakeFunc(config, fingerprint))
  59. } else {
  60. client.SetHandshakeFunc(shadowtls.DefaultTLSHandshakeFunc(clientConfig.Password, config))
  61. }
  62. return conn
  63. })
  64. var err error
  65. client, err = shadowtls.NewClient(clientConfig)
  66. if err != nil {
  67. return newError("failed to create client").Base(err)
  68. }
  69. conn, err := client.DialContext(ctx)
  70. if err != nil {
  71. return newError("failed to connect to server").Base(err)
  72. }
  73. return singbridge.CopyConn(ctx, inboundConn, link, conn)
  74. }
  75. func uTLSHandshakeFunc(config *tls.Config, clientHelloID *utls.ClientHelloID) shadowtls.TLSHandshakeFunc {
  76. return func(ctx context.Context, conn net.Conn, sessionIDGenerator shadowtls.TLSSessionIDGeneratorFunc) error {
  77. tlsConfig := &utls.Config{
  78. Rand: config.Rand,
  79. Time: config.Time,
  80. VerifyPeerCertificate: config.VerifyPeerCertificate,
  81. RootCAs: config.RootCAs,
  82. NextProtos: config.NextProtos,
  83. ServerName: config.ServerName,
  84. InsecureSkipVerify: config.InsecureSkipVerify,
  85. CipherSuites: config.CipherSuites,
  86. MinVersion: config.MinVersion,
  87. MaxVersion: config.MaxVersion,
  88. CurvePreferences: sing_common.Map(config.CurvePreferences, func(it tls.CurveID) utls.CurveID {
  89. return utls.CurveID(it)
  90. }),
  91. SessionTicketsDisabled: config.SessionTicketsDisabled,
  92. Renegotiation: utls.RenegotiationSupport(config.Renegotiation),
  93. SessionIDGenerator: sessionIDGenerator,
  94. }
  95. tlsConn := utls.UClient(conn, tlsConfig, *clientHelloID)
  96. return tlsConn.HandshakeContext(ctx)
  97. }
  98. }