allow_list.go 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. package nebula
  2. import (
  3. "fmt"
  4. "net/netip"
  5. "regexp"
  6. "github.com/gaissmai/bart"
  7. "github.com/slackhq/nebula/config"
  8. )
  9. type AllowList struct {
  10. // The values of this cidrTree are `bool`, signifying allow/deny
  11. cidrTree *bart.Table[bool]
  12. }
  13. type RemoteAllowList struct {
  14. AllowList *AllowList
  15. // Inside Range Specific, keys of this tree are inside CIDRs and values
  16. // are *AllowList
  17. insideAllowLists *bart.Table[*AllowList]
  18. }
  19. type LocalAllowList struct {
  20. AllowList *AllowList
  21. // To avoid ambiguity, all rules must be true, or all rules must be false.
  22. nameRules []AllowListNameRule
  23. }
  24. type AllowListNameRule struct {
  25. Name *regexp.Regexp
  26. Allow bool
  27. }
  28. func NewLocalAllowListFromConfig(c *config.C, k string) (*LocalAllowList, error) {
  29. var nameRules []AllowListNameRule
  30. handleKey := func(key string, value any) (bool, error) {
  31. if key == "interfaces" {
  32. var err error
  33. nameRules, err = getAllowListInterfaces(k, value)
  34. if err != nil {
  35. return false, err
  36. }
  37. return true, nil
  38. }
  39. return false, nil
  40. }
  41. al, err := newAllowListFromConfig(c, k, handleKey)
  42. if err != nil {
  43. return nil, err
  44. }
  45. return &LocalAllowList{AllowList: al, nameRules: nameRules}, nil
  46. }
  47. func NewRemoteAllowListFromConfig(c *config.C, k, rangesKey string) (*RemoteAllowList, error) {
  48. al, err := newAllowListFromConfig(c, k, nil)
  49. if err != nil {
  50. return nil, err
  51. }
  52. remoteAllowRanges, err := getRemoteAllowRanges(c, rangesKey)
  53. if err != nil {
  54. return nil, err
  55. }
  56. return &RemoteAllowList{AllowList: al, insideAllowLists: remoteAllowRanges}, nil
  57. }
  58. // If the handleKey func returns true, the rest of the parsing is skipped
  59. // for this key. This allows parsing of special values like `interfaces`.
  60. func newAllowListFromConfig(c *config.C, k string, handleKey func(key string, value any) (bool, error)) (*AllowList, error) {
  61. r := c.Get(k)
  62. if r == nil {
  63. return nil, nil
  64. }
  65. return newAllowList(k, r, handleKey)
  66. }
  67. // If the handleKey func returns true, the rest of the parsing is skipped
  68. // for this key. This allows parsing of special values like `interfaces`.
  69. func newAllowList(k string, raw any, handleKey func(key string, value any) (bool, error)) (*AllowList, error) {
  70. rawMap, ok := raw.(map[string]any)
  71. if !ok {
  72. return nil, fmt.Errorf("config `%s` has invalid type: %T", k, raw)
  73. }
  74. tree := new(bart.Table[bool])
  75. // Keep track of the rules we have added for both ipv4 and ipv6
  76. type allowListRules struct {
  77. firstValue bool
  78. allValuesMatch bool
  79. defaultSet bool
  80. allValues bool
  81. }
  82. rules4 := allowListRules{firstValue: true, allValuesMatch: true, defaultSet: false}
  83. rules6 := allowListRules{firstValue: true, allValuesMatch: true, defaultSet: false}
  84. for rawCIDR, rawValue := range rawMap {
  85. if handleKey != nil {
  86. handled, err := handleKey(rawCIDR, rawValue)
  87. if err != nil {
  88. return nil, err
  89. }
  90. if handled {
  91. continue
  92. }
  93. }
  94. value, ok := config.AsBool(rawValue)
  95. if !ok {
  96. return nil, fmt.Errorf("config `%s` has invalid value (type %T): %v", k, rawValue, rawValue)
  97. }
  98. ipNet, err := netip.ParsePrefix(rawCIDR)
  99. if err != nil {
  100. return nil, fmt.Errorf("config `%s` has invalid CIDR: %s. %w", k, rawCIDR, err)
  101. }
  102. ipNet = netip.PrefixFrom(ipNet.Addr().Unmap(), ipNet.Bits())
  103. tree.Insert(ipNet, value)
  104. maskBits := ipNet.Bits()
  105. var rules *allowListRules
  106. if ipNet.Addr().Is4() {
  107. rules = &rules4
  108. } else {
  109. rules = &rules6
  110. }
  111. if rules.firstValue {
  112. rules.allValues = value
  113. rules.firstValue = false
  114. } else {
  115. if value != rules.allValues {
  116. rules.allValuesMatch = false
  117. }
  118. }
  119. // Check if this is 0.0.0.0/0 or ::/0
  120. if maskBits == 0 {
  121. rules.defaultSet = true
  122. }
  123. }
  124. if !rules4.defaultSet {
  125. if rules4.allValuesMatch {
  126. tree.Insert(netip.PrefixFrom(netip.IPv4Unspecified(), 0), !rules4.allValues)
  127. } else {
  128. return nil, fmt.Errorf("config `%s` contains both true and false rules, but no default set for 0.0.0.0/0", k)
  129. }
  130. }
  131. if !rules6.defaultSet {
  132. if rules6.allValuesMatch {
  133. tree.Insert(netip.PrefixFrom(netip.IPv6Unspecified(), 0), !rules6.allValues)
  134. } else {
  135. return nil, fmt.Errorf("config `%s` contains both true and false rules, but no default set for ::/0", k)
  136. }
  137. }
  138. return &AllowList{cidrTree: tree}, nil
  139. }
  140. func getAllowListInterfaces(k string, v any) ([]AllowListNameRule, error) {
  141. var nameRules []AllowListNameRule
  142. rawRules, ok := v.(map[string]any)
  143. if !ok {
  144. return nil, fmt.Errorf("config `%s.interfaces` is invalid (type %T): %v", k, v, v)
  145. }
  146. firstEntry := true
  147. var allValues bool
  148. for name, rawAllow := range rawRules {
  149. allow, ok := config.AsBool(rawAllow)
  150. if !ok {
  151. return nil, fmt.Errorf("config `%s.interfaces` has invalid value (type %T): %v", k, rawAllow, rawAllow)
  152. }
  153. nameRE, err := regexp.Compile("^" + name + "$")
  154. if err != nil {
  155. return nil, fmt.Errorf("config `%s.interfaces` has invalid key: %s: %v", k, name, err)
  156. }
  157. nameRules = append(nameRules, AllowListNameRule{
  158. Name: nameRE,
  159. Allow: allow,
  160. })
  161. if firstEntry {
  162. allValues = allow
  163. firstEntry = false
  164. } else {
  165. if allow != allValues {
  166. return nil, fmt.Errorf("config `%s.interfaces` values must all be the same true/false value", k)
  167. }
  168. }
  169. }
  170. return nameRules, nil
  171. }
  172. func getRemoteAllowRanges(c *config.C, k string) (*bart.Table[*AllowList], error) {
  173. value := c.Get(k)
  174. if value == nil {
  175. return nil, nil
  176. }
  177. remoteAllowRanges := new(bart.Table[*AllowList])
  178. rawMap, ok := value.(map[string]any)
  179. if !ok {
  180. return nil, fmt.Errorf("config `%s` has invalid type: %T", k, value)
  181. }
  182. for rawCIDR, rawValue := range rawMap {
  183. allowList, err := newAllowList(fmt.Sprintf("%s.%s", k, rawCIDR), rawValue, nil)
  184. if err != nil {
  185. return nil, err
  186. }
  187. ipNet, err := netip.ParsePrefix(rawCIDR)
  188. if err != nil {
  189. return nil, fmt.Errorf("config `%s` has invalid CIDR: %s. %w", k, rawCIDR, err)
  190. }
  191. remoteAllowRanges.Insert(netip.PrefixFrom(ipNet.Addr().Unmap(), ipNet.Bits()), allowList)
  192. }
  193. return remoteAllowRanges, nil
  194. }
  195. func (al *AllowList) Allow(addr netip.Addr) bool {
  196. if al == nil {
  197. return true
  198. }
  199. result, _ := al.cidrTree.Lookup(addr)
  200. return result
  201. }
  202. func (al *LocalAllowList) Allow(udpAddr netip.Addr) bool {
  203. if al == nil {
  204. return true
  205. }
  206. return al.AllowList.Allow(udpAddr)
  207. }
  208. func (al *LocalAllowList) AllowName(name string) bool {
  209. if al == nil || len(al.nameRules) == 0 {
  210. return true
  211. }
  212. for _, rule := range al.nameRules {
  213. if rule.Name.MatchString(name) {
  214. return rule.Allow
  215. }
  216. }
  217. // If no rules match, return the default, which is the inverse of the rules
  218. return !al.nameRules[0].Allow
  219. }
  220. func (al *RemoteAllowList) AllowUnknownVpnAddr(vpnAddr netip.Addr) bool {
  221. if al == nil {
  222. return true
  223. }
  224. return al.AllowList.Allow(vpnAddr)
  225. }
  226. func (al *RemoteAllowList) Allow(vpnAddr netip.Addr, udpAddr netip.Addr) bool {
  227. if !al.getInsideAllowList(vpnAddr).Allow(udpAddr) {
  228. return false
  229. }
  230. return al.AllowList.Allow(udpAddr)
  231. }
  232. func (al *RemoteAllowList) AllowAll(vpnAddrs []netip.Addr, udpAddr netip.Addr) bool {
  233. if !al.AllowList.Allow(udpAddr) {
  234. return false
  235. }
  236. for _, vpnAddr := range vpnAddrs {
  237. if !al.getInsideAllowList(vpnAddr).Allow(udpAddr) {
  238. return false
  239. }
  240. }
  241. return true
  242. }
  243. func (al *RemoteAllowList) getInsideAllowList(vpnAddr netip.Addr) *AllowList {
  244. if al.insideAllowLists != nil {
  245. inside, ok := al.insideAllowLists.Lookup(vpnAddr)
  246. if ok {
  247. return inside
  248. }
  249. }
  250. return nil
  251. }