tun_darwin.go 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  1. //go:build !ios && !e2e_testing
  2. // +build !ios,!e2e_testing
  3. package overlay
  4. import (
  5. "errors"
  6. "fmt"
  7. "io"
  8. "net"
  9. "os"
  10. "syscall"
  11. "unsafe"
  12. "github.com/sirupsen/logrus"
  13. "github.com/slackhq/nebula/cidr"
  14. "github.com/slackhq/nebula/iputil"
  15. netroute "golang.org/x/net/route"
  16. "golang.org/x/sys/unix"
  17. )
  18. type tun struct {
  19. io.ReadWriteCloser
  20. Device string
  21. cidr *net.IPNet
  22. DefaultMTU int
  23. Routes []Route
  24. routeTree *cidr.Tree4
  25. l *logrus.Logger
  26. // cache out buffer since we need to prepend 4 bytes for tun metadata
  27. out []byte
  28. }
  29. type sockaddrCtl struct {
  30. scLen uint8
  31. scFamily uint8
  32. ssSysaddr uint16
  33. scID uint32
  34. scUnit uint32
  35. scReserved [5]uint32
  36. }
  37. type ifReq struct {
  38. Name [16]byte
  39. Flags uint16
  40. pad [8]byte
  41. }
  42. func ioctl(a1, a2, a3 uintptr) error {
  43. _, _, errno := unix.Syscall(unix.SYS_IOCTL, a1, a2, a3)
  44. if errno != 0 {
  45. return errno
  46. }
  47. return nil
  48. }
  49. var sockaddrCtlSize uintptr = 32
  50. const (
  51. _SYSPROTO_CONTROL = 2 //define SYSPROTO_CONTROL 2 /* kernel control protocol */
  52. _AF_SYS_CONTROL = 2 //#define AF_SYS_CONTROL 2 /* corresponding sub address type */
  53. _PF_SYSTEM = unix.AF_SYSTEM //#define PF_SYSTEM AF_SYSTEM
  54. _CTLIOCGINFO = 3227799043 //#define CTLIOCGINFO _IOWR('N', 3, struct ctl_info)
  55. utunControlName = "com.apple.net.utun_control"
  56. )
  57. type ifreqAddr struct {
  58. Name [16]byte
  59. Addr unix.RawSockaddrInet4
  60. pad [8]byte
  61. }
  62. type ifreqMTU struct {
  63. Name [16]byte
  64. MTU int32
  65. pad [8]byte
  66. }
  67. func newTun(l *logrus.Logger, name string, cidr *net.IPNet, defaultMTU int, routes []Route, _ int, _ bool) (*tun, error) {
  68. routeTree, err := makeRouteTree(l, routes, false)
  69. if err != nil {
  70. return nil, err
  71. }
  72. ifIndex := -1
  73. if name != "" && name != "utun" {
  74. _, err := fmt.Sscanf(name, "utun%d", &ifIndex)
  75. if err != nil || ifIndex < 0 {
  76. // NOTE: we don't make this error so we don't break existing
  77. // configs that set a name before it was used.
  78. l.Warn("interface name must be utun[0-9]+ on Darwin, ignoring")
  79. ifIndex = -1
  80. }
  81. }
  82. fd, err := unix.Socket(_PF_SYSTEM, unix.SOCK_DGRAM, _SYSPROTO_CONTROL)
  83. if err != nil {
  84. return nil, fmt.Errorf("system socket: %v", err)
  85. }
  86. var ctlInfo = &struct {
  87. ctlID uint32
  88. ctlName [96]byte
  89. }{}
  90. copy(ctlInfo.ctlName[:], utunControlName)
  91. err = ioctl(uintptr(fd), uintptr(_CTLIOCGINFO), uintptr(unsafe.Pointer(ctlInfo)))
  92. if err != nil {
  93. return nil, fmt.Errorf("CTLIOCGINFO: %v", err)
  94. }
  95. sc := sockaddrCtl{
  96. scLen: uint8(sockaddrCtlSize),
  97. scFamily: unix.AF_SYSTEM,
  98. ssSysaddr: _AF_SYS_CONTROL,
  99. scID: ctlInfo.ctlID,
  100. scUnit: uint32(ifIndex) + 1,
  101. }
  102. _, _, errno := unix.RawSyscall(
  103. unix.SYS_CONNECT,
  104. uintptr(fd),
  105. uintptr(unsafe.Pointer(&sc)),
  106. sockaddrCtlSize,
  107. )
  108. if errno != 0 {
  109. return nil, fmt.Errorf("SYS_CONNECT: %v", errno)
  110. }
  111. var ifName struct {
  112. name [16]byte
  113. }
  114. ifNameSize := uintptr(len(ifName.name))
  115. _, _, errno = syscall.Syscall6(syscall.SYS_GETSOCKOPT, uintptr(fd),
  116. 2, // SYSPROTO_CONTROL
  117. 2, // UTUN_OPT_IFNAME
  118. uintptr(unsafe.Pointer(&ifName)),
  119. uintptr(unsafe.Pointer(&ifNameSize)), 0)
  120. if errno != 0 {
  121. return nil, fmt.Errorf("SYS_GETSOCKOPT: %v", errno)
  122. }
  123. name = string(ifName.name[:ifNameSize-1])
  124. err = syscall.SetNonblock(fd, true)
  125. if err != nil {
  126. return nil, fmt.Errorf("SetNonblock: %v", err)
  127. }
  128. file := os.NewFile(uintptr(fd), "")
  129. tun := &tun{
  130. ReadWriteCloser: file,
  131. Device: name,
  132. cidr: cidr,
  133. DefaultMTU: defaultMTU,
  134. Routes: routes,
  135. routeTree: routeTree,
  136. l: l,
  137. }
  138. return tun, nil
  139. }
  140. func (t *tun) deviceBytes() (o [16]byte) {
  141. for i, c := range t.Device {
  142. o[i] = byte(c)
  143. }
  144. return
  145. }
  146. func newTunFromFd(_ *logrus.Logger, _ int, _ *net.IPNet, _ int, _ []Route, _ int) (*tun, error) {
  147. return nil, fmt.Errorf("newTunFromFd not supported in Darwin")
  148. }
  149. func (t *tun) Close() error {
  150. if t.ReadWriteCloser != nil {
  151. return t.ReadWriteCloser.Close()
  152. }
  153. return nil
  154. }
  155. func (t *tun) Activate() error {
  156. devName := t.deviceBytes()
  157. var addr, mask [4]byte
  158. copy(addr[:], t.cidr.IP.To4())
  159. copy(mask[:], t.cidr.Mask)
  160. s, err := unix.Socket(
  161. unix.AF_INET,
  162. unix.SOCK_DGRAM,
  163. unix.IPPROTO_IP,
  164. )
  165. if err != nil {
  166. return err
  167. }
  168. fd := uintptr(s)
  169. ifra := ifreqAddr{
  170. Name: devName,
  171. Addr: unix.RawSockaddrInet4{
  172. Family: unix.AF_INET,
  173. Addr: addr,
  174. },
  175. }
  176. // Set the device ip address
  177. if err = ioctl(fd, unix.SIOCSIFADDR, uintptr(unsafe.Pointer(&ifra))); err != nil {
  178. return fmt.Errorf("failed to set tun address: %s", err)
  179. }
  180. // Set the device network
  181. ifra.Addr.Addr = mask
  182. if err = ioctl(fd, unix.SIOCSIFNETMASK, uintptr(unsafe.Pointer(&ifra))); err != nil {
  183. return fmt.Errorf("failed to set tun netmask: %s", err)
  184. }
  185. // Set the device name
  186. ifrf := ifReq{Name: devName}
  187. if err = ioctl(fd, unix.SIOCGIFFLAGS, uintptr(unsafe.Pointer(&ifrf))); err != nil {
  188. return fmt.Errorf("failed to set tun device name: %s", err)
  189. }
  190. // Set the MTU on the device
  191. ifm := ifreqMTU{Name: devName, MTU: int32(t.DefaultMTU)}
  192. if err = ioctl(fd, unix.SIOCSIFMTU, uintptr(unsafe.Pointer(&ifm))); err != nil {
  193. return fmt.Errorf("failed to set tun mtu: %v", err)
  194. }
  195. /*
  196. // Set the transmit queue length
  197. ifrq := ifreqQLEN{Name: devName, Value: int32(t.TXQueueLen)}
  198. if err = ioctl(fd, unix.SIOCSIFTXQLEN, uintptr(unsafe.Pointer(&ifrq))); err != nil {
  199. // If we can't set the queue length nebula will still work but it may lead to packet loss
  200. l.WithError(err).Error("Failed to set tun tx queue length")
  201. }
  202. */
  203. // Bring up the interface
  204. ifrf.Flags = ifrf.Flags | unix.IFF_UP
  205. if err = ioctl(fd, unix.SIOCSIFFLAGS, uintptr(unsafe.Pointer(&ifrf))); err != nil {
  206. return fmt.Errorf("failed to bring the tun device up: %s", err)
  207. }
  208. routeSock, err := unix.Socket(unix.AF_ROUTE, unix.SOCK_RAW, unix.AF_UNSPEC)
  209. if err != nil {
  210. return fmt.Errorf("unable to create AF_ROUTE socket: %v", err)
  211. }
  212. defer func() {
  213. unix.Shutdown(routeSock, unix.SHUT_RDWR)
  214. err := unix.Close(routeSock)
  215. if err != nil {
  216. t.l.WithError(err).Error("failed to close AF_ROUTE socket")
  217. }
  218. }()
  219. routeAddr := &netroute.Inet4Addr{}
  220. maskAddr := &netroute.Inet4Addr{}
  221. linkAddr, err := getLinkAddr(t.Device)
  222. if err != nil {
  223. return err
  224. }
  225. if linkAddr == nil {
  226. return fmt.Errorf("unable to discover link_addr for tun interface")
  227. }
  228. copy(routeAddr.IP[:], addr[:])
  229. copy(maskAddr.IP[:], mask[:])
  230. err = addRoute(routeSock, routeAddr, maskAddr, linkAddr)
  231. if err != nil {
  232. if errors.Is(err, unix.EEXIST) {
  233. err = fmt.Errorf("unable to add tun route, identical route already exists: %s", t.cidr)
  234. }
  235. return err
  236. }
  237. // Run the interface
  238. ifrf.Flags = ifrf.Flags | unix.IFF_UP | unix.IFF_RUNNING
  239. if err = ioctl(fd, unix.SIOCSIFFLAGS, uintptr(unsafe.Pointer(&ifrf))); err != nil {
  240. return fmt.Errorf("failed to run tun device: %s", err)
  241. }
  242. // Unsafe path routes
  243. for _, r := range t.Routes {
  244. if r.Via == nil {
  245. // We don't allow route MTUs so only install routes with a via
  246. continue
  247. }
  248. copy(routeAddr.IP[:], r.Cidr.IP.To4())
  249. copy(maskAddr.IP[:], net.IP(r.Cidr.Mask).To4())
  250. err = addRoute(routeSock, routeAddr, maskAddr, linkAddr)
  251. if err != nil {
  252. if errors.Is(err, unix.EEXIST) {
  253. t.l.WithField("route", r.Cidr).
  254. Warnf("unable to add unsafe_route, identical route already exists")
  255. } else {
  256. return err
  257. }
  258. }
  259. // TODO how to set metric
  260. }
  261. return nil
  262. }
  263. func (t *tun) RouteFor(ip iputil.VpnIp) iputil.VpnIp {
  264. r := t.routeTree.MostSpecificContains(ip)
  265. if r != nil {
  266. return r.(iputil.VpnIp)
  267. }
  268. return 0
  269. }
  270. // Get the LinkAddr for the interface of the given name
  271. // TODO: Is there an easier way to fetch this when we create the interface?
  272. // Maybe SIOCGIFINDEX? but this doesn't appear to exist in the darwin headers.
  273. func getLinkAddr(name string) (*netroute.LinkAddr, error) {
  274. rib, err := netroute.FetchRIB(unix.AF_UNSPEC, unix.NET_RT_IFLIST, 0)
  275. if err != nil {
  276. return nil, err
  277. }
  278. msgs, err := netroute.ParseRIB(unix.NET_RT_IFLIST, rib)
  279. if err != nil {
  280. return nil, err
  281. }
  282. for _, m := range msgs {
  283. switch m := m.(type) {
  284. case *netroute.InterfaceMessage:
  285. if m.Name == name {
  286. sa, ok := m.Addrs[unix.RTAX_IFP].(*netroute.LinkAddr)
  287. if ok {
  288. return sa, nil
  289. }
  290. }
  291. }
  292. }
  293. return nil, nil
  294. }
  295. func addRoute(sock int, addr, mask *netroute.Inet4Addr, link *netroute.LinkAddr) error {
  296. r := netroute.RouteMessage{
  297. Version: unix.RTM_VERSION,
  298. Type: unix.RTM_ADD,
  299. Flags: unix.RTF_UP,
  300. Seq: 1,
  301. Addrs: []netroute.Addr{
  302. unix.RTAX_DST: addr,
  303. unix.RTAX_GATEWAY: link,
  304. unix.RTAX_NETMASK: mask,
  305. },
  306. }
  307. data, err := r.Marshal()
  308. if err != nil {
  309. return fmt.Errorf("failed to create route.RouteMessage: %w", err)
  310. }
  311. _, err = unix.Write(sock, data[:])
  312. if err != nil {
  313. return fmt.Errorf("failed to write route.RouteMessage to socket: %w", err)
  314. }
  315. return nil
  316. }
  317. func (t *tun) Read(to []byte) (int, error) {
  318. buf := make([]byte, len(to)+4)
  319. n, err := t.ReadWriteCloser.Read(buf)
  320. copy(to, buf[4:])
  321. return n - 4, err
  322. }
  323. // Write is only valid for single threaded use
  324. func (t *tun) Write(from []byte) (int, error) {
  325. buf := t.out
  326. if cap(buf) < len(from)+4 {
  327. buf = make([]byte, len(from)+4)
  328. t.out = buf
  329. }
  330. buf = buf[:len(from)+4]
  331. if len(from) == 0 {
  332. return 0, syscall.EIO
  333. }
  334. // Determine the IP Family for the NULL L2 Header
  335. ipVer := from[0] >> 4
  336. if ipVer == 4 {
  337. buf[3] = syscall.AF_INET
  338. } else if ipVer == 6 {
  339. buf[3] = syscall.AF_INET6
  340. } else {
  341. return 0, fmt.Errorf("unable to determine IP version from packet")
  342. }
  343. copy(buf[4:], from)
  344. n, err := t.ReadWriteCloser.Write(buf)
  345. return n - 4, err
  346. }
  347. func (t *tun) Cidr() *net.IPNet {
  348. return t.cidr
  349. }
  350. func (t *tun) Name() string {
  351. return t.Device
  352. }
  353. func (t *tun) NewMultiQueueReader() (io.ReadWriteCloser, error) {
  354. return nil, fmt.Errorf("TODO: multiqueue not implemented for darwin")
  355. }