topology_test.go 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935
  1. // Copyright 2019 the Kilo authors
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. package mesh
  15. import (
  16. "net"
  17. "testing"
  18. "time"
  19. "github.com/go-kit/kit/log"
  20. "github.com/kylelemons/godebug/pretty"
  21. "golang.zx2c4.com/wireguard/wgctrl/wgtypes"
  22. "github.com/squat/kilo/pkg/wireguard"
  23. )
  24. func mustParseCIDR(s string) (r net.IPNet) {
  25. if _, ip, err := net.ParseCIDR(s); err != nil {
  26. panic("failed to parse CIDR")
  27. } else {
  28. r = *ip
  29. }
  30. return
  31. }
  32. var (
  33. key1 = wgtypes.Key{'k', 'e', 'y', '1'}
  34. key2 = wgtypes.Key{'k', 'e', 'y', '2'}
  35. key3 = wgtypes.Key{'k', 'e', 'y', '3'}
  36. key4 = wgtypes.Key{'k', 'e', 'y', '4'}
  37. key5 = wgtypes.Key{'k', 'e', 'y', '5'}
  38. )
  39. func setup(t *testing.T) (map[string]*Node, map[string]*Peer, wgtypes.Key, int) {
  40. key := wgtypes.Key{'p', 'r', 'i', 'v'}
  41. e1 := &net.IPNet{IP: net.ParseIP("10.1.0.1").To4(), Mask: net.CIDRMask(16, 32)}
  42. e2 := &net.IPNet{IP: net.ParseIP("10.1.0.2").To4(), Mask: net.CIDRMask(16, 32)}
  43. e3 := &net.IPNet{IP: net.ParseIP("10.1.0.3").To4(), Mask: net.CIDRMask(16, 32)}
  44. e4 := &net.IPNet{IP: net.ParseIP("10.1.0.4").To4(), Mask: net.CIDRMask(16, 32)}
  45. i1 := &net.IPNet{IP: net.ParseIP("192.168.0.1").To4(), Mask: net.CIDRMask(32, 32)}
  46. i2 := &net.IPNet{IP: net.ParseIP("192.168.0.2").To4(), Mask: net.CIDRMask(32, 32)}
  47. i3 := &net.IPNet{IP: net.ParseIP("192.168.178.3").To4(), Mask: net.CIDRMask(32, 32)}
  48. nodes := map[string]*Node{
  49. "a": {
  50. Name: "a",
  51. Endpoint: wireguard.NewEndpoint(e1.IP, DefaultKiloPort),
  52. InternalIP: i1,
  53. Location: "1",
  54. Subnet: &net.IPNet{IP: net.ParseIP("10.2.1.0"), Mask: net.CIDRMask(24, 32)},
  55. Key: key1,
  56. PersistentKeepalive: 25,
  57. },
  58. "b": {
  59. Name: "b",
  60. Endpoint: wireguard.NewEndpoint(e2.IP, DefaultKiloPort),
  61. InternalIP: i1,
  62. Location: "2",
  63. Subnet: &net.IPNet{IP: net.ParseIP("10.2.2.0"), Mask: net.CIDRMask(24, 32)},
  64. Key: key2,
  65. AllowedLocationIPs: []net.IPNet{*i3},
  66. },
  67. "c": {
  68. Name: "c",
  69. Endpoint: wireguard.NewEndpoint(e3.IP, DefaultKiloPort),
  70. InternalIP: i2,
  71. // Same location as node b.
  72. Location: "2",
  73. Subnet: &net.IPNet{IP: net.ParseIP("10.2.3.0"), Mask: net.CIDRMask(24, 32)},
  74. Key: key3,
  75. },
  76. "d": {
  77. Name: "d",
  78. Endpoint: wireguard.NewEndpoint(e4.IP, DefaultKiloPort),
  79. // Same location as node a, but without private IP
  80. Location: "1",
  81. Subnet: &net.IPNet{IP: net.ParseIP("10.2.4.0"), Mask: net.CIDRMask(24, 32)},
  82. Key: key4,
  83. },
  84. }
  85. peers := map[string]*Peer{
  86. "a": {
  87. Name: "a",
  88. Peer: wireguard.Peer{
  89. PeerConfig: wgtypes.PeerConfig{
  90. AllowedIPs: []net.IPNet{
  91. {IP: net.ParseIP("10.5.0.1"), Mask: net.CIDRMask(24, 32)},
  92. {IP: net.ParseIP("10.5.0.2"), Mask: net.CIDRMask(24, 32)},
  93. },
  94. PublicKey: key4,
  95. },
  96. },
  97. },
  98. "b": {
  99. Name: "b",
  100. Peer: wireguard.Peer{
  101. PeerConfig: wgtypes.PeerConfig{
  102. AllowedIPs: []net.IPNet{
  103. {IP: net.ParseIP("10.5.0.3"), Mask: net.CIDRMask(24, 32)},
  104. },
  105. PublicKey: key5,
  106. },
  107. Endpoint: wireguard.NewEndpoint(net.ParseIP("192.168.0.1"), DefaultKiloPort),
  108. },
  109. },
  110. }
  111. return nodes, peers, key, DefaultKiloPort
  112. }
  113. func TestNewTopology(t *testing.T) {
  114. nodes, peers, key, port := setup(t)
  115. w1 := net.ParseIP("10.4.0.1").To4()
  116. w2 := net.ParseIP("10.4.0.2").To4()
  117. w3 := net.ParseIP("10.4.0.3").To4()
  118. w4 := net.ParseIP("10.4.0.4").To4()
  119. for _, tc := range []struct {
  120. name string
  121. granularity Granularity
  122. hostname string
  123. result *Topology
  124. }{
  125. {
  126. name: "logical from a",
  127. granularity: LogicalGranularity,
  128. hostname: nodes["a"].Name,
  129. result: &Topology{
  130. hostname: nodes["a"].Name,
  131. leader: true,
  132. location: logicalLocationPrefix + nodes["a"].Location,
  133. subnet: nodes["a"].Subnet,
  134. privateIP: nodes["a"].InternalIP,
  135. wireGuardCIDR: &net.IPNet{IP: w1, Mask: net.CIDRMask(16, 32)},
  136. segments: []*segment{
  137. {
  138. allowedIPs: []net.IPNet{*nodes["a"].Subnet, *nodes["a"].InternalIP, {IP: w1, Mask: net.CIDRMask(32, 32)}},
  139. endpoint: nodes["a"].Endpoint,
  140. key: nodes["a"].Key,
  141. persistentKeepalive: nodes["a"].PersistentKeepalive,
  142. location: logicalLocationPrefix + nodes["a"].Location,
  143. cidrs: []*net.IPNet{nodes["a"].Subnet},
  144. hostnames: []string{"a"},
  145. privateIPs: []net.IP{nodes["a"].InternalIP.IP},
  146. wireGuardIP: w1,
  147. },
  148. {
  149. allowedIPs: []net.IPNet{*nodes["b"].Subnet, *nodes["b"].InternalIP, *nodes["c"].Subnet, *nodes["c"].InternalIP, {IP: w2, Mask: net.CIDRMask(32, 32)}},
  150. endpoint: nodes["b"].Endpoint,
  151. key: nodes["b"].Key,
  152. persistentKeepalive: nodes["b"].PersistentKeepalive,
  153. location: logicalLocationPrefix + nodes["b"].Location,
  154. cidrs: []*net.IPNet{nodes["b"].Subnet, nodes["c"].Subnet},
  155. hostnames: []string{"b", "c"},
  156. privateIPs: []net.IP{nodes["b"].InternalIP.IP, nodes["c"].InternalIP.IP},
  157. wireGuardIP: w2,
  158. allowedLocationIPs: nodes["b"].AllowedLocationIPs,
  159. },
  160. {
  161. allowedIPs: []net.IPNet{*nodes["d"].Subnet, {IP: w3, Mask: net.CIDRMask(32, 32)}},
  162. endpoint: nodes["d"].Endpoint,
  163. key: nodes["d"].Key,
  164. persistentKeepalive: nodes["d"].PersistentKeepalive,
  165. location: nodeLocationPrefix + nodes["d"].Name,
  166. cidrs: []*net.IPNet{nodes["d"].Subnet},
  167. hostnames: []string{"d"},
  168. privateIPs: nil,
  169. wireGuardIP: w3,
  170. },
  171. },
  172. peers: []*Peer{peers["a"], peers["b"]},
  173. logger: log.NewNopLogger(),
  174. },
  175. },
  176. {
  177. name: "logical from b",
  178. granularity: LogicalGranularity,
  179. hostname: nodes["b"].Name,
  180. result: &Topology{
  181. hostname: nodes["b"].Name,
  182. leader: true,
  183. location: logicalLocationPrefix + nodes["b"].Location,
  184. subnet: nodes["b"].Subnet,
  185. privateIP: nodes["b"].InternalIP,
  186. wireGuardCIDR: &net.IPNet{IP: w2, Mask: net.CIDRMask(16, 32)},
  187. segments: []*segment{
  188. {
  189. allowedIPs: []net.IPNet{*nodes["a"].Subnet, *nodes["a"].InternalIP, {IP: w1, Mask: net.CIDRMask(32, 32)}},
  190. endpoint: nodes["a"].Endpoint,
  191. key: nodes["a"].Key,
  192. persistentKeepalive: nodes["a"].PersistentKeepalive,
  193. location: logicalLocationPrefix + nodes["a"].Location,
  194. cidrs: []*net.IPNet{nodes["a"].Subnet},
  195. hostnames: []string{"a"},
  196. privateIPs: []net.IP{nodes["a"].InternalIP.IP},
  197. wireGuardIP: w1,
  198. },
  199. {
  200. allowedIPs: []net.IPNet{*nodes["b"].Subnet, *nodes["b"].InternalIP, *nodes["c"].Subnet, *nodes["c"].InternalIP, {IP: w2, Mask: net.CIDRMask(32, 32)}},
  201. endpoint: nodes["b"].Endpoint,
  202. key: nodes["b"].Key,
  203. persistentKeepalive: nodes["b"].PersistentKeepalive,
  204. location: logicalLocationPrefix + nodes["b"].Location,
  205. cidrs: []*net.IPNet{nodes["b"].Subnet, nodes["c"].Subnet},
  206. hostnames: []string{"b", "c"},
  207. privateIPs: []net.IP{nodes["b"].InternalIP.IP, nodes["c"].InternalIP.IP},
  208. wireGuardIP: w2,
  209. allowedLocationIPs: nodes["b"].AllowedLocationIPs,
  210. },
  211. {
  212. allowedIPs: []net.IPNet{*nodes["d"].Subnet, {IP: w3, Mask: net.CIDRMask(32, 32)}},
  213. endpoint: nodes["d"].Endpoint,
  214. key: nodes["d"].Key,
  215. persistentKeepalive: nodes["d"].PersistentKeepalive,
  216. location: nodeLocationPrefix + nodes["d"].Name,
  217. cidrs: []*net.IPNet{nodes["d"].Subnet},
  218. hostnames: []string{"d"},
  219. privateIPs: nil,
  220. wireGuardIP: w3,
  221. },
  222. },
  223. peers: []*Peer{peers["a"], peers["b"]},
  224. logger: log.NewNopLogger(),
  225. },
  226. },
  227. {
  228. name: "logical from c",
  229. granularity: LogicalGranularity,
  230. hostname: nodes["c"].Name,
  231. result: &Topology{
  232. hostname: nodes["c"].Name,
  233. leader: false,
  234. location: logicalLocationPrefix + nodes["b"].Location,
  235. subnet: nodes["c"].Subnet,
  236. privateIP: nodes["c"].InternalIP,
  237. wireGuardCIDR: DefaultKiloSubnet,
  238. segments: []*segment{
  239. {
  240. allowedIPs: []net.IPNet{*nodes["a"].Subnet, *nodes["a"].InternalIP, {IP: w1, Mask: net.CIDRMask(32, 32)}},
  241. endpoint: nodes["a"].Endpoint,
  242. key: nodes["a"].Key,
  243. persistentKeepalive: nodes["a"].PersistentKeepalive,
  244. location: logicalLocationPrefix + nodes["a"].Location,
  245. cidrs: []*net.IPNet{nodes["a"].Subnet},
  246. hostnames: []string{"a"},
  247. privateIPs: []net.IP{nodes["a"].InternalIP.IP},
  248. wireGuardIP: w1,
  249. },
  250. {
  251. allowedIPs: []net.IPNet{*nodes["b"].Subnet, *nodes["b"].InternalIP, *nodes["c"].Subnet, *nodes["c"].InternalIP, {IP: w2, Mask: net.CIDRMask(32, 32)}},
  252. endpoint: nodes["b"].Endpoint,
  253. key: nodes["b"].Key,
  254. persistentKeepalive: nodes["b"].PersistentKeepalive,
  255. location: logicalLocationPrefix + nodes["b"].Location,
  256. cidrs: []*net.IPNet{nodes["b"].Subnet, nodes["c"].Subnet},
  257. hostnames: []string{"b", "c"},
  258. privateIPs: []net.IP{nodes["b"].InternalIP.IP, nodes["c"].InternalIP.IP},
  259. wireGuardIP: w2,
  260. allowedLocationIPs: nodes["b"].AllowedLocationIPs,
  261. },
  262. {
  263. allowedIPs: []net.IPNet{*nodes["d"].Subnet, {IP: w3, Mask: net.CIDRMask(32, 32)}},
  264. endpoint: nodes["d"].Endpoint,
  265. key: nodes["d"].Key,
  266. persistentKeepalive: nodes["d"].PersistentKeepalive,
  267. location: nodeLocationPrefix + nodes["d"].Name,
  268. cidrs: []*net.IPNet{nodes["d"].Subnet},
  269. hostnames: []string{"d"},
  270. privateIPs: nil,
  271. wireGuardIP: w3,
  272. },
  273. },
  274. peers: []*Peer{peers["a"], peers["b"]},
  275. logger: log.NewNopLogger(),
  276. },
  277. },
  278. {
  279. name: "full from a",
  280. granularity: FullGranularity,
  281. hostname: nodes["a"].Name,
  282. result: &Topology{
  283. hostname: nodes["a"].Name,
  284. leader: true,
  285. location: nodeLocationPrefix + nodes["a"].Name,
  286. subnet: nodes["a"].Subnet,
  287. privateIP: nodes["a"].InternalIP,
  288. wireGuardCIDR: &net.IPNet{IP: w1, Mask: net.CIDRMask(16, 32)},
  289. segments: []*segment{
  290. {
  291. allowedIPs: []net.IPNet{*nodes["a"].Subnet, *nodes["a"].InternalIP, {IP: w1, Mask: net.CIDRMask(32, 32)}},
  292. endpoint: nodes["a"].Endpoint,
  293. key: nodes["a"].Key,
  294. persistentKeepalive: nodes["a"].PersistentKeepalive,
  295. location: nodeLocationPrefix + nodes["a"].Name,
  296. cidrs: []*net.IPNet{nodes["a"].Subnet},
  297. hostnames: []string{"a"},
  298. privateIPs: []net.IP{nodes["a"].InternalIP.IP},
  299. wireGuardIP: w1,
  300. },
  301. {
  302. allowedIPs: []net.IPNet{*nodes["b"].Subnet, *nodes["b"].InternalIP, {IP: w2, Mask: net.CIDRMask(32, 32)}},
  303. endpoint: nodes["b"].Endpoint,
  304. key: nodes["b"].Key,
  305. persistentKeepalive: nodes["b"].PersistentKeepalive,
  306. location: nodeLocationPrefix + nodes["b"].Name,
  307. cidrs: []*net.IPNet{nodes["b"].Subnet},
  308. hostnames: []string{"b"},
  309. privateIPs: []net.IP{nodes["b"].InternalIP.IP},
  310. wireGuardIP: w2,
  311. allowedLocationIPs: nodes["b"].AllowedLocationIPs,
  312. },
  313. {
  314. allowedIPs: []net.IPNet{*nodes["c"].Subnet, *nodes["c"].InternalIP, {IP: w3, Mask: net.CIDRMask(32, 32)}},
  315. endpoint: nodes["c"].Endpoint,
  316. key: nodes["c"].Key,
  317. persistentKeepalive: nodes["c"].PersistentKeepalive,
  318. location: nodeLocationPrefix + nodes["c"].Name,
  319. cidrs: []*net.IPNet{nodes["c"].Subnet},
  320. hostnames: []string{"c"},
  321. privateIPs: []net.IP{nodes["c"].InternalIP.IP},
  322. wireGuardIP: w3,
  323. },
  324. {
  325. allowedIPs: []net.IPNet{*nodes["d"].Subnet, {IP: w4, Mask: net.CIDRMask(32, 32)}},
  326. endpoint: nodes["d"].Endpoint,
  327. key: nodes["d"].Key,
  328. persistentKeepalive: nodes["d"].PersistentKeepalive,
  329. location: nodeLocationPrefix + nodes["d"].Name,
  330. cidrs: []*net.IPNet{nodes["d"].Subnet},
  331. hostnames: []string{"d"},
  332. privateIPs: nil,
  333. wireGuardIP: w4,
  334. },
  335. },
  336. peers: []*Peer{peers["a"], peers["b"]},
  337. logger: log.NewNopLogger(),
  338. },
  339. },
  340. {
  341. name: "full from b",
  342. granularity: FullGranularity,
  343. hostname: nodes["b"].Name,
  344. result: &Topology{
  345. hostname: nodes["b"].Name,
  346. leader: true,
  347. location: nodeLocationPrefix + nodes["b"].Name,
  348. subnet: nodes["b"].Subnet,
  349. privateIP: nodes["b"].InternalIP,
  350. wireGuardCIDR: &net.IPNet{IP: w2, Mask: net.CIDRMask(16, 32)},
  351. segments: []*segment{
  352. {
  353. allowedIPs: []net.IPNet{*nodes["a"].Subnet, *nodes["a"].InternalIP, {IP: w1, Mask: net.CIDRMask(32, 32)}},
  354. endpoint: nodes["a"].Endpoint,
  355. key: nodes["a"].Key,
  356. persistentKeepalive: nodes["a"].PersistentKeepalive,
  357. location: nodeLocationPrefix + nodes["a"].Name,
  358. cidrs: []*net.IPNet{nodes["a"].Subnet},
  359. hostnames: []string{"a"},
  360. privateIPs: []net.IP{nodes["a"].InternalIP.IP},
  361. wireGuardIP: w1,
  362. },
  363. {
  364. allowedIPs: []net.IPNet{*nodes["b"].Subnet, *nodes["b"].InternalIP, {IP: w2, Mask: net.CIDRMask(32, 32)}},
  365. endpoint: nodes["b"].Endpoint,
  366. key: nodes["b"].Key,
  367. persistentKeepalive: nodes["b"].PersistentKeepalive,
  368. location: nodeLocationPrefix + nodes["b"].Name,
  369. cidrs: []*net.IPNet{nodes["b"].Subnet},
  370. hostnames: []string{"b"},
  371. privateIPs: []net.IP{nodes["b"].InternalIP.IP},
  372. wireGuardIP: w2,
  373. allowedLocationIPs: nodes["b"].AllowedLocationIPs,
  374. },
  375. {
  376. allowedIPs: []net.IPNet{*nodes["c"].Subnet, *nodes["c"].InternalIP, {IP: w3, Mask: net.CIDRMask(32, 32)}},
  377. endpoint: nodes["c"].Endpoint,
  378. key: nodes["c"].Key,
  379. persistentKeepalive: nodes["c"].PersistentKeepalive,
  380. location: nodeLocationPrefix + nodes["c"].Name,
  381. cidrs: []*net.IPNet{nodes["c"].Subnet},
  382. hostnames: []string{"c"},
  383. privateIPs: []net.IP{nodes["c"].InternalIP.IP},
  384. wireGuardIP: w3,
  385. },
  386. {
  387. allowedIPs: []net.IPNet{*nodes["d"].Subnet, {IP: w4, Mask: net.CIDRMask(32, 32)}},
  388. endpoint: nodes["d"].Endpoint,
  389. key: nodes["d"].Key,
  390. persistentKeepalive: nodes["d"].PersistentKeepalive,
  391. location: nodeLocationPrefix + nodes["d"].Name,
  392. cidrs: []*net.IPNet{nodes["d"].Subnet},
  393. hostnames: []string{"d"},
  394. privateIPs: nil,
  395. wireGuardIP: w4,
  396. },
  397. },
  398. peers: []*Peer{peers["a"], peers["b"]},
  399. logger: log.NewNopLogger(),
  400. },
  401. },
  402. {
  403. name: "full from c",
  404. granularity: FullGranularity,
  405. hostname: nodes["c"].Name,
  406. result: &Topology{
  407. hostname: nodes["c"].Name,
  408. leader: true,
  409. location: nodeLocationPrefix + nodes["c"].Name,
  410. subnet: nodes["c"].Subnet,
  411. privateIP: nodes["c"].InternalIP,
  412. wireGuardCIDR: &net.IPNet{IP: w3, Mask: net.CIDRMask(16, 32)},
  413. segments: []*segment{
  414. {
  415. allowedIPs: []net.IPNet{*nodes["a"].Subnet, *nodes["a"].InternalIP, {IP: w1, Mask: net.CIDRMask(32, 32)}},
  416. endpoint: nodes["a"].Endpoint,
  417. key: nodes["a"].Key,
  418. persistentKeepalive: nodes["a"].PersistentKeepalive,
  419. location: nodeLocationPrefix + nodes["a"].Name,
  420. cidrs: []*net.IPNet{nodes["a"].Subnet},
  421. hostnames: []string{"a"},
  422. privateIPs: []net.IP{nodes["a"].InternalIP.IP},
  423. wireGuardIP: w1,
  424. },
  425. {
  426. allowedIPs: []net.IPNet{*nodes["b"].Subnet, *nodes["b"].InternalIP, {IP: w2, Mask: net.CIDRMask(32, 32)}},
  427. endpoint: nodes["b"].Endpoint,
  428. key: nodes["b"].Key,
  429. persistentKeepalive: nodes["b"].PersistentKeepalive,
  430. location: nodeLocationPrefix + nodes["b"].Name,
  431. cidrs: []*net.IPNet{nodes["b"].Subnet},
  432. hostnames: []string{"b"},
  433. privateIPs: []net.IP{nodes["b"].InternalIP.IP},
  434. wireGuardIP: w2,
  435. allowedLocationIPs: nodes["b"].AllowedLocationIPs,
  436. },
  437. {
  438. allowedIPs: []net.IPNet{*nodes["c"].Subnet, *nodes["c"].InternalIP, {IP: w3, Mask: net.CIDRMask(32, 32)}},
  439. endpoint: nodes["c"].Endpoint,
  440. key: nodes["c"].Key,
  441. persistentKeepalive: nodes["c"].PersistentKeepalive,
  442. location: nodeLocationPrefix + nodes["c"].Name,
  443. cidrs: []*net.IPNet{nodes["c"].Subnet},
  444. hostnames: []string{"c"},
  445. privateIPs: []net.IP{nodes["c"].InternalIP.IP},
  446. wireGuardIP: w3,
  447. },
  448. {
  449. allowedIPs: []net.IPNet{*nodes["d"].Subnet, {IP: w4, Mask: net.CIDRMask(32, 32)}},
  450. endpoint: nodes["d"].Endpoint,
  451. key: nodes["d"].Key,
  452. persistentKeepalive: nodes["d"].PersistentKeepalive,
  453. location: nodeLocationPrefix + nodes["d"].Name,
  454. cidrs: []*net.IPNet{nodes["d"].Subnet},
  455. hostnames: []string{"d"},
  456. privateIPs: nil,
  457. wireGuardIP: w4,
  458. },
  459. },
  460. peers: []*Peer{peers["a"], peers["b"]},
  461. logger: log.NewNopLogger(),
  462. },
  463. },
  464. {
  465. name: "full from d",
  466. granularity: FullGranularity,
  467. hostname: nodes["d"].Name,
  468. result: &Topology{
  469. hostname: nodes["d"].Name,
  470. leader: true,
  471. location: nodeLocationPrefix + nodes["d"].Name,
  472. subnet: nodes["d"].Subnet,
  473. privateIP: nil,
  474. wireGuardCIDR: &net.IPNet{IP: w4, Mask: net.CIDRMask(16, 32)},
  475. segments: []*segment{
  476. {
  477. allowedIPs: []net.IPNet{*nodes["a"].Subnet, *nodes["a"].InternalIP, {IP: w1, Mask: net.CIDRMask(32, 32)}},
  478. endpoint: nodes["a"].Endpoint,
  479. key: nodes["a"].Key,
  480. persistentKeepalive: nodes["a"].PersistentKeepalive,
  481. location: nodeLocationPrefix + nodes["a"].Name,
  482. cidrs: []*net.IPNet{nodes["a"].Subnet},
  483. hostnames: []string{"a"},
  484. privateIPs: []net.IP{nodes["a"].InternalIP.IP},
  485. wireGuardIP: w1,
  486. },
  487. {
  488. allowedIPs: []net.IPNet{*nodes["b"].Subnet, *nodes["b"].InternalIP, {IP: w2, Mask: net.CIDRMask(32, 32)}},
  489. endpoint: nodes["b"].Endpoint,
  490. key: nodes["b"].Key,
  491. persistentKeepalive: nodes["b"].PersistentKeepalive,
  492. location: nodeLocationPrefix + nodes["b"].Name,
  493. cidrs: []*net.IPNet{nodes["b"].Subnet},
  494. hostnames: []string{"b"},
  495. privateIPs: []net.IP{nodes["b"].InternalIP.IP},
  496. wireGuardIP: w2,
  497. allowedLocationIPs: nodes["b"].AllowedLocationIPs,
  498. },
  499. {
  500. allowedIPs: []net.IPNet{*nodes["c"].Subnet, *nodes["c"].InternalIP, {IP: w3, Mask: net.CIDRMask(32, 32)}},
  501. endpoint: nodes["c"].Endpoint,
  502. key: nodes["c"].Key,
  503. persistentKeepalive: nodes["c"].PersistentKeepalive,
  504. location: nodeLocationPrefix + nodes["c"].Name,
  505. cidrs: []*net.IPNet{nodes["c"].Subnet},
  506. hostnames: []string{"c"},
  507. privateIPs: []net.IP{nodes["c"].InternalIP.IP},
  508. wireGuardIP: w3,
  509. },
  510. {
  511. allowedIPs: []net.IPNet{*nodes["d"].Subnet, {IP: w4, Mask: net.CIDRMask(32, 32)}},
  512. endpoint: nodes["d"].Endpoint,
  513. key: nodes["d"].Key,
  514. persistentKeepalive: nodes["d"].PersistentKeepalive,
  515. location: nodeLocationPrefix + nodes["d"].Name,
  516. cidrs: []*net.IPNet{nodes["d"].Subnet},
  517. hostnames: []string{"d"},
  518. privateIPs: nil,
  519. wireGuardIP: w4,
  520. },
  521. },
  522. peers: []*Peer{peers["a"], peers["b"]},
  523. logger: log.NewNopLogger(),
  524. },
  525. },
  526. } {
  527. tc.result.key = key
  528. tc.result.port = port
  529. topo, err := NewTopology(nodes, peers, tc.granularity, tc.hostname, port, key, DefaultKiloSubnet, 0, nil)
  530. if err != nil {
  531. t.Errorf("test case %q: failed to generate Topology: %v", tc.name, err)
  532. }
  533. if diff := pretty.Compare(topo, tc.result); diff != "" {
  534. t.Errorf("test case %q: got diff: %v", tc.name, diff)
  535. }
  536. }
  537. }
  538. func mustTopo(t *testing.T, nodes map[string]*Node, peers map[string]*Peer, granularity Granularity, hostname string, port int, key wgtypes.Key, subnet *net.IPNet, persistentKeepalive time.Duration) *Topology {
  539. topo, err := NewTopology(nodes, peers, granularity, hostname, port, key, subnet, persistentKeepalive, nil)
  540. if err != nil {
  541. t.Errorf("failed to generate Topology: %v", err)
  542. }
  543. return topo
  544. }
  545. func TestFindLeader(t *testing.T) {
  546. ip, e1, err := net.ParseCIDR("10.0.0.1/32")
  547. if err != nil {
  548. t.Fatalf("failed to parse external IP CIDR: %v", err)
  549. }
  550. e1.IP = ip
  551. ip, e2, err := net.ParseCIDR("8.8.8.8/32")
  552. if err != nil {
  553. t.Fatalf("failed to parse external IP CIDR: %v", err)
  554. }
  555. e2.IP = ip
  556. nodes := []*Node{
  557. {
  558. Name: "a",
  559. Endpoint: wireguard.NewEndpoint(e1.IP, DefaultKiloPort),
  560. },
  561. {
  562. Name: "b",
  563. Endpoint: wireguard.NewEndpoint(e2.IP, DefaultKiloPort),
  564. },
  565. {
  566. Name: "c",
  567. Endpoint: wireguard.NewEndpoint(e2.IP, DefaultKiloPort),
  568. },
  569. {
  570. Name: "d",
  571. Endpoint: wireguard.NewEndpoint(e1.IP, DefaultKiloPort),
  572. Leader: true,
  573. },
  574. {
  575. Name: "2",
  576. Endpoint: wireguard.NewEndpoint(e2.IP, DefaultKiloPort),
  577. Leader: true,
  578. },
  579. }
  580. for _, tc := range []struct {
  581. name string
  582. nodes []*Node
  583. out int
  584. }{
  585. {
  586. name: "nil",
  587. nodes: nil,
  588. out: 0,
  589. },
  590. {
  591. name: "one",
  592. nodes: []*Node{nodes[0]},
  593. out: 0,
  594. },
  595. {
  596. name: "non-leaders",
  597. nodes: []*Node{nodes[0], nodes[1], nodes[2]},
  598. out: 1,
  599. },
  600. {
  601. name: "leaders",
  602. nodes: []*Node{nodes[3], nodes[4]},
  603. out: 1,
  604. },
  605. {
  606. name: "public",
  607. nodes: []*Node{nodes[1], nodes[2], nodes[4]},
  608. out: 2,
  609. },
  610. {
  611. name: "private",
  612. nodes: []*Node{nodes[0], nodes[3]},
  613. out: 1,
  614. },
  615. {
  616. name: "all",
  617. nodes: nodes,
  618. out: 4,
  619. },
  620. } {
  621. l := findLeader(tc.nodes)
  622. if l != tc.out {
  623. t.Errorf("test case %q: expected %d got %d", tc.name, tc.out, l)
  624. }
  625. }
  626. }
  627. func TestDeduplicatePeerIPs(t *testing.T) {
  628. p1 := &Peer{
  629. Name: "1",
  630. Peer: wireguard.Peer{
  631. PeerConfig: wgtypes.PeerConfig{
  632. PublicKey: key1,
  633. AllowedIPs: []net.IPNet{
  634. {IP: net.ParseIP("10.0.0.1"), Mask: net.CIDRMask(24, 32)},
  635. {IP: net.ParseIP("10.0.0.2"), Mask: net.CIDRMask(24, 32)},
  636. },
  637. },
  638. },
  639. }
  640. p2 := &Peer{
  641. Name: "2",
  642. Peer: wireguard.Peer{
  643. PeerConfig: wgtypes.PeerConfig{
  644. PublicKey: key2,
  645. AllowedIPs: []net.IPNet{
  646. {IP: net.ParseIP("10.0.0.1"), Mask: net.CIDRMask(24, 32)},
  647. {IP: net.ParseIP("10.0.0.3"), Mask: net.CIDRMask(24, 32)},
  648. },
  649. },
  650. },
  651. }
  652. p3 := &Peer{
  653. Name: "3",
  654. Peer: wireguard.Peer{
  655. PeerConfig: wgtypes.PeerConfig{
  656. PublicKey: key3,
  657. AllowedIPs: []net.IPNet{
  658. {IP: net.ParseIP("10.0.0.2"), Mask: net.CIDRMask(24, 32)},
  659. {IP: net.ParseIP("10.0.0.3"), Mask: net.CIDRMask(24, 32)},
  660. {IP: net.ParseIP("10.0.0.1"), Mask: net.CIDRMask(24, 32)},
  661. },
  662. },
  663. },
  664. }
  665. p4 := &Peer{
  666. Name: "4",
  667. Peer: wireguard.Peer{
  668. PeerConfig: wgtypes.PeerConfig{
  669. PublicKey: key4,
  670. AllowedIPs: []net.IPNet{
  671. {IP: net.ParseIP("10.0.0.3"), Mask: net.CIDRMask(24, 32)},
  672. {IP: net.ParseIP("10.0.0.3"), Mask: net.CIDRMask(24, 32)},
  673. },
  674. },
  675. },
  676. }
  677. for _, tc := range []struct {
  678. name string
  679. peers []*Peer
  680. out []*Peer
  681. }{
  682. {
  683. name: "nil",
  684. peers: nil,
  685. out: nil,
  686. },
  687. {
  688. name: "simple dupe",
  689. peers: []*Peer{p1, p2},
  690. out: []*Peer{
  691. p1,
  692. {
  693. Name: "2",
  694. Peer: wireguard.Peer{
  695. PeerConfig: wgtypes.PeerConfig{
  696. PublicKey: key2,
  697. AllowedIPs: []net.IPNet{
  698. {IP: net.ParseIP("10.0.0.3"), Mask: net.CIDRMask(24, 32)},
  699. },
  700. },
  701. },
  702. },
  703. },
  704. },
  705. {
  706. name: "simple dupe reversed",
  707. peers: []*Peer{p2, p1},
  708. out: []*Peer{
  709. p2,
  710. {
  711. Name: "1",
  712. Peer: wireguard.Peer{
  713. PeerConfig: wgtypes.PeerConfig{
  714. PublicKey: key1,
  715. AllowedIPs: []net.IPNet{
  716. {IP: net.ParseIP("10.0.0.2"), Mask: net.CIDRMask(24, 32)},
  717. },
  718. },
  719. },
  720. },
  721. },
  722. },
  723. {
  724. name: "one duplicates all",
  725. peers: []*Peer{p3, p2, p1, p4},
  726. out: []*Peer{
  727. p3,
  728. {
  729. Name: "2",
  730. Peer: wireguard.Peer{
  731. PeerConfig: wgtypes.PeerConfig{
  732. PublicKey: key2,
  733. },
  734. },
  735. },
  736. {
  737. Name: "1",
  738. Peer: wireguard.Peer{
  739. PeerConfig: wgtypes.PeerConfig{
  740. PublicKey: key1,
  741. },
  742. },
  743. },
  744. {
  745. Name: "4",
  746. Peer: wireguard.Peer{
  747. PeerConfig: wgtypes.PeerConfig{
  748. PublicKey: key4,
  749. },
  750. },
  751. },
  752. },
  753. },
  754. {
  755. name: "one duplicates itself",
  756. peers: []*Peer{p4, p1},
  757. out: []*Peer{
  758. {
  759. Name: "4",
  760. Peer: wireguard.Peer{
  761. PeerConfig: wgtypes.PeerConfig{
  762. PublicKey: key4,
  763. AllowedIPs: []net.IPNet{
  764. {IP: net.ParseIP("10.0.0.3"), Mask: net.CIDRMask(24, 32)},
  765. },
  766. },
  767. },
  768. },
  769. {
  770. Name: "1",
  771. Peer: wireguard.Peer{
  772. PeerConfig: wgtypes.PeerConfig{
  773. PublicKey: key1,
  774. AllowedIPs: []net.IPNet{
  775. {IP: net.ParseIP("10.0.0.1"), Mask: net.CIDRMask(24, 32)},
  776. {IP: net.ParseIP("10.0.0.2"), Mask: net.CIDRMask(24, 32)},
  777. },
  778. },
  779. },
  780. },
  781. },
  782. },
  783. } {
  784. out := deduplicatePeerIPs(tc.peers)
  785. if diff := pretty.Compare(out, tc.out); diff != "" {
  786. t.Errorf("test case %q: got diff: %v", tc.name, diff)
  787. }
  788. }
  789. }
  790. func TestFilterAllowedIPs(t *testing.T) {
  791. nodes, peers, key, port := setup(t)
  792. topo := mustTopo(t, nodes, peers, LogicalGranularity, nodes["a"].Name, port, key, DefaultKiloSubnet, nodes["a"].PersistentKeepalive)
  793. for _, tc := range []struct {
  794. name string
  795. allowedLocationIPs map[int][]net.IPNet
  796. result map[int][]net.IPNet
  797. }{
  798. {
  799. name: "nothing to filter",
  800. allowedLocationIPs: map[int][]net.IPNet{
  801. 0: {
  802. mustParseCIDR("192.168.178.4/32"),
  803. },
  804. 1: {
  805. mustParseCIDR("192.168.178.5/32"),
  806. },
  807. 2: {
  808. mustParseCIDR("192.168.178.6/32"),
  809. mustParseCIDR("192.168.178.7/32"),
  810. },
  811. },
  812. result: map[int][]net.IPNet{
  813. 0: {
  814. mustParseCIDR("192.168.178.4/32"),
  815. },
  816. 1: {
  817. mustParseCIDR("192.168.178.5/32"),
  818. },
  819. 2: {
  820. mustParseCIDR("192.168.178.6/32"),
  821. mustParseCIDR("192.168.178.7/32"),
  822. },
  823. },
  824. },
  825. {
  826. name: "intersections between segments",
  827. allowedLocationIPs: map[int][]net.IPNet{
  828. 0: {
  829. mustParseCIDR("192.168.178.4/32"),
  830. mustParseCIDR("192.168.178.8/32"),
  831. },
  832. 1: {
  833. mustParseCIDR("192.168.178.5/32"),
  834. },
  835. 2: {
  836. mustParseCIDR("192.168.178.6/32"),
  837. mustParseCIDR("192.168.178.7/32"),
  838. mustParseCIDR("192.168.178.4/32"),
  839. },
  840. },
  841. result: map[int][]net.IPNet{
  842. 0: {
  843. mustParseCIDR("192.168.178.8/32"),
  844. },
  845. 1: {
  846. mustParseCIDR("192.168.178.5/32"),
  847. },
  848. 2: {
  849. mustParseCIDR("192.168.178.6/32"),
  850. mustParseCIDR("192.168.178.7/32"),
  851. mustParseCIDR("192.168.178.4/32"),
  852. },
  853. },
  854. },
  855. {
  856. name: "intersections with wireGuardCIDR",
  857. allowedLocationIPs: map[int][]net.IPNet{
  858. 0: {
  859. mustParseCIDR("10.4.0.1/32"),
  860. mustParseCIDR("192.168.178.8/32"),
  861. },
  862. 1: {
  863. mustParseCIDR("192.168.178.5/32"),
  864. },
  865. 2: {
  866. mustParseCIDR("192.168.178.6/32"),
  867. mustParseCIDR("192.168.178.7/32"),
  868. },
  869. },
  870. result: map[int][]net.IPNet{
  871. 0: {
  872. mustParseCIDR("192.168.178.8/32"),
  873. },
  874. 1: {
  875. mustParseCIDR("192.168.178.5/32"),
  876. },
  877. 2: {
  878. mustParseCIDR("192.168.178.6/32"),
  879. mustParseCIDR("192.168.178.7/32"),
  880. },
  881. },
  882. },
  883. {
  884. name: "intersections with more than one allowedLocationIPs",
  885. allowedLocationIPs: map[int][]net.IPNet{
  886. 0: {
  887. mustParseCIDR("192.168.178.8/32"),
  888. },
  889. 1: {
  890. mustParseCIDR("192.168.178.5/32"),
  891. },
  892. 2: {
  893. mustParseCIDR("192.168.178.7/24"),
  894. },
  895. },
  896. result: map[int][]net.IPNet{
  897. 0: {},
  898. 1: {},
  899. 2: {
  900. mustParseCIDR("192.168.178.7/24"),
  901. },
  902. },
  903. },
  904. } {
  905. for k, v := range tc.allowedLocationIPs {
  906. topo.segments[k].allowedLocationIPs = v
  907. }
  908. for k, v := range topo.segments {
  909. f := topo.filterAllowedLocationIPs(v.allowedLocationIPs, v.location)
  910. // Overwrite the allowedLocationIPs to mimic the actual usage of the filterAllowedLocationIPs function.
  911. topo.segments[k].allowedLocationIPs = f
  912. if !ipNetSlicesEqual(f, tc.result[k]) {
  913. t.Errorf("test case %q:\n\texpected:\n\t%q\n\tgot:\n\t%q\n", tc.name, tc.result[k], f)
  914. }
  915. }
  916. }
  917. }