proxy.go 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  1. // Package proxy contains all proxies used by Xray.
  2. //
  3. // To implement an inbound or outbound proxy, one needs to do the following:
  4. // 1. Implement the interface(s) below.
  5. // 2. Register a config creator through common.RegisterConfig.
  6. package proxy
  7. import (
  8. "context"
  9. gotls "crypto/tls"
  10. "io"
  11. "runtime"
  12. "github.com/pires/go-proxyproto"
  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/protocol"
  17. "github.com/xtls/xray-core/common/session"
  18. "github.com/xtls/xray-core/common/signal"
  19. "github.com/xtls/xray-core/features/routing"
  20. "github.com/xtls/xray-core/features/stats"
  21. "github.com/xtls/xray-core/transport"
  22. "github.com/xtls/xray-core/transport/internet"
  23. "github.com/xtls/xray-core/transport/internet/reality"
  24. "github.com/xtls/xray-core/transport/internet/stat"
  25. "github.com/xtls/xray-core/transport/internet/tls"
  26. )
  27. // An Inbound processes inbound connections.
  28. type Inbound interface {
  29. // Network returns a list of networks that this inbound supports. Connections with not-supported networks will not be passed into Process().
  30. Network() []net.Network
  31. // Process processes a connection of given network. If necessary, the Inbound can dispatch the connection to an Outbound.
  32. Process(context.Context, net.Network, stat.Connection, routing.Dispatcher) error
  33. }
  34. // An Outbound process outbound connections.
  35. type Outbound interface {
  36. // Process processes the given connection. The given dialer may be used to dial a system outbound connection.
  37. Process(context.Context, *transport.Link, internet.Dialer) error
  38. }
  39. // UserManager is the interface for Inbounds and Outbounds that can manage their users.
  40. type UserManager interface {
  41. // AddUser adds a new user.
  42. AddUser(context.Context, *protocol.MemoryUser) error
  43. // RemoveUser removes a user by email.
  44. RemoveUser(context.Context, string) error
  45. }
  46. type GetInbound interface {
  47. GetInbound() Inbound
  48. }
  49. type GetOutbound interface {
  50. GetOutbound() Outbound
  51. }
  52. // UnwrapRawConn support unwrap stats, tls, utls, reality and proxyproto conn and get raw tcp conn from it
  53. func UnwrapRawConn(conn net.Conn) (net.Conn, stats.Counter, stats.Counter) {
  54. var readCounter, writerCounter stats.Counter
  55. if conn != nil {
  56. statConn, ok := conn.(*stat.CounterConnection)
  57. if ok {
  58. conn = statConn.Connection
  59. readCounter = statConn.ReadCounter
  60. writerCounter = statConn.WriteCounter
  61. }
  62. if xc, ok := conn.(*gotls.Conn); ok {
  63. conn = xc.NetConn()
  64. } else if utlsConn, ok := conn.(*tls.UConn); ok {
  65. conn = utlsConn.NetConn()
  66. } else if realityConn, ok := conn.(*reality.Conn); ok {
  67. conn = realityConn.NetConn()
  68. } else if realityUConn, ok := conn.(*reality.UConn); ok {
  69. conn = realityUConn.NetConn()
  70. }
  71. if pc, ok := conn.(*proxyproto.Conn); ok {
  72. conn = pc.Raw()
  73. // 8192 > 4096, there is no need to process pc's bufReader
  74. }
  75. }
  76. return conn, readCounter, writerCounter
  77. }
  78. // CopyRawConnIfExist use the most efficient copy method.
  79. // - If caller don't want to turn on splice, do not pass in both reader conn and writer conn
  80. // - writer are from *transport.Link
  81. func CopyRawConnIfExist(ctx context.Context, readerConn net.Conn, writerConn net.Conn, writer buf.Writer, timer signal.ActivityUpdater) error {
  82. readerConn, readCounter, _ := UnwrapRawConn(readerConn)
  83. writerConn, _, writeCounter := UnwrapRawConn(writerConn)
  84. reader := buf.NewReader(readerConn)
  85. if inbound := session.InboundFromContext(ctx); inbound != nil {
  86. if tc, ok := writerConn.(*net.TCPConn); ok && readerConn != nil && writerConn != nil && (runtime.GOOS == "linux" || runtime.GOOS == "android") {
  87. for inbound.CanSpliceCopy != 3 {
  88. if inbound.CanSpliceCopy == 1 {
  89. newError("CopyRawConn splice").WriteToLog(session.ExportIDToError(ctx))
  90. runtime.Gosched() // necessary
  91. w, err := tc.ReadFrom(readerConn)
  92. if readCounter != nil {
  93. readCounter.Add(w)
  94. }
  95. if writeCounter != nil {
  96. writeCounter.Add(w)
  97. }
  98. if err != nil && errors.Cause(err) != io.EOF {
  99. return err
  100. }
  101. return nil
  102. }
  103. buffer, err := reader.ReadMultiBuffer()
  104. if !buffer.IsEmpty() {
  105. if readCounter != nil {
  106. readCounter.Add(int64(buffer.Len()))
  107. }
  108. timer.Update()
  109. if werr := writer.WriteMultiBuffer(buffer); werr != nil {
  110. return werr
  111. }
  112. }
  113. if err != nil {
  114. return err
  115. }
  116. }
  117. }
  118. }
  119. newError("CopyRawConn readv").WriteToLog(session.ExportIDToError(ctx))
  120. if err := buf.Copy(reader, writer, buf.UpdateActivity(timer), buf.AddToStatCounter(readCounter)); err != nil {
  121. return newError("failed to process response").Base(err)
  122. }
  123. return nil
  124. }