1
0

service.go 7.0 KB

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