stack_gvisor.go 5.9 KB

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