allow_list.go 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307
  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 interface{}) (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 interface{}) (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 interface{}, handleKey func(key string, value interface{}) (bool, error)) (*AllowList, error) {
  70. rawMap, ok := raw.(map[interface{}]interface{})
  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 rawKey, rawValue := range rawMap {
  85. rawCIDR, ok := rawKey.(string)
  86. if !ok {
  87. return nil, fmt.Errorf("config `%s` has invalid key (type %T): %v", k, rawKey, rawKey)
  88. }
  89. if handleKey != nil {
  90. handled, err := handleKey(rawCIDR, rawValue)
  91. if err != nil {
  92. return nil, err
  93. }
  94. if handled {
  95. continue
  96. }
  97. }
  98. value, ok := rawValue.(bool)
  99. if !ok {
  100. return nil, fmt.Errorf("config `%s` has invalid value (type %T): %v", k, rawValue, rawValue)
  101. }
  102. ipNet, err := netip.ParsePrefix(rawCIDR)
  103. if err != nil {
  104. return nil, fmt.Errorf("config `%s` has invalid CIDR: %s. %w", k, rawCIDR, err)
  105. }
  106. ipNet = netip.PrefixFrom(ipNet.Addr().Unmap(), ipNet.Bits())
  107. // TODO: should we error on duplicate CIDRs in the config?
  108. tree.Insert(ipNet, value)
  109. maskBits := ipNet.Bits()
  110. var rules *allowListRules
  111. if ipNet.Addr().Is4() {
  112. rules = &rules4
  113. } else {
  114. rules = &rules6
  115. }
  116. if rules.firstValue {
  117. rules.allValues = value
  118. rules.firstValue = false
  119. } else {
  120. if value != rules.allValues {
  121. rules.allValuesMatch = false
  122. }
  123. }
  124. // Check if this is 0.0.0.0/0 or ::/0
  125. if maskBits == 0 {
  126. rules.defaultSet = true
  127. }
  128. }
  129. if !rules4.defaultSet {
  130. if rules4.allValuesMatch {
  131. tree.Insert(netip.PrefixFrom(netip.IPv4Unspecified(), 0), !rules4.allValues)
  132. } else {
  133. return nil, fmt.Errorf("config `%s` contains both true and false rules, but no default set for 0.0.0.0/0", k)
  134. }
  135. }
  136. if !rules6.defaultSet {
  137. if rules6.allValuesMatch {
  138. tree.Insert(netip.PrefixFrom(netip.IPv6Unspecified(), 0), !rules6.allValues)
  139. } else {
  140. return nil, fmt.Errorf("config `%s` contains both true and false rules, but no default set for ::/0", k)
  141. }
  142. }
  143. return &AllowList{cidrTree: tree}, nil
  144. }
  145. func getAllowListInterfaces(k string, v interface{}) ([]AllowListNameRule, error) {
  146. var nameRules []AllowListNameRule
  147. rawRules, ok := v.(map[interface{}]interface{})
  148. if !ok {
  149. return nil, fmt.Errorf("config `%s.interfaces` is invalid (type %T): %v", k, v, v)
  150. }
  151. firstEntry := true
  152. var allValues bool
  153. for rawName, rawAllow := range rawRules {
  154. name, ok := rawName.(string)
  155. if !ok {
  156. return nil, fmt.Errorf("config `%s.interfaces` has invalid key (type %T): %v", k, rawName, rawName)
  157. }
  158. allow, ok := rawAllow.(bool)
  159. if !ok {
  160. return nil, fmt.Errorf("config `%s.interfaces` has invalid value (type %T): %v", k, rawAllow, rawAllow)
  161. }
  162. nameRE, err := regexp.Compile("^" + name + "$")
  163. if err != nil {
  164. return nil, fmt.Errorf("config `%s.interfaces` has invalid key: %s: %v", k, name, err)
  165. }
  166. nameRules = append(nameRules, AllowListNameRule{
  167. Name: nameRE,
  168. Allow: allow,
  169. })
  170. if firstEntry {
  171. allValues = allow
  172. firstEntry = false
  173. } else {
  174. if allow != allValues {
  175. return nil, fmt.Errorf("config `%s.interfaces` values must all be the same true/false value", k)
  176. }
  177. }
  178. }
  179. return nameRules, nil
  180. }
  181. func getRemoteAllowRanges(c *config.C, k string) (*bart.Table[*AllowList], error) {
  182. value := c.Get(k)
  183. if value == nil {
  184. return nil, nil
  185. }
  186. remoteAllowRanges := new(bart.Table[*AllowList])
  187. rawMap, ok := value.(map[interface{}]interface{})
  188. if !ok {
  189. return nil, fmt.Errorf("config `%s` has invalid type: %T", k, value)
  190. }
  191. for rawKey, rawValue := range rawMap {
  192. rawCIDR, ok := rawKey.(string)
  193. if !ok {
  194. return nil, fmt.Errorf("config `%s` has invalid key (type %T): %v", k, rawKey, rawKey)
  195. }
  196. allowList, err := newAllowList(fmt.Sprintf("%s.%s", k, rawCIDR), rawValue, nil)
  197. if err != nil {
  198. return nil, err
  199. }
  200. ipNet, err := netip.ParsePrefix(rawCIDR)
  201. if err != nil {
  202. return nil, fmt.Errorf("config `%s` has invalid CIDR: %s. %w", k, rawCIDR, err)
  203. }
  204. remoteAllowRanges.Insert(netip.PrefixFrom(ipNet.Addr().Unmap(), ipNet.Bits()), allowList)
  205. }
  206. return remoteAllowRanges, nil
  207. }
  208. func (al *AllowList) Allow(ip netip.Addr) bool {
  209. if al == nil {
  210. return true
  211. }
  212. result, _ := al.cidrTree.Lookup(ip)
  213. return result
  214. }
  215. func (al *LocalAllowList) Allow(ip netip.Addr) bool {
  216. if al == nil {
  217. return true
  218. }
  219. return al.AllowList.Allow(ip)
  220. }
  221. func (al *LocalAllowList) AllowName(name string) bool {
  222. if al == nil || len(al.nameRules) == 0 {
  223. return true
  224. }
  225. for _, rule := range al.nameRules {
  226. if rule.Name.MatchString(name) {
  227. return rule.Allow
  228. }
  229. }
  230. // If no rules match, return the default, which is the inverse of the rules
  231. return !al.nameRules[0].Allow
  232. }
  233. func (al *RemoteAllowList) AllowUnknownVpnIp(ip netip.Addr) bool {
  234. if al == nil {
  235. return true
  236. }
  237. return al.AllowList.Allow(ip)
  238. }
  239. func (al *RemoteAllowList) Allow(vpnIp netip.Addr, ip netip.Addr) bool {
  240. if !al.getInsideAllowList(vpnIp).Allow(ip) {
  241. return false
  242. }
  243. return al.AllowList.Allow(ip)
  244. }
  245. func (al *RemoteAllowList) getInsideAllowList(vpnIp netip.Addr) *AllowList {
  246. if al.insideAllowLists != nil {
  247. inside, ok := al.insideAllowLists.Lookup(vpnIp)
  248. if ok {
  249. return inside
  250. }
  251. }
  252. return nil
  253. }