route_test.go 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. package overlay
  2. import (
  3. "fmt"
  4. "net"
  5. "testing"
  6. "github.com/slackhq/nebula/config"
  7. "github.com/slackhq/nebula/iputil"
  8. "github.com/slackhq/nebula/test"
  9. "github.com/stretchr/testify/assert"
  10. )
  11. func Test_parseRoutes(t *testing.T) {
  12. l := test.NewLogger()
  13. c := config.NewC(l)
  14. _, n, _ := net.ParseCIDR("10.0.0.0/24")
  15. // test no routes config
  16. routes, err := parseRoutes(c, n)
  17. assert.Nil(t, err)
  18. assert.Len(t, routes, 0)
  19. // not an array
  20. c.Settings["tun"] = map[interface{}]interface{}{"routes": "hi"}
  21. routes, err = parseRoutes(c, n)
  22. assert.Nil(t, routes)
  23. assert.EqualError(t, err, "tun.routes is not an array")
  24. // no routes
  25. c.Settings["tun"] = map[interface{}]interface{}{"routes": []interface{}{}}
  26. routes, err = parseRoutes(c, n)
  27. assert.Nil(t, err)
  28. assert.Len(t, routes, 0)
  29. // weird route
  30. c.Settings["tun"] = map[interface{}]interface{}{"routes": []interface{}{"asdf"}}
  31. routes, err = parseRoutes(c, n)
  32. assert.Nil(t, routes)
  33. assert.EqualError(t, err, "entry 1 in tun.routes is invalid")
  34. // no mtu
  35. c.Settings["tun"] = map[interface{}]interface{}{"routes": []interface{}{map[interface{}]interface{}{}}}
  36. routes, err = parseRoutes(c, n)
  37. assert.Nil(t, routes)
  38. assert.EqualError(t, err, "entry 1.mtu in tun.routes is not present")
  39. // bad mtu
  40. c.Settings["tun"] = map[interface{}]interface{}{"routes": []interface{}{map[interface{}]interface{}{"mtu": "nope"}}}
  41. routes, err = parseRoutes(c, n)
  42. assert.Nil(t, routes)
  43. assert.EqualError(t, err, "entry 1.mtu in tun.routes is not an integer: strconv.Atoi: parsing \"nope\": invalid syntax")
  44. // low mtu
  45. c.Settings["tun"] = map[interface{}]interface{}{"routes": []interface{}{map[interface{}]interface{}{"mtu": "499"}}}
  46. routes, err = parseRoutes(c, n)
  47. assert.Nil(t, routes)
  48. assert.EqualError(t, err, "entry 1.mtu in tun.routes is below 500: 499")
  49. // missing route
  50. c.Settings["tun"] = map[interface{}]interface{}{"routes": []interface{}{map[interface{}]interface{}{"mtu": "500"}}}
  51. routes, err = parseRoutes(c, n)
  52. assert.Nil(t, routes)
  53. assert.EqualError(t, err, "entry 1.route in tun.routes is not present")
  54. // unparsable route
  55. c.Settings["tun"] = map[interface{}]interface{}{"routes": []interface{}{map[interface{}]interface{}{"mtu": "500", "route": "nope"}}}
  56. routes, err = parseRoutes(c, n)
  57. assert.Nil(t, routes)
  58. assert.EqualError(t, err, "entry 1.route in tun.routes failed to parse: invalid CIDR address: nope")
  59. // below network range
  60. c.Settings["tun"] = map[interface{}]interface{}{"routes": []interface{}{map[interface{}]interface{}{"mtu": "500", "route": "1.0.0.0/8"}}}
  61. routes, err = parseRoutes(c, n)
  62. assert.Nil(t, routes)
  63. assert.EqualError(t, err, "entry 1.route in tun.routes is not contained within the network attached to the certificate; route: 1.0.0.0/8, network: 10.0.0.0/24")
  64. // above network range
  65. c.Settings["tun"] = map[interface{}]interface{}{"routes": []interface{}{map[interface{}]interface{}{"mtu": "500", "route": "10.0.1.0/24"}}}
  66. routes, err = parseRoutes(c, n)
  67. assert.Nil(t, routes)
  68. assert.EqualError(t, err, "entry 1.route in tun.routes is not contained within the network attached to the certificate; route: 10.0.1.0/24, network: 10.0.0.0/24")
  69. // happy case
  70. c.Settings["tun"] = map[interface{}]interface{}{"routes": []interface{}{
  71. map[interface{}]interface{}{"mtu": "9000", "route": "10.0.0.0/29"},
  72. map[interface{}]interface{}{"mtu": "8000", "route": "10.0.0.1/32"},
  73. }}
  74. routes, err = parseRoutes(c, n)
  75. assert.Nil(t, err)
  76. assert.Len(t, routes, 2)
  77. tested := 0
  78. for _, r := range routes {
  79. if r.MTU == 8000 {
  80. assert.Equal(t, "10.0.0.1/32", r.Cidr.String())
  81. tested++
  82. } else {
  83. assert.Equal(t, 9000, r.MTU)
  84. assert.Equal(t, "10.0.0.0/29", r.Cidr.String())
  85. tested++
  86. }
  87. }
  88. if tested != 2 {
  89. t.Fatal("Did not see both routes")
  90. }
  91. }
  92. func Test_parseUnsafeRoutes(t *testing.T) {
  93. l := test.NewLogger()
  94. c := config.NewC(l)
  95. _, n, _ := net.ParseCIDR("10.0.0.0/24")
  96. // test no routes config
  97. routes, err := parseUnsafeRoutes(c, n)
  98. assert.Nil(t, err)
  99. assert.Len(t, routes, 0)
  100. // not an array
  101. c.Settings["tun"] = map[interface{}]interface{}{"unsafe_routes": "hi"}
  102. routes, err = parseUnsafeRoutes(c, n)
  103. assert.Nil(t, routes)
  104. assert.EqualError(t, err, "tun.unsafe_routes is not an array")
  105. // no routes
  106. c.Settings["tun"] = map[interface{}]interface{}{"unsafe_routes": []interface{}{}}
  107. routes, err = parseUnsafeRoutes(c, n)
  108. assert.Nil(t, err)
  109. assert.Len(t, routes, 0)
  110. // weird route
  111. c.Settings["tun"] = map[interface{}]interface{}{"unsafe_routes": []interface{}{"asdf"}}
  112. routes, err = parseUnsafeRoutes(c, n)
  113. assert.Nil(t, routes)
  114. assert.EqualError(t, err, "entry 1 in tun.unsafe_routes is invalid")
  115. // no via
  116. c.Settings["tun"] = map[interface{}]interface{}{"unsafe_routes": []interface{}{map[interface{}]interface{}{}}}
  117. routes, err = parseUnsafeRoutes(c, n)
  118. assert.Nil(t, routes)
  119. assert.EqualError(t, err, "entry 1.via in tun.unsafe_routes is not present")
  120. // invalid via
  121. for _, invalidValue := range []interface{}{
  122. 127, false, nil, 1.0, []string{"1", "2"},
  123. } {
  124. c.Settings["tun"] = map[interface{}]interface{}{"unsafe_routes": []interface{}{map[interface{}]interface{}{"via": invalidValue}}}
  125. routes, err = parseUnsafeRoutes(c, n)
  126. assert.Nil(t, routes)
  127. assert.EqualError(t, err, fmt.Sprintf("entry 1.via in tun.unsafe_routes is not a string: found %T", invalidValue))
  128. }
  129. // unparsable via
  130. c.Settings["tun"] = map[interface{}]interface{}{"unsafe_routes": []interface{}{map[interface{}]interface{}{"mtu": "500", "via": "nope"}}}
  131. routes, err = parseUnsafeRoutes(c, n)
  132. assert.Nil(t, routes)
  133. assert.EqualError(t, err, "entry 1.via in tun.unsafe_routes failed to parse address: nope")
  134. // missing route
  135. c.Settings["tun"] = map[interface{}]interface{}{"unsafe_routes": []interface{}{map[interface{}]interface{}{"via": "127.0.0.1", "mtu": "500"}}}
  136. routes, err = parseUnsafeRoutes(c, n)
  137. assert.Nil(t, routes)
  138. assert.EqualError(t, err, "entry 1.route in tun.unsafe_routes is not present")
  139. // unparsable route
  140. c.Settings["tun"] = map[interface{}]interface{}{"unsafe_routes": []interface{}{map[interface{}]interface{}{"via": "127.0.0.1", "mtu": "500", "route": "nope"}}}
  141. routes, err = parseUnsafeRoutes(c, n)
  142. assert.Nil(t, routes)
  143. assert.EqualError(t, err, "entry 1.route in tun.unsafe_routes failed to parse: invalid CIDR address: nope")
  144. // within network range
  145. c.Settings["tun"] = map[interface{}]interface{}{"unsafe_routes": []interface{}{map[interface{}]interface{}{"via": "127.0.0.1", "route": "10.0.0.0/24"}}}
  146. routes, err = parseUnsafeRoutes(c, n)
  147. assert.Nil(t, routes)
  148. assert.EqualError(t, err, "entry 1.route in tun.unsafe_routes is contained within the network attached to the certificate; route: 10.0.0.0/24, network: 10.0.0.0/24")
  149. // below network range
  150. c.Settings["tun"] = map[interface{}]interface{}{"unsafe_routes": []interface{}{map[interface{}]interface{}{"via": "127.0.0.1", "route": "1.0.0.0/8"}}}
  151. routes, err = parseUnsafeRoutes(c, n)
  152. assert.Len(t, routes, 1)
  153. assert.Nil(t, err)
  154. // above network range
  155. c.Settings["tun"] = map[interface{}]interface{}{"unsafe_routes": []interface{}{map[interface{}]interface{}{"via": "127.0.0.1", "route": "10.0.1.0/24"}}}
  156. routes, err = parseUnsafeRoutes(c, n)
  157. assert.Len(t, routes, 1)
  158. assert.Nil(t, err)
  159. // no mtu
  160. c.Settings["tun"] = map[interface{}]interface{}{"unsafe_routes": []interface{}{map[interface{}]interface{}{"via": "127.0.0.1", "route": "1.0.0.0/8"}}}
  161. routes, err = parseUnsafeRoutes(c, n)
  162. assert.Len(t, routes, 1)
  163. assert.Equal(t, 0, routes[0].MTU)
  164. // bad mtu
  165. c.Settings["tun"] = map[interface{}]interface{}{"unsafe_routes": []interface{}{map[interface{}]interface{}{"via": "127.0.0.1", "mtu": "nope"}}}
  166. routes, err = parseUnsafeRoutes(c, n)
  167. assert.Nil(t, routes)
  168. assert.EqualError(t, err, "entry 1.mtu in tun.unsafe_routes is not an integer: strconv.Atoi: parsing \"nope\": invalid syntax")
  169. // low mtu
  170. c.Settings["tun"] = map[interface{}]interface{}{"unsafe_routes": []interface{}{map[interface{}]interface{}{"via": "127.0.0.1", "mtu": "499"}}}
  171. routes, err = parseUnsafeRoutes(c, n)
  172. assert.Nil(t, routes)
  173. assert.EqualError(t, err, "entry 1.mtu in tun.unsafe_routes is below 500: 499")
  174. // happy case
  175. c.Settings["tun"] = map[interface{}]interface{}{"unsafe_routes": []interface{}{
  176. map[interface{}]interface{}{"via": "127.0.0.1", "mtu": "9000", "route": "1.0.0.0/29"},
  177. map[interface{}]interface{}{"via": "127.0.0.1", "mtu": "8000", "route": "1.0.0.1/32"},
  178. map[interface{}]interface{}{"via": "127.0.0.1", "mtu": "1500", "metric": 1234, "route": "1.0.0.2/32"},
  179. }}
  180. routes, err = parseUnsafeRoutes(c, n)
  181. assert.Nil(t, err)
  182. assert.Len(t, routes, 3)
  183. tested := 0
  184. for _, r := range routes {
  185. if r.MTU == 8000 {
  186. assert.Equal(t, "1.0.0.1/32", r.Cidr.String())
  187. tested++
  188. } else if r.MTU == 9000 {
  189. assert.Equal(t, 9000, r.MTU)
  190. assert.Equal(t, "1.0.0.0/29", r.Cidr.String())
  191. tested++
  192. } else {
  193. assert.Equal(t, 1500, r.MTU)
  194. assert.Equal(t, 1234, r.Metric)
  195. assert.Equal(t, "1.0.0.2/32", r.Cidr.String())
  196. tested++
  197. }
  198. }
  199. if tested != 3 {
  200. t.Fatal("Did not see both unsafe_routes")
  201. }
  202. }
  203. func Test_makeRouteTree(t *testing.T) {
  204. l := test.NewLogger()
  205. c := config.NewC(l)
  206. _, n, _ := net.ParseCIDR("10.0.0.0/24")
  207. c.Settings["tun"] = map[interface{}]interface{}{"unsafe_routes": []interface{}{
  208. map[interface{}]interface{}{"via": "192.168.0.1", "route": "1.0.0.0/28"},
  209. map[interface{}]interface{}{"via": "192.168.0.2", "route": "1.0.0.1/32"},
  210. }}
  211. routes, err := parseUnsafeRoutes(c, n)
  212. assert.NoError(t, err)
  213. assert.Len(t, routes, 2)
  214. routeTree, err := makeRouteTree(l, routes, true)
  215. assert.NoError(t, err)
  216. ip := iputil.Ip2VpnIp(net.ParseIP("1.0.0.2"))
  217. r := routeTree.MostSpecificContains(ip)
  218. assert.NotNil(t, r)
  219. assert.IsType(t, iputil.VpnIp(0), r)
  220. assert.EqualValues(t, iputil.Ip2VpnIp(net.ParseIP("192.168.0.1")), r)
  221. ip = iputil.Ip2VpnIp(net.ParseIP("1.0.0.1"))
  222. r = routeTree.MostSpecificContains(ip)
  223. assert.NotNil(t, r)
  224. assert.IsType(t, iputil.VpnIp(0), r)
  225. assert.EqualValues(t, iputil.Ip2VpnIp(net.ParseIP("192.168.0.2")), r)
  226. ip = iputil.Ip2VpnIp(net.ParseIP("1.1.0.1"))
  227. r = routeTree.MostSpecificContains(ip)
  228. assert.Nil(t, r)
  229. }