outbound.go 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. package shadowsocks_2022
  2. import (
  3. "context"
  4. "time"
  5. shadowsocks "github.com/sagernet/sing-shadowsocks"
  6. "github.com/sagernet/sing-shadowsocks/shadowaead_2022"
  7. C "github.com/sagernet/sing/common"
  8. B "github.com/sagernet/sing/common/buf"
  9. "github.com/sagernet/sing/common/bufio"
  10. N "github.com/sagernet/sing/common/network"
  11. "github.com/sagernet/sing/common/uot"
  12. "github.com/xtls/xray-core/common"
  13. "github.com/xtls/xray-core/common/buf"
  14. "github.com/xtls/xray-core/common/errors"
  15. "github.com/xtls/xray-core/common/net"
  16. "github.com/xtls/xray-core/common/session"
  17. "github.com/xtls/xray-core/common/singbridge"
  18. "github.com/xtls/xray-core/transport"
  19. "github.com/xtls/xray-core/transport/internet"
  20. )
  21. func init() {
  22. common.Must(common.RegisterConfig((*ClientConfig)(nil), func(ctx context.Context, config interface{}) (interface{}, error) {
  23. return NewClient(ctx, config.(*ClientConfig))
  24. }))
  25. }
  26. type Outbound struct {
  27. ctx context.Context
  28. server net.Destination
  29. method shadowsocks.Method
  30. uotClient *uot.Client
  31. }
  32. func NewClient(ctx context.Context, config *ClientConfig) (*Outbound, error) {
  33. o := &Outbound{
  34. ctx: ctx,
  35. server: net.Destination{
  36. Address: config.Address.AsAddress(),
  37. Port: net.Port(config.Port),
  38. Network: net.Network_TCP,
  39. },
  40. }
  41. if C.Contains(shadowaead_2022.List, config.Method) {
  42. if config.Key == "" {
  43. return nil, errors.New("missing psk")
  44. }
  45. method, err := shadowaead_2022.NewWithPassword(config.Method, config.Key, nil)
  46. if err != nil {
  47. return nil, errors.New("create method").Base(err)
  48. }
  49. o.method = method
  50. } else {
  51. return nil, errors.New("unknown method ", config.Method)
  52. }
  53. if config.UdpOverTcp {
  54. o.uotClient = &uot.Client{Version: uint8(config.UdpOverTcpVersion)}
  55. }
  56. return o, nil
  57. }
  58. func (o *Outbound) Process(ctx context.Context, link *transport.Link, dialer internet.Dialer) error {
  59. var inboundConn net.Conn
  60. inbound := session.InboundFromContext(ctx)
  61. if inbound != nil {
  62. inboundConn = inbound.Conn
  63. }
  64. outbounds := session.OutboundsFromContext(ctx)
  65. ob := outbounds[len(outbounds)-1]
  66. if !ob.Target.IsValid() {
  67. return errors.New("target not specified")
  68. }
  69. ob.Name = "shadowsocks-2022"
  70. ob.CanSpliceCopy = 3
  71. destination := ob.Target
  72. network := destination.Network
  73. errors.LogInfo(ctx, "tunneling request to ", destination, " via ", o.server.NetAddr())
  74. serverDestination := o.server
  75. if o.uotClient != nil {
  76. serverDestination.Network = net.Network_TCP
  77. } else {
  78. serverDestination.Network = network
  79. }
  80. connection, err := dialer.Dial(ctx, serverDestination)
  81. if err != nil {
  82. return errors.New("failed to connect to server").Base(err)
  83. }
  84. if session.TimeoutOnlyFromContext(ctx) {
  85. ctx, _ = context.WithCancel(context.Background())
  86. }
  87. if network == net.Network_TCP {
  88. serverConn := o.method.DialEarlyConn(connection, singbridge.ToSocksaddr(destination))
  89. var handshake bool
  90. if timeoutReader, isTimeoutReader := link.Reader.(buf.TimeoutReader); isTimeoutReader {
  91. mb, err := timeoutReader.ReadMultiBufferTimeout(time.Millisecond * 100)
  92. if err != nil && err != buf.ErrNotTimeoutReader && err != buf.ErrReadTimeout {
  93. return errors.New("read payload").Base(err)
  94. }
  95. payload := B.New()
  96. for {
  97. payload.Reset()
  98. nb, n := buf.SplitBytes(mb, payload.FreeBytes())
  99. if n > 0 {
  100. payload.Truncate(n)
  101. _, err = serverConn.Write(payload.Bytes())
  102. if err != nil {
  103. payload.Release()
  104. return errors.New("write payload").Base(err)
  105. }
  106. handshake = true
  107. }
  108. if nb.IsEmpty() {
  109. break
  110. }
  111. mb = nb
  112. }
  113. payload.Release()
  114. }
  115. if !handshake {
  116. _, err = serverConn.Write(nil)
  117. if err != nil {
  118. return errors.New("client handshake").Base(err)
  119. }
  120. }
  121. return singbridge.CopyConn(ctx, inboundConn, link, serverConn)
  122. } else {
  123. var packetConn N.PacketConn
  124. if pc, isPacketConn := inboundConn.(N.PacketConn); isPacketConn {
  125. packetConn = pc
  126. } else if nc, isNetPacket := inboundConn.(net.PacketConn); isNetPacket {
  127. packetConn = bufio.NewPacketConn(nc)
  128. } else {
  129. packetConn = &singbridge.PacketConnWrapper{
  130. Reader: link.Reader,
  131. Writer: link.Writer,
  132. Conn: inboundConn,
  133. Dest: destination,
  134. }
  135. }
  136. if o.uotClient != nil {
  137. uConn, err := o.uotClient.DialEarlyConn(o.method.DialEarlyConn(connection, uot.RequestDestination(o.uotClient.Version)), false, singbridge.ToSocksaddr(destination))
  138. if err != nil {
  139. return err
  140. }
  141. return singbridge.ReturnError(bufio.CopyPacketConn(ctx, packetConn, uConn))
  142. } else {
  143. serverConn := o.method.DialPacketConn(connection)
  144. return singbridge.ReturnError(bufio.CopyPacketConn(ctx, packetConn, serverConn))
  145. }
  146. }
  147. }