service.go 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  1. package service
  2. import (
  3. "bytes"
  4. "context"
  5. "errors"
  6. "fmt"
  7. "log"
  8. "math"
  9. "net"
  10. "net/netip"
  11. "strings"
  12. "sync"
  13. "github.com/slackhq/nebula"
  14. "github.com/slackhq/nebula/overlay"
  15. "golang.org/x/sync/errgroup"
  16. "gvisor.dev/gvisor/pkg/buffer"
  17. "gvisor.dev/gvisor/pkg/tcpip"
  18. "gvisor.dev/gvisor/pkg/tcpip/adapters/gonet"
  19. "gvisor.dev/gvisor/pkg/tcpip/header"
  20. "gvisor.dev/gvisor/pkg/tcpip/link/channel"
  21. "gvisor.dev/gvisor/pkg/tcpip/network/ipv4"
  22. "gvisor.dev/gvisor/pkg/tcpip/network/ipv6"
  23. "gvisor.dev/gvisor/pkg/tcpip/stack"
  24. "gvisor.dev/gvisor/pkg/tcpip/transport/icmp"
  25. "gvisor.dev/gvisor/pkg/tcpip/transport/tcp"
  26. "gvisor.dev/gvisor/pkg/tcpip/transport/udp"
  27. "gvisor.dev/gvisor/pkg/waiter"
  28. )
  29. const nicID = 1
  30. type Service struct {
  31. eg *errgroup.Group
  32. control *nebula.Control
  33. ipstack *stack.Stack
  34. mu struct {
  35. sync.Mutex
  36. listeners map[uint16]*tcpListener
  37. }
  38. }
  39. func New(control *nebula.Control) (*Service, error) {
  40. wait, err := control.Start()
  41. if err != nil {
  42. return nil, err
  43. }
  44. ctx := control.Context()
  45. eg, ctx := errgroup.WithContext(ctx)
  46. s := Service{
  47. eg: eg,
  48. control: control,
  49. }
  50. s.mu.listeners = map[uint16]*tcpListener{}
  51. device, ok := control.Device().(*overlay.UserDevice)
  52. if !ok {
  53. return nil, errors.New("must be using user device")
  54. }
  55. s.ipstack = stack.New(stack.Options{
  56. NetworkProtocols: []stack.NetworkProtocolFactory{ipv4.NewProtocol, ipv6.NewProtocol},
  57. TransportProtocols: []stack.TransportProtocolFactory{tcp.NewProtocol, udp.NewProtocol, icmp.NewProtocol4, icmp.NewProtocol6},
  58. })
  59. sackEnabledOpt := tcpip.TCPSACKEnabled(true) // TCP SACK is disabled by default
  60. tcpipErr := s.ipstack.SetTransportProtocolOption(tcp.ProtocolNumber, &sackEnabledOpt)
  61. if tcpipErr != nil {
  62. return nil, fmt.Errorf("could not enable TCP SACK: %v", tcpipErr)
  63. }
  64. linkEP := channel.New( /*size*/ 512 /*mtu*/, 1280, "")
  65. if tcpipProblem := s.ipstack.CreateNIC(nicID, linkEP); tcpipProblem != nil {
  66. return nil, fmt.Errorf("could not create netstack NIC: %v", tcpipProblem)
  67. }
  68. ipv4Subnet, _ := tcpip.NewSubnet(tcpip.AddrFrom4([4]byte{0x00, 0x00, 0x00, 0x00}), tcpip.MaskFrom(strings.Repeat("\x00", 4)))
  69. s.ipstack.SetRouteTable([]tcpip.Route{
  70. {
  71. Destination: ipv4Subnet,
  72. NIC: nicID,
  73. },
  74. })
  75. ipNet := device.Networks()
  76. pa := tcpip.ProtocolAddress{
  77. AddressWithPrefix: tcpip.AddrFromSlice(ipNet[0].Addr().AsSlice()).WithPrefix(),
  78. Protocol: ipv4.ProtocolNumber,
  79. }
  80. if err := s.ipstack.AddProtocolAddress(nicID, pa, stack.AddressProperties{
  81. PEB: stack.CanBePrimaryEndpoint, // zero value default
  82. ConfigType: stack.AddressConfigStatic, // zero value default
  83. }); err != nil {
  84. return nil, fmt.Errorf("error creating IP: %s", err)
  85. }
  86. const tcpReceiveBufferSize = 0
  87. const maxInFlightConnectionAttempts = 1024
  88. tcpFwd := tcp.NewForwarder(s.ipstack, tcpReceiveBufferSize, maxInFlightConnectionAttempts, s.tcpHandler)
  89. s.ipstack.SetTransportProtocolHandler(tcp.ProtocolNumber, tcpFwd.HandlePacket)
  90. reader, writer := device.Pipe()
  91. go func() {
  92. <-ctx.Done()
  93. reader.Close()
  94. writer.Close()
  95. }()
  96. // create Goroutines to forward packets between Nebula and Gvisor
  97. eg.Go(func() error {
  98. buf := make([]byte, header.IPv4MaximumHeaderSize+header.IPv4MaximumPayloadSize)
  99. for {
  100. // this will read exactly one packet
  101. n, err := reader.Read(buf)
  102. if err != nil {
  103. return err
  104. }
  105. packetBuf := stack.NewPacketBuffer(stack.PacketBufferOptions{
  106. Payload: buffer.MakeWithData(bytes.Clone(buf[:n])),
  107. })
  108. linkEP.InjectInbound(header.IPv4ProtocolNumber, packetBuf)
  109. if err := ctx.Err(); err != nil {
  110. return err
  111. }
  112. }
  113. })
  114. eg.Go(func() error {
  115. for {
  116. packet := linkEP.ReadContext(ctx)
  117. if packet == nil {
  118. if err := ctx.Err(); err != nil {
  119. return err
  120. }
  121. continue
  122. }
  123. bufView := packet.ToView()
  124. if _, err := bufView.WriteTo(writer); err != nil {
  125. return err
  126. }
  127. bufView.Release()
  128. }
  129. })
  130. // Add the nebula wait function to the group so a fatal reader error
  131. // propagates out through errgroup.Wait().
  132. eg.Go(func() error {
  133. return wait()
  134. })
  135. return &s, nil
  136. }
  137. func getProtocolNumber(addr netip.Addr) tcpip.NetworkProtocolNumber {
  138. if addr.Is6() {
  139. return ipv6.ProtocolNumber
  140. }
  141. return ipv4.ProtocolNumber
  142. }
  143. // DialContext dials the provided address.
  144. func (s *Service) DialContext(ctx context.Context, network, address string) (net.Conn, error) {
  145. switch network {
  146. case "udp", "udp4", "udp6":
  147. addr, err := net.ResolveUDPAddr(network, address)
  148. if err != nil {
  149. return nil, err
  150. }
  151. fullAddr := tcpip.FullAddress{
  152. NIC: nicID,
  153. Addr: tcpip.AddrFromSlice(addr.IP),
  154. Port: uint16(addr.Port),
  155. }
  156. num := getProtocolNumber(addr.AddrPort().Addr())
  157. return gonet.DialUDP(s.ipstack, nil, &fullAddr, num)
  158. case "tcp", "tcp4", "tcp6":
  159. addr, err := net.ResolveTCPAddr(network, address)
  160. if err != nil {
  161. return nil, err
  162. }
  163. fullAddr := tcpip.FullAddress{
  164. NIC: nicID,
  165. Addr: tcpip.AddrFromSlice(addr.IP),
  166. Port: uint16(addr.Port),
  167. }
  168. num := getProtocolNumber(addr.AddrPort().Addr())
  169. return gonet.DialContextTCP(ctx, s.ipstack, fullAddr, num)
  170. default:
  171. return nil, fmt.Errorf("unknown network type: %s", network)
  172. }
  173. }
  174. // Dial dials the provided address
  175. func (s *Service) Dial(network, address string) (net.Conn, error) {
  176. return s.DialContext(context.Background(), network, address)
  177. }
  178. // Listen listens on the provided address. Currently only TCP with wildcard
  179. // addresses are supported.
  180. func (s *Service) Listen(network, address string) (net.Listener, error) {
  181. if network != "tcp" && network != "tcp4" {
  182. return nil, errors.New("only tcp is supported")
  183. }
  184. addr, err := net.ResolveTCPAddr(network, address)
  185. if err != nil {
  186. return nil, err
  187. }
  188. if addr.IP != nil && !bytes.Equal(addr.IP, []byte{0, 0, 0, 0}) {
  189. return nil, fmt.Errorf("only wildcard address supported, got %q %v", address, addr.IP)
  190. }
  191. if addr.Port == 0 {
  192. return nil, errors.New("specific port required, got 0")
  193. }
  194. if addr.Port < 0 || addr.Port >= math.MaxUint16 {
  195. return nil, fmt.Errorf("invalid port %d", addr.Port)
  196. }
  197. port := uint16(addr.Port)
  198. l := &tcpListener{
  199. port: port,
  200. s: s,
  201. addr: addr,
  202. accept: make(chan net.Conn),
  203. }
  204. s.mu.Lock()
  205. defer s.mu.Unlock()
  206. if _, ok := s.mu.listeners[port]; ok {
  207. return nil, fmt.Errorf("already listening on port %d", port)
  208. }
  209. s.mu.listeners[port] = l
  210. return l, nil
  211. }
  212. func (s *Service) Wait() error {
  213. return s.eg.Wait()
  214. }
  215. func (s *Service) Close() error {
  216. s.control.Stop()
  217. return nil
  218. }
  219. func (s *Service) tcpHandler(r *tcp.ForwarderRequest) {
  220. endpointID := r.ID()
  221. s.mu.Lock()
  222. defer s.mu.Unlock()
  223. l, ok := s.mu.listeners[endpointID.LocalPort]
  224. if !ok {
  225. r.Complete(true)
  226. return
  227. }
  228. var wq waiter.Queue
  229. ep, err := r.CreateEndpoint(&wq)
  230. if err != nil {
  231. log.Printf("got error creating endpoint %q", err)
  232. r.Complete(true)
  233. return
  234. }
  235. r.Complete(false)
  236. ep.SocketOptions().SetKeepAlive(true)
  237. conn := gonet.NewTCPConn(&wq, ep)
  238. l.accept <- conn
  239. }