3
0

allow_list.go 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. package nebula
  2. import (
  3. "fmt"
  4. "net"
  5. "regexp"
  6. "github.com/slackhq/nebula/cidr"
  7. "github.com/slackhq/nebula/config"
  8. "github.com/slackhq/nebula/iputil"
  9. )
  10. type AllowList struct {
  11. // The values of this cidrTree are `bool`, signifying allow/deny
  12. cidrTree *cidr.Tree6[bool]
  13. }
  14. type RemoteAllowList struct {
  15. AllowList *AllowList
  16. // Inside Range Specific, keys of this tree are inside CIDRs and values
  17. // are *AllowList
  18. insideAllowLists *cidr.Tree6[*AllowList]
  19. }
  20. type LocalAllowList struct {
  21. AllowList *AllowList
  22. // To avoid ambiguity, all rules must be true, or all rules must be false.
  23. nameRules []AllowListNameRule
  24. }
  25. type AllowListNameRule struct {
  26. Name *regexp.Regexp
  27. Allow bool
  28. }
  29. func NewLocalAllowListFromConfig(c *config.C, k string) (*LocalAllowList, error) {
  30. var nameRules []AllowListNameRule
  31. handleKey := func(key string, value interface{}) (bool, error) {
  32. if key == "interfaces" {
  33. var err error
  34. nameRules, err = getAllowListInterfaces(k, value)
  35. if err != nil {
  36. return false, err
  37. }
  38. return true, nil
  39. }
  40. return false, nil
  41. }
  42. al, err := newAllowListFromConfig(c, k, handleKey)
  43. if err != nil {
  44. return nil, err
  45. }
  46. return &LocalAllowList{AllowList: al, nameRules: nameRules}, nil
  47. }
  48. func NewRemoteAllowListFromConfig(c *config.C, k, rangesKey string) (*RemoteAllowList, error) {
  49. al, err := newAllowListFromConfig(c, k, nil)
  50. if err != nil {
  51. return nil, err
  52. }
  53. remoteAllowRanges, err := getRemoteAllowRanges(c, rangesKey)
  54. if err != nil {
  55. return nil, err
  56. }
  57. return &RemoteAllowList{AllowList: al, insideAllowLists: remoteAllowRanges}, nil
  58. }
  59. // If the handleKey func returns true, the rest of the parsing is skipped
  60. // for this key. This allows parsing of special values like `interfaces`.
  61. func newAllowListFromConfig(c *config.C, k string, handleKey func(key string, value interface{}) (bool, error)) (*AllowList, error) {
  62. r := c.Get(k)
  63. if r == nil {
  64. return nil, nil
  65. }
  66. return newAllowList(k, r, handleKey)
  67. }
  68. // If the handleKey func returns true, the rest of the parsing is skipped
  69. // for this key. This allows parsing of special values like `interfaces`.
  70. func newAllowList(k string, raw interface{}, handleKey func(key string, value interface{}) (bool, error)) (*AllowList, error) {
  71. rawMap, ok := raw.(map[interface{}]interface{})
  72. if !ok {
  73. return nil, fmt.Errorf("config `%s` has invalid type: %T", k, raw)
  74. }
  75. tree := cidr.NewTree6[bool]()
  76. // Keep track of the rules we have added for both ipv4 and ipv6
  77. type allowListRules struct {
  78. firstValue bool
  79. allValuesMatch bool
  80. defaultSet bool
  81. allValues bool
  82. }
  83. rules4 := allowListRules{firstValue: true, allValuesMatch: true, defaultSet: false}
  84. rules6 := allowListRules{firstValue: true, allValuesMatch: true, defaultSet: false}
  85. for rawKey, rawValue := range rawMap {
  86. rawCIDR, ok := rawKey.(string)
  87. if !ok {
  88. return nil, fmt.Errorf("config `%s` has invalid key (type %T): %v", k, rawKey, rawKey)
  89. }
  90. if handleKey != nil {
  91. handled, err := handleKey(rawCIDR, rawValue)
  92. if err != nil {
  93. return nil, err
  94. }
  95. if handled {
  96. continue
  97. }
  98. }
  99. value, ok := rawValue.(bool)
  100. if !ok {
  101. return nil, fmt.Errorf("config `%s` has invalid value (type %T): %v", k, rawValue, rawValue)
  102. }
  103. _, ipNet, err := net.ParseCIDR(rawCIDR)
  104. if err != nil {
  105. return nil, fmt.Errorf("config `%s` has invalid CIDR: %s", k, rawCIDR)
  106. }
  107. // TODO: should we error on duplicate CIDRs in the config?
  108. tree.AddCIDR(ipNet, value)
  109. maskBits, maskSize := ipNet.Mask.Size()
  110. var rules *allowListRules
  111. if maskSize == 32 {
  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. _, zeroCIDR, _ := net.ParseCIDR("0.0.0.0/0")
  132. tree.AddCIDR(zeroCIDR, !rules4.allValues)
  133. } else {
  134. return nil, fmt.Errorf("config `%s` contains both true and false rules, but no default set for 0.0.0.0/0", k)
  135. }
  136. }
  137. if !rules6.defaultSet {
  138. if rules6.allValuesMatch {
  139. _, zeroCIDR, _ := net.ParseCIDR("::/0")
  140. tree.AddCIDR(zeroCIDR, !rules6.allValues)
  141. } else {
  142. return nil, fmt.Errorf("config `%s` contains both true and false rules, but no default set for ::/0", k)
  143. }
  144. }
  145. return &AllowList{cidrTree: tree}, nil
  146. }
  147. func getAllowListInterfaces(k string, v interface{}) ([]AllowListNameRule, error) {
  148. var nameRules []AllowListNameRule
  149. rawRules, ok := v.(map[interface{}]interface{})
  150. if !ok {
  151. return nil, fmt.Errorf("config `%s.interfaces` is invalid (type %T): %v", k, v, v)
  152. }
  153. firstEntry := true
  154. var allValues bool
  155. for rawName, rawAllow := range rawRules {
  156. name, ok := rawName.(string)
  157. if !ok {
  158. return nil, fmt.Errorf("config `%s.interfaces` has invalid key (type %T): %v", k, rawName, rawName)
  159. }
  160. allow, ok := rawAllow.(bool)
  161. if !ok {
  162. return nil, fmt.Errorf("config `%s.interfaces` has invalid value (type %T): %v", k, rawAllow, rawAllow)
  163. }
  164. nameRE, err := regexp.Compile("^" + name + "$")
  165. if err != nil {
  166. return nil, fmt.Errorf("config `%s.interfaces` has invalid key: %s: %v", k, name, err)
  167. }
  168. nameRules = append(nameRules, AllowListNameRule{
  169. Name: nameRE,
  170. Allow: allow,
  171. })
  172. if firstEntry {
  173. allValues = allow
  174. firstEntry = false
  175. } else {
  176. if allow != allValues {
  177. return nil, fmt.Errorf("config `%s.interfaces` values must all be the same true/false value", k)
  178. }
  179. }
  180. }
  181. return nameRules, nil
  182. }
  183. func getRemoteAllowRanges(c *config.C, k string) (*cidr.Tree6[*AllowList], error) {
  184. value := c.Get(k)
  185. if value == nil {
  186. return nil, nil
  187. }
  188. remoteAllowRanges := cidr.NewTree6[*AllowList]()
  189. rawMap, ok := value.(map[interface{}]interface{})
  190. if !ok {
  191. return nil, fmt.Errorf("config `%s` has invalid type: %T", k, value)
  192. }
  193. for rawKey, rawValue := range rawMap {
  194. rawCIDR, ok := rawKey.(string)
  195. if !ok {
  196. return nil, fmt.Errorf("config `%s` has invalid key (type %T): %v", k, rawKey, rawKey)
  197. }
  198. allowList, err := newAllowList(fmt.Sprintf("%s.%s", k, rawCIDR), rawValue, nil)
  199. if err != nil {
  200. return nil, err
  201. }
  202. _, ipNet, err := net.ParseCIDR(rawCIDR)
  203. if err != nil {
  204. return nil, fmt.Errorf("config `%s` has invalid CIDR: %s", k, rawCIDR)
  205. }
  206. remoteAllowRanges.AddCIDR(ipNet, allowList)
  207. }
  208. return remoteAllowRanges, nil
  209. }
  210. func (al *AllowList) Allow(ip net.IP) bool {
  211. if al == nil {
  212. return true
  213. }
  214. _, result := al.cidrTree.MostSpecificContains(ip)
  215. return result
  216. }
  217. func (al *AllowList) AllowIpV4(ip iputil.VpnIp) bool {
  218. if al == nil {
  219. return true
  220. }
  221. _, result := al.cidrTree.MostSpecificContainsIpV4(ip)
  222. return result
  223. }
  224. func (al *AllowList) AllowIpV6(hi, lo uint64) bool {
  225. if al == nil {
  226. return true
  227. }
  228. _, result := al.cidrTree.MostSpecificContainsIpV6(hi, lo)
  229. return result
  230. }
  231. func (al *LocalAllowList) Allow(ip net.IP) bool {
  232. if al == nil {
  233. return true
  234. }
  235. return al.AllowList.Allow(ip)
  236. }
  237. func (al *LocalAllowList) AllowName(name string) bool {
  238. if al == nil || len(al.nameRules) == 0 {
  239. return true
  240. }
  241. for _, rule := range al.nameRules {
  242. if rule.Name.MatchString(name) {
  243. return rule.Allow
  244. }
  245. }
  246. // If no rules match, return the default, which is the inverse of the rules
  247. return !al.nameRules[0].Allow
  248. }
  249. func (al *RemoteAllowList) AllowUnknownVpnIp(ip net.IP) bool {
  250. if al == nil {
  251. return true
  252. }
  253. return al.AllowList.Allow(ip)
  254. }
  255. func (al *RemoteAllowList) Allow(vpnIp iputil.VpnIp, ip net.IP) bool {
  256. if !al.getInsideAllowList(vpnIp).Allow(ip) {
  257. return false
  258. }
  259. return al.AllowList.Allow(ip)
  260. }
  261. func (al *RemoteAllowList) AllowIpV4(vpnIp iputil.VpnIp, ip iputil.VpnIp) bool {
  262. if al == nil {
  263. return true
  264. }
  265. if !al.getInsideAllowList(vpnIp).AllowIpV4(ip) {
  266. return false
  267. }
  268. return al.AllowList.AllowIpV4(ip)
  269. }
  270. func (al *RemoteAllowList) AllowIpV6(vpnIp iputil.VpnIp, hi, lo uint64) bool {
  271. if al == nil {
  272. return true
  273. }
  274. if !al.getInsideAllowList(vpnIp).AllowIpV6(hi, lo) {
  275. return false
  276. }
  277. return al.AllowList.AllowIpV6(hi, lo)
  278. }
  279. func (al *RemoteAllowList) getInsideAllowList(vpnIp iputil.VpnIp) *AllowList {
  280. if al.insideAllowLists != nil {
  281. ok, inside := al.insideAllowLists.MostSpecificContainsIpV4(vpnIp)
  282. if ok {
  283. return inside
  284. }
  285. }
  286. return nil
  287. }