tun.go 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215
  1. package overlay
  2. import (
  3. "crypto/rand"
  4. "fmt"
  5. "io"
  6. "net"
  7. "net/netip"
  8. "github.com/sirupsen/logrus"
  9. "github.com/slackhq/nebula/config"
  10. "github.com/slackhq/nebula/util"
  11. )
  12. const DefaultMTU = 1300
  13. type NameError struct {
  14. Name string
  15. Underlying error
  16. }
  17. func (e *NameError) Error() string {
  18. return fmt.Sprintf("could not set tun device name: %s because %s", e.Name, e.Underlying)
  19. }
  20. // TODO: We may be able to remove routines
  21. type DeviceFactory func(c *config.C, l *logrus.Logger, vpnNetworks []netip.Prefix, unsafeNetworks []netip.Prefix, routines int) (Device, error)
  22. func NewDeviceFromConfig(c *config.C, l *logrus.Logger, vpnNetworks []netip.Prefix, unsafeNetworks []netip.Prefix, routines int) (Device, error) {
  23. switch {
  24. case c.GetBool("tun.disabled", false):
  25. tun := newDisabledTun(vpnNetworks, c.GetInt("tun.tx_queue", 500), c.GetBool("stats.message_metrics", false), l)
  26. return tun, nil
  27. default:
  28. return newTun(c, l, vpnNetworks, unsafeNetworks, routines > 1)
  29. }
  30. }
  31. func NewFdDeviceFromConfig(fd *int) DeviceFactory {
  32. return func(c *config.C, l *logrus.Logger, vpnNetworks []netip.Prefix, unsafeNetworks []netip.Prefix, routines int) (Device, error) {
  33. return newTunFromFd(c, l, *fd, vpnNetworks, unsafeNetworks)
  34. }
  35. }
  36. func getAllRoutesFromConfig(c *config.C, vpnNetworks []netip.Prefix, initial bool) (bool, []Route, error) {
  37. if !initial && !c.HasChanged("tun.routes") && !c.HasChanged("tun.unsafe_routes") {
  38. return false, nil, nil
  39. }
  40. routes, err := parseRoutes(c, vpnNetworks)
  41. if err != nil {
  42. return true, nil, util.NewContextualError("Could not parse tun.routes", nil, err)
  43. }
  44. unsafeRoutes, err := parseUnsafeRoutes(c, vpnNetworks)
  45. if err != nil {
  46. return true, nil, util.NewContextualError("Could not parse tun.unsafe_routes", nil, err)
  47. }
  48. routes = append(routes, unsafeRoutes...)
  49. return true, routes, nil
  50. }
  51. // findRemovedRoutes will return all routes that are not present in the newRoutes list and would affect the system route table.
  52. // Via is not used to evaluate since it does not affect the system route table.
  53. func findRemovedRoutes(newRoutes, oldRoutes []Route) []Route {
  54. var removed []Route
  55. has := func(entry Route) bool {
  56. for _, check := range newRoutes {
  57. if check.Equal(entry) {
  58. return true
  59. }
  60. }
  61. return false
  62. }
  63. for _, oldEntry := range oldRoutes {
  64. if !has(oldEntry) {
  65. removed = append(removed, oldEntry)
  66. }
  67. }
  68. return removed
  69. }
  70. func prefixToMask(prefix netip.Prefix) netip.Addr {
  71. pLen := 128
  72. if prefix.Addr().Is4() {
  73. pLen = 32
  74. }
  75. addr, _ := netip.AddrFromSlice(net.CIDRMask(prefix.Bits(), pLen))
  76. return addr
  77. }
  78. func flipBytes(b []byte) []byte {
  79. for i := 0; i < len(b); i++ {
  80. b[i] ^= 0xFF
  81. }
  82. return b
  83. }
  84. func orBytes(a []byte, b []byte) []byte {
  85. ret := make([]byte, len(a))
  86. for i := 0; i < len(a); i++ {
  87. ret[i] = a[i] | b[i]
  88. }
  89. return ret
  90. }
  91. func getBroadcast(cidr netip.Prefix) netip.Addr {
  92. broadcast, _ := netip.AddrFromSlice(
  93. orBytes(
  94. cidr.Addr().AsSlice(),
  95. flipBytes(prefixToMask(cidr).AsSlice()),
  96. ),
  97. )
  98. return broadcast
  99. }
  100. func selectGateway(dest netip.Prefix, gateways []netip.Prefix) (netip.Prefix, error) {
  101. for _, gateway := range gateways {
  102. if dest.Addr().Is4() && gateway.Addr().Is4() {
  103. return gateway, nil
  104. }
  105. if dest.Addr().Is6() && gateway.Addr().Is6() {
  106. return gateway, nil
  107. }
  108. }
  109. return netip.Prefix{}, fmt.Errorf("no gateway found for %v in the list of vpn networks", dest)
  110. }
  111. // genLinkLocal generates a random IPv4 link-local address.
  112. // If randomizer is nil, it uses rand.Reader to find two random bytes
  113. func genLinkLocal(randomizer io.Reader) netip.Prefix {
  114. if randomizer == nil {
  115. randomizer = rand.Reader
  116. }
  117. octets := []byte{169, 254, 0, 0}
  118. _, _ = randomizer.Read(octets[2:4])
  119. return coerceLinkLocal(octets)
  120. }
  121. func coerceLinkLocal(octets []byte) netip.Prefix {
  122. if octets[3] == 0 {
  123. octets[3] = 1 //please no .0 addresses
  124. } else if octets[2] == 255 && octets[3] == 255 {
  125. octets[3] = 254 //please no broadcast addresses
  126. }
  127. out, _ := netip.AddrFromSlice(octets)
  128. return netip.PrefixFrom(out, 32)
  129. }
  130. // prepareUnsafeOriginAddr provides the IPv4 address used on IPv6-only clients that need to access IPv4 unsafe routes
  131. func prepareUnsafeOriginAddr(d Device, l *logrus.Logger, c *config.C, routes []Route) netip.Prefix {
  132. if !d.Networks()[0].Addr().Is6() {
  133. return netip.Prefix{} //if we have an IPv4 assignment within the overlay, we don't need an unsafe origin address
  134. }
  135. needed := false
  136. for _, route := range routes { //or if we have a route defined into an IPv4 range
  137. if route.Cidr.Addr().Is4() {
  138. needed = true //todo should this only apply to unsafe routes? almost certainly
  139. break
  140. }
  141. }
  142. if !needed {
  143. return netip.Prefix{}
  144. }
  145. //todo better config name for sure
  146. if a := c.GetString("tun.unsafe_origin_address_for_4over6", ""); a != "" {
  147. out, err := netip.ParseAddr(a)
  148. if err != nil {
  149. l.WithField("value", a).WithError(err).Warn("failed to parse tun.unsafe_origin_address_for_4over6, will use a random value")
  150. } else if !out.Is4() || !out.IsLinkLocalUnicast() {
  151. l.WithField("value", out).Warn("tun.unsafe_origin_address_for_4over6 must be an IPv4 address")
  152. } else if out.IsValid() {
  153. return netip.PrefixFrom(out, 32)
  154. }
  155. }
  156. return genLinkLocal(nil)
  157. }
  158. // prepareSnatAddr provides the address that an IPv6-only unsafe router should use to SNAT traffic before handing it to the operating system
  159. func prepareSnatAddr(d Device, l *logrus.Logger, c *config.C) netip.Prefix {
  160. if !d.Networks()[0].Addr().Is6() {
  161. return netip.Prefix{} //if we have an IPv4 assignment within the overlay, we don't need a snat address
  162. }
  163. needed := false
  164. for _, un := range d.UnsafeNetworks() { //if we are an unsafe router for an IPv4 range
  165. if un.Addr().Is4() {
  166. needed = true
  167. break
  168. }
  169. }
  170. if !needed {
  171. return netip.Prefix{}
  172. }
  173. if a := c.GetString("tun.snat_address_for_4over6", ""); a != "" {
  174. out, err := netip.ParseAddr(a)
  175. if err != nil {
  176. l.WithField("value", a).WithError(err).Warn("failed to parse tun.snat_address_for_4over6, will use a random value")
  177. } else if !out.Is4() || !out.IsLinkLocalUnicast() {
  178. l.WithField("value", out).Warn("tun.snat_address_for_4over6 must be an IPv4 address")
  179. } else if out.IsValid() {
  180. return netip.PrefixFrom(out, 32)
  181. }
  182. }
  183. return genLinkLocal(nil)
  184. }