stack_gvisor.go 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. package tun
  2. import (
  3. "context"
  4. "time"
  5. "github.com/xtls/xray-core/common/errors"
  6. "github.com/xtls/xray-core/common/net"
  7. "gvisor.dev/gvisor/pkg/tcpip"
  8. "gvisor.dev/gvisor/pkg/tcpip/adapters/gonet"
  9. "gvisor.dev/gvisor/pkg/tcpip/header"
  10. "gvisor.dev/gvisor/pkg/tcpip/network/ipv4"
  11. "gvisor.dev/gvisor/pkg/tcpip/network/ipv6"
  12. "gvisor.dev/gvisor/pkg/tcpip/stack"
  13. "gvisor.dev/gvisor/pkg/tcpip/transport/tcp"
  14. "gvisor.dev/gvisor/pkg/tcpip/transport/udp"
  15. "gvisor.dev/gvisor/pkg/waiter"
  16. )
  17. const (
  18. defaultNIC tcpip.NICID = 1
  19. tcpRXBufMinSize = tcp.MinBufferSize
  20. tcpRXBufDefSize = tcp.DefaultSendBufferSize
  21. tcpRXBufMaxSize = 8 << 20 // 8MiB
  22. tcpTXBufMinSize = tcp.MinBufferSize
  23. tcpTXBufDefSize = tcp.DefaultReceiveBufferSize
  24. tcpTXBufMaxSize = 6 << 20 // 6MiB
  25. )
  26. // stackGVisor is ip stack implemented by gVisor package
  27. type stackGVisor struct {
  28. ctx context.Context
  29. tun GVisorTun
  30. idleTimeout time.Duration
  31. handler *Handler
  32. stack *stack.Stack
  33. endpoint stack.LinkEndpoint
  34. }
  35. // GVisorTun implements a bridge to connect gVisor ip stack to tun interface
  36. type GVisorTun interface {
  37. newEndpoint() (stack.LinkEndpoint, error)
  38. }
  39. // NewStack builds new ip stack (using gVisor)
  40. func NewStack(ctx context.Context, options StackOptions, handler *Handler) (Stack, error) {
  41. gStack := &stackGVisor{
  42. ctx: ctx,
  43. tun: options.Tun.(GVisorTun),
  44. idleTimeout: options.IdleTimeout,
  45. handler: handler,
  46. }
  47. return gStack, nil
  48. }
  49. // Start is called by Handler to bring stack to life
  50. func (t *stackGVisor) Start() error {
  51. linkEndpoint, err := t.tun.newEndpoint()
  52. if err != nil {
  53. return err
  54. }
  55. ipStack, err := createStack(linkEndpoint)
  56. if err != nil {
  57. return err
  58. }
  59. tcpForwarder := tcp.NewForwarder(ipStack, 0, 65535, func(r *tcp.ForwarderRequest) {
  60. go func(r *tcp.ForwarderRequest) {
  61. var wq waiter.Queue
  62. var id = r.ID()
  63. // Perform a TCP three-way handshake.
  64. ep, err := r.CreateEndpoint(&wq)
  65. if err != nil {
  66. errors.LogError(t.ctx, err.String())
  67. r.Complete(true)
  68. return
  69. }
  70. options := ep.SocketOptions()
  71. options.SetKeepAlive(false)
  72. options.SetReuseAddress(true)
  73. options.SetReusePort(true)
  74. t.handler.HandleConnection(
  75. gonet.NewTCPConn(&wq, ep),
  76. // local address on the gVisor side is connection destination
  77. net.TCPDestination(net.IPAddress(id.LocalAddress.AsSlice()), net.Port(id.LocalPort)),
  78. )
  79. // close the socket
  80. ep.Close()
  81. // send connection complete upstream
  82. r.Complete(false)
  83. }(r)
  84. })
  85. ipStack.SetTransportProtocolHandler(tcp.ProtocolNumber, tcpForwarder.HandlePacket)
  86. udpForwarder := udp.NewForwarder(ipStack, func(r *udp.ForwarderRequest) {
  87. go func(r *udp.ForwarderRequest) {
  88. var wq waiter.Queue
  89. var id = r.ID()
  90. ep, err := r.CreateEndpoint(&wq)
  91. if err != nil {
  92. errors.LogError(t.ctx, err.String())
  93. return
  94. }
  95. options := ep.SocketOptions()
  96. options.SetReuseAddress(true)
  97. options.SetReusePort(true)
  98. t.handler.HandleConnection(
  99. gonet.NewUDPConn(&wq, ep),
  100. // local address on the gVisor side is connection destination
  101. net.UDPDestination(net.IPAddress(id.LocalAddress.AsSlice()), net.Port(id.LocalPort)),
  102. )
  103. // close the socket
  104. ep.Close()
  105. }(r)
  106. })
  107. ipStack.SetTransportProtocolHandler(udp.ProtocolNumber, udpForwarder.HandlePacket)
  108. t.stack = ipStack
  109. t.endpoint = linkEndpoint
  110. return nil
  111. }
  112. // Close is called by Handler to shut down the stack
  113. func (t *stackGVisor) Close() error {
  114. if t.stack == nil {
  115. return nil
  116. }
  117. t.endpoint.Attach(nil)
  118. t.stack.Close()
  119. for _, endpoint := range t.stack.CleanupEndpoints() {
  120. endpoint.Abort()
  121. }
  122. return nil
  123. }
  124. // createStack configure gVisor ip stack
  125. func createStack(ep stack.LinkEndpoint) (*stack.Stack, error) {
  126. opts := stack.Options{
  127. NetworkProtocols: []stack.NetworkProtocolFactory{ipv4.NewProtocol, ipv6.NewProtocol},
  128. TransportProtocols: []stack.TransportProtocolFactory{tcp.NewProtocol, udp.NewProtocol},
  129. HandleLocal: false,
  130. }
  131. gStack := stack.New(opts)
  132. err := gStack.CreateNIC(defaultNIC, ep)
  133. if err != nil {
  134. return nil, errors.New(err.String())
  135. }
  136. gStack.SetRouteTable([]tcpip.Route{
  137. {Destination: header.IPv4EmptySubnet, NIC: defaultNIC},
  138. {Destination: header.IPv6EmptySubnet, NIC: defaultNIC},
  139. })
  140. err = gStack.SetSpoofing(defaultNIC, true)
  141. if err != nil {
  142. return nil, errors.New(err.String())
  143. }
  144. err = gStack.SetPromiscuousMode(defaultNIC, true)
  145. if err != nil {
  146. return nil, errors.New(err.String())
  147. }
  148. cOpt := tcpip.CongestionControlOption("cubic")
  149. gStack.SetTransportProtocolOption(tcp.ProtocolNumber, &cOpt)
  150. sOpt := tcpip.TCPSACKEnabled(true)
  151. gStack.SetTransportProtocolOption(tcp.ProtocolNumber, &sOpt)
  152. mOpt := tcpip.TCPModerateReceiveBufferOption(true)
  153. gStack.SetTransportProtocolOption(tcp.ProtocolNumber, &mOpt)
  154. tcpRXBufOpt := tcpip.TCPReceiveBufferSizeRangeOption{
  155. Min: tcpRXBufMinSize,
  156. Default: tcpRXBufDefSize,
  157. Max: tcpRXBufMaxSize,
  158. }
  159. err = gStack.SetTransportProtocolOption(tcp.ProtocolNumber, &tcpRXBufOpt)
  160. if err != nil {
  161. return nil, errors.New(err.String())
  162. }
  163. tcpTXBufOpt := tcpip.TCPSendBufferSizeRangeOption{
  164. Min: tcpTXBufMinSize,
  165. Default: tcpTXBufDefSize,
  166. Max: tcpTXBufMaxSize,
  167. }
  168. err = gStack.SetTransportProtocolOption(tcp.ProtocolNumber, &tcpTXBufOpt)
  169. if err != nil {
  170. return nil, errors.New(err.String())
  171. }
  172. return gStack, nil
  173. }