allow_list.go 7.7 KB

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