3
0

lighthouse_test.go 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457
  1. package nebula
  2. import (
  3. "context"
  4. "fmt"
  5. "net"
  6. "testing"
  7. "github.com/slackhq/nebula/config"
  8. "github.com/slackhq/nebula/header"
  9. "github.com/slackhq/nebula/iputil"
  10. "github.com/slackhq/nebula/test"
  11. "github.com/slackhq/nebula/udp"
  12. "github.com/stretchr/testify/assert"
  13. "gopkg.in/yaml.v2"
  14. )
  15. //TODO: Add a test to ensure udpAddr is copied and not reused
  16. func TestOldIPv4Only(t *testing.T) {
  17. // This test ensures our new ipv6 enabled LH protobuf IpAndPorts works with the old style to enable backwards compatibility
  18. b := []byte{8, 129, 130, 132, 80, 16, 10}
  19. var m Ip4AndPort
  20. err := m.Unmarshal(b)
  21. assert.NoError(t, err)
  22. assert.Equal(t, "10.1.1.1", iputil.VpnIp(m.GetIp()).String())
  23. }
  24. func TestNewLhQuery(t *testing.T) {
  25. myIp := net.ParseIP("192.1.1.1")
  26. myIpint := iputil.Ip2VpnIp(myIp)
  27. // Generating a new lh query should work
  28. a := NewLhQueryByInt(myIpint)
  29. // The result should be a nebulameta protobuf
  30. assert.IsType(t, &NebulaMeta{}, a)
  31. // It should also Marshal fine
  32. b, err := a.Marshal()
  33. assert.Nil(t, err)
  34. // and then Unmarshal fine
  35. n := &NebulaMeta{}
  36. err = n.Unmarshal(b)
  37. assert.Nil(t, err)
  38. }
  39. func Test_lhStaticMapping(t *testing.T) {
  40. l := test.NewLogger()
  41. _, myVpnNet, _ := net.ParseCIDR("10.128.0.1/16")
  42. lh1 := "10.128.0.2"
  43. c := config.NewC(l)
  44. c.Settings["lighthouse"] = map[interface{}]interface{}{"hosts": []interface{}{lh1}}
  45. c.Settings["static_host_map"] = map[interface{}]interface{}{lh1: []interface{}{"1.1.1.1:4242"}}
  46. _, err := NewLightHouseFromConfig(context.Background(), l, c, myVpnNet, nil, nil)
  47. assert.Nil(t, err)
  48. lh2 := "10.128.0.3"
  49. c = config.NewC(l)
  50. c.Settings["lighthouse"] = map[interface{}]interface{}{"hosts": []interface{}{lh1, lh2}}
  51. c.Settings["static_host_map"] = map[interface{}]interface{}{lh1: []interface{}{"100.1.1.1:4242"}}
  52. _, err = NewLightHouseFromConfig(context.Background(), l, c, myVpnNet, nil, nil)
  53. assert.EqualError(t, err, "lighthouse 10.128.0.3 does not have a static_host_map entry")
  54. }
  55. func BenchmarkLighthouseHandleRequest(b *testing.B) {
  56. l := test.NewLogger()
  57. _, myVpnNet, _ := net.ParseCIDR("10.128.0.1/0")
  58. c := config.NewC(l)
  59. lh, err := NewLightHouseFromConfig(context.Background(), l, c, myVpnNet, nil, nil)
  60. if !assert.NoError(b, err) {
  61. b.Fatal()
  62. }
  63. hAddr := udp.NewAddrFromString("4.5.6.7:12345")
  64. hAddr2 := udp.NewAddrFromString("4.5.6.7:12346")
  65. lh.addrMap[3] = NewRemoteList(nil)
  66. lh.addrMap[3].unlockedSetV4(
  67. 3,
  68. 3,
  69. []*Ip4AndPort{
  70. NewIp4AndPort(hAddr.IP, uint32(hAddr.Port)),
  71. NewIp4AndPort(hAddr2.IP, uint32(hAddr2.Port)),
  72. },
  73. func(iputil.VpnIp, *Ip4AndPort) bool { return true },
  74. )
  75. rAddr := udp.NewAddrFromString("1.2.2.3:12345")
  76. rAddr2 := udp.NewAddrFromString("1.2.2.3:12346")
  77. lh.addrMap[2] = NewRemoteList(nil)
  78. lh.addrMap[2].unlockedSetV4(
  79. 3,
  80. 3,
  81. []*Ip4AndPort{
  82. NewIp4AndPort(rAddr.IP, uint32(rAddr.Port)),
  83. NewIp4AndPort(rAddr2.IP, uint32(rAddr2.Port)),
  84. },
  85. func(iputil.VpnIp, *Ip4AndPort) bool { return true },
  86. )
  87. mw := &mockEncWriter{}
  88. b.Run("notfound", func(b *testing.B) {
  89. lhh := lh.NewRequestHandler()
  90. req := &NebulaMeta{
  91. Type: NebulaMeta_HostQuery,
  92. Details: &NebulaMetaDetails{
  93. VpnIp: 4,
  94. Ip4AndPorts: nil,
  95. },
  96. }
  97. p, err := req.Marshal()
  98. assert.NoError(b, err)
  99. for n := 0; n < b.N; n++ {
  100. lhh.HandleRequest(rAddr, 2, p, mw)
  101. }
  102. })
  103. b.Run("found", func(b *testing.B) {
  104. lhh := lh.NewRequestHandler()
  105. req := &NebulaMeta{
  106. Type: NebulaMeta_HostQuery,
  107. Details: &NebulaMetaDetails{
  108. VpnIp: 3,
  109. Ip4AndPorts: nil,
  110. },
  111. }
  112. p, err := req.Marshal()
  113. assert.NoError(b, err)
  114. for n := 0; n < b.N; n++ {
  115. lhh.HandleRequest(rAddr, 2, p, mw)
  116. }
  117. })
  118. }
  119. func TestLighthouse_Memory(t *testing.T) {
  120. l := test.NewLogger()
  121. myUdpAddr0 := &udp.Addr{IP: net.ParseIP("10.0.0.2"), Port: 4242}
  122. myUdpAddr1 := &udp.Addr{IP: net.ParseIP("192.168.0.2"), Port: 4242}
  123. myUdpAddr2 := &udp.Addr{IP: net.ParseIP("172.16.0.2"), Port: 4242}
  124. myUdpAddr3 := &udp.Addr{IP: net.ParseIP("100.152.0.2"), Port: 4242}
  125. myUdpAddr4 := &udp.Addr{IP: net.ParseIP("24.15.0.2"), Port: 4242}
  126. myUdpAddr5 := &udp.Addr{IP: net.ParseIP("192.168.0.2"), Port: 4243}
  127. myUdpAddr6 := &udp.Addr{IP: net.ParseIP("192.168.0.2"), Port: 4244}
  128. myUdpAddr7 := &udp.Addr{IP: net.ParseIP("192.168.0.2"), Port: 4245}
  129. myUdpAddr8 := &udp.Addr{IP: net.ParseIP("192.168.0.2"), Port: 4246}
  130. myUdpAddr9 := &udp.Addr{IP: net.ParseIP("192.168.0.2"), Port: 4247}
  131. myUdpAddr10 := &udp.Addr{IP: net.ParseIP("192.168.0.2"), Port: 4248}
  132. myUdpAddr11 := &udp.Addr{IP: net.ParseIP("192.168.0.2"), Port: 4249}
  133. myVpnIp := iputil.Ip2VpnIp(net.ParseIP("10.128.0.2"))
  134. theirUdpAddr0 := &udp.Addr{IP: net.ParseIP("10.0.0.3"), Port: 4242}
  135. theirUdpAddr1 := &udp.Addr{IP: net.ParseIP("192.168.0.3"), Port: 4242}
  136. theirUdpAddr2 := &udp.Addr{IP: net.ParseIP("172.16.0.3"), Port: 4242}
  137. theirUdpAddr3 := &udp.Addr{IP: net.ParseIP("100.152.0.3"), Port: 4242}
  138. theirUdpAddr4 := &udp.Addr{IP: net.ParseIP("24.15.0.3"), Port: 4242}
  139. theirVpnIp := iputil.Ip2VpnIp(net.ParseIP("10.128.0.3"))
  140. c := config.NewC(l)
  141. c.Settings["lighthouse"] = map[interface{}]interface{}{"am_lighthouse": true}
  142. c.Settings["listen"] = map[interface{}]interface{}{"port": 4242}
  143. lh, err := NewLightHouseFromConfig(context.Background(), l, c, &net.IPNet{IP: net.IP{10, 128, 0, 1}, Mask: net.IPMask{255, 255, 255, 0}}, nil, nil)
  144. assert.NoError(t, err)
  145. lhh := lh.NewRequestHandler()
  146. // Test that my first update responds with just that
  147. newLHHostUpdate(myUdpAddr0, myVpnIp, []*udp.Addr{myUdpAddr1, myUdpAddr2}, lhh)
  148. r := newLHHostRequest(myUdpAddr0, myVpnIp, myVpnIp, lhh)
  149. assertIp4InArray(t, r.msg.Details.Ip4AndPorts, myUdpAddr1, myUdpAddr2)
  150. // Ensure we don't accumulate addresses
  151. newLHHostUpdate(myUdpAddr0, myVpnIp, []*udp.Addr{myUdpAddr3}, lhh)
  152. r = newLHHostRequest(myUdpAddr0, myVpnIp, myVpnIp, lhh)
  153. assertIp4InArray(t, r.msg.Details.Ip4AndPorts, myUdpAddr3)
  154. // Grow it back to 2
  155. newLHHostUpdate(myUdpAddr0, myVpnIp, []*udp.Addr{myUdpAddr1, myUdpAddr4}, lhh)
  156. r = newLHHostRequest(myUdpAddr0, myVpnIp, myVpnIp, lhh)
  157. assertIp4InArray(t, r.msg.Details.Ip4AndPorts, myUdpAddr1, myUdpAddr4)
  158. // Update a different host and ask about it
  159. newLHHostUpdate(theirUdpAddr0, theirVpnIp, []*udp.Addr{theirUdpAddr1, theirUdpAddr2, theirUdpAddr3, theirUdpAddr4}, lhh)
  160. r = newLHHostRequest(theirUdpAddr0, theirVpnIp, theirVpnIp, lhh)
  161. assertIp4InArray(t, r.msg.Details.Ip4AndPorts, theirUdpAddr1, theirUdpAddr2, theirUdpAddr3, theirUdpAddr4)
  162. // Have both hosts ask about the other
  163. r = newLHHostRequest(theirUdpAddr0, theirVpnIp, myVpnIp, lhh)
  164. assertIp4InArray(t, r.msg.Details.Ip4AndPorts, myUdpAddr1, myUdpAddr4)
  165. r = newLHHostRequest(myUdpAddr0, myVpnIp, theirVpnIp, lhh)
  166. assertIp4InArray(t, r.msg.Details.Ip4AndPorts, theirUdpAddr1, theirUdpAddr2, theirUdpAddr3, theirUdpAddr4)
  167. // Make sure we didn't get changed
  168. r = newLHHostRequest(myUdpAddr0, myVpnIp, myVpnIp, lhh)
  169. assertIp4InArray(t, r.msg.Details.Ip4AndPorts, myUdpAddr1, myUdpAddr4)
  170. // Ensure proper ordering and limiting
  171. // Send 12 addrs, get 10 back, the last 2 removed, allowing the duplicate to remain (clients dedupe)
  172. newLHHostUpdate(
  173. myUdpAddr0,
  174. myVpnIp,
  175. []*udp.Addr{
  176. myUdpAddr1,
  177. myUdpAddr2,
  178. myUdpAddr3,
  179. myUdpAddr4,
  180. myUdpAddr5,
  181. myUdpAddr5, //Duplicated on purpose
  182. myUdpAddr6,
  183. myUdpAddr7,
  184. myUdpAddr8,
  185. myUdpAddr9,
  186. myUdpAddr10,
  187. myUdpAddr11, // This should get cut
  188. }, lhh)
  189. r = newLHHostRequest(myUdpAddr0, myVpnIp, myVpnIp, lhh)
  190. assertIp4InArray(
  191. t,
  192. r.msg.Details.Ip4AndPorts,
  193. myUdpAddr1, myUdpAddr2, myUdpAddr3, myUdpAddr4, myUdpAddr5, myUdpAddr5, myUdpAddr6, myUdpAddr7, myUdpAddr8, myUdpAddr9,
  194. )
  195. // Make sure we won't add ips in our vpn network
  196. bad1 := &udp.Addr{IP: net.ParseIP("10.128.0.99"), Port: 4242}
  197. bad2 := &udp.Addr{IP: net.ParseIP("10.128.0.100"), Port: 4242}
  198. good := &udp.Addr{IP: net.ParseIP("1.128.0.99"), Port: 4242}
  199. newLHHostUpdate(myUdpAddr0, myVpnIp, []*udp.Addr{bad1, bad2, good}, lhh)
  200. r = newLHHostRequest(myUdpAddr0, myVpnIp, myVpnIp, lhh)
  201. assertIp4InArray(t, r.msg.Details.Ip4AndPorts, good)
  202. }
  203. func TestLighthouse_reload(t *testing.T) {
  204. l := test.NewLogger()
  205. c := config.NewC(l)
  206. c.Settings["lighthouse"] = map[interface{}]interface{}{"am_lighthouse": true}
  207. c.Settings["listen"] = map[interface{}]interface{}{"port": 4242}
  208. lh, err := NewLightHouseFromConfig(context.Background(), l, c, &net.IPNet{IP: net.IP{10, 128, 0, 1}, Mask: net.IPMask{255, 255, 255, 0}}, nil, nil)
  209. assert.NoError(t, err)
  210. nc := map[interface{}]interface{}{
  211. "static_host_map": map[interface{}]interface{}{
  212. "10.128.0.2": []interface{}{"1.1.1.1:4242"},
  213. },
  214. }
  215. rc, err := yaml.Marshal(nc)
  216. assert.NoError(t, err)
  217. c.ReloadConfigString(string(rc))
  218. err = lh.reload(c, false)
  219. assert.NoError(t, err)
  220. }
  221. func newLHHostRequest(fromAddr *udp.Addr, myVpnIp, queryVpnIp iputil.VpnIp, lhh *LightHouseHandler) testLhReply {
  222. req := &NebulaMeta{
  223. Type: NebulaMeta_HostQuery,
  224. Details: &NebulaMetaDetails{
  225. VpnIp: uint32(queryVpnIp),
  226. },
  227. }
  228. b, err := req.Marshal()
  229. if err != nil {
  230. panic(err)
  231. }
  232. filter := NebulaMeta_HostQueryReply
  233. w := &testEncWriter{
  234. metaFilter: &filter,
  235. }
  236. lhh.HandleRequest(fromAddr, myVpnIp, b, w)
  237. return w.lastReply
  238. }
  239. func newLHHostUpdate(fromAddr *udp.Addr, vpnIp iputil.VpnIp, addrs []*udp.Addr, lhh *LightHouseHandler) {
  240. req := &NebulaMeta{
  241. Type: NebulaMeta_HostUpdateNotification,
  242. Details: &NebulaMetaDetails{
  243. VpnIp: uint32(vpnIp),
  244. Ip4AndPorts: make([]*Ip4AndPort, len(addrs)),
  245. },
  246. }
  247. for k, v := range addrs {
  248. req.Details.Ip4AndPorts[k] = &Ip4AndPort{Ip: uint32(iputil.Ip2VpnIp(v.IP)), Port: uint32(v.Port)}
  249. }
  250. b, err := req.Marshal()
  251. if err != nil {
  252. panic(err)
  253. }
  254. w := &testEncWriter{}
  255. lhh.HandleRequest(fromAddr, vpnIp, b, w)
  256. }
  257. //TODO: this is a RemoteList test
  258. //func Test_lhRemoteAllowList(t *testing.T) {
  259. // l := NewLogger()
  260. // c := NewConfig(l)
  261. // c.Settings["remoteallowlist"] = map[interface{}]interface{}{
  262. // "10.20.0.0/12": false,
  263. // }
  264. // allowList, err := c.GetAllowList("remoteallowlist", false)
  265. // assert.Nil(t, err)
  266. //
  267. // lh1 := "10.128.0.2"
  268. // lh1IP := net.ParseIP(lh1)
  269. //
  270. // udpServer, _ := NewListener(l, "0.0.0.0", 0, true)
  271. //
  272. // lh := NewLightHouse(l, true, &net.IPNet{IP: net.IP{0, 0, 0, 1}, Mask: net.IPMask{255, 255, 255, 0}}, []uint32{ip2int(lh1IP)}, 10, 10003, udpServer, false, 1, false)
  273. // lh.SetRemoteAllowList(allowList)
  274. //
  275. // // A disallowed ip should not enter the cache but we should end up with an empty entry in the addrMap
  276. // remote1IP := net.ParseIP("10.20.0.3")
  277. // remotes := lh.unlockedGetRemoteList(ip2int(remote1IP))
  278. // remotes.unlockedPrependV4(ip2int(remote1IP), NewIp4AndPort(remote1IP, 4242))
  279. // assert.NotNil(t, lh.addrMap[ip2int(remote1IP)])
  280. // assert.Empty(t, lh.addrMap[ip2int(remote1IP)].CopyAddrs([]*net.IPNet{}))
  281. //
  282. // // Make sure a good ip enters the cache and addrMap
  283. // remote2IP := net.ParseIP("10.128.0.3")
  284. // remote2UDPAddr := NewUDPAddr(remote2IP, uint16(4242))
  285. // lh.addRemoteV4(ip2int(remote2IP), ip2int(remote2IP), NewIp4AndPort(remote2UDPAddr.IP, uint32(remote2UDPAddr.Port)), false, false)
  286. // assertUdpAddrInArray(t, lh.addrMap[ip2int(remote2IP)].CopyAddrs([]*net.IPNet{}), remote2UDPAddr)
  287. //
  288. // // Another good ip gets into the cache, ordering is inverted
  289. // remote3IP := net.ParseIP("10.128.0.4")
  290. // remote3UDPAddr := NewUDPAddr(remote3IP, uint16(4243))
  291. // lh.addRemoteV4(ip2int(remote2IP), ip2int(remote2IP), NewIp4AndPort(remote3UDPAddr.IP, uint32(remote3UDPAddr.Port)), false, false)
  292. // assertUdpAddrInArray(t, lh.addrMap[ip2int(remote2IP)].CopyAddrs([]*net.IPNet{}), remote2UDPAddr, remote3UDPAddr)
  293. //
  294. // // If we exceed the length limit we should only have the most recent addresses
  295. // addedAddrs := []*udpAddr{}
  296. // for i := 0; i < 11; i++ {
  297. // remoteUDPAddr := NewUDPAddr(net.IP{10, 128, 0, 4}, uint16(4243+i))
  298. // lh.addRemoteV4(ip2int(remote2IP), ip2int(remote2IP), NewIp4AndPort(remoteUDPAddr.IP, uint32(remoteUDPAddr.Port)), false, false)
  299. // // The first entry here is a duplicate, don't add it to the assert list
  300. // if i != 0 {
  301. // addedAddrs = append(addedAddrs, remoteUDPAddr)
  302. // }
  303. // }
  304. //
  305. // // We should only have the last 10 of what we tried to add
  306. // assert.True(t, len(addedAddrs) >= 10, "We should have tried to add at least 10 addresses")
  307. // assertUdpAddrInArray(
  308. // t,
  309. // lh.addrMap[ip2int(remote2IP)].CopyAddrs([]*net.IPNet{}),
  310. // addedAddrs[0],
  311. // addedAddrs[1],
  312. // addedAddrs[2],
  313. // addedAddrs[3],
  314. // addedAddrs[4],
  315. // addedAddrs[5],
  316. // addedAddrs[6],
  317. // addedAddrs[7],
  318. // addedAddrs[8],
  319. // addedAddrs[9],
  320. // )
  321. //}
  322. func Test_ipMaskContains(t *testing.T) {
  323. assert.True(t, ipMaskContains(iputil.Ip2VpnIp(net.ParseIP("10.0.0.1")), 32-24, iputil.Ip2VpnIp(net.ParseIP("10.0.0.255"))))
  324. assert.False(t, ipMaskContains(iputil.Ip2VpnIp(net.ParseIP("10.0.0.1")), 32-24, iputil.Ip2VpnIp(net.ParseIP("10.0.1.1"))))
  325. assert.True(t, ipMaskContains(iputil.Ip2VpnIp(net.ParseIP("10.0.0.1")), 32, iputil.Ip2VpnIp(net.ParseIP("10.0.1.1"))))
  326. }
  327. type testLhReply struct {
  328. nebType header.MessageType
  329. nebSubType header.MessageSubType
  330. vpnIp iputil.VpnIp
  331. msg *NebulaMeta
  332. }
  333. type testEncWriter struct {
  334. lastReply testLhReply
  335. metaFilter *NebulaMeta_MessageType
  336. }
  337. func (tw *testEncWriter) SendVia(via *HostInfo, relay *Relay, ad, nb, out []byte, nocopy bool) {
  338. }
  339. func (tw *testEncWriter) Handshake(vpnIp iputil.VpnIp) {
  340. }
  341. func (tw *testEncWriter) SendMessageToHostInfo(t header.MessageType, st header.MessageSubType, hostinfo *HostInfo, p, _, _ []byte) {
  342. msg := &NebulaMeta{}
  343. err := msg.Unmarshal(p)
  344. if tw.metaFilter == nil || msg.Type == *tw.metaFilter {
  345. tw.lastReply = testLhReply{
  346. nebType: t,
  347. nebSubType: st,
  348. vpnIp: hostinfo.vpnIp,
  349. msg: msg,
  350. }
  351. }
  352. if err != nil {
  353. panic(err)
  354. }
  355. }
  356. func (tw *testEncWriter) SendMessageToVpnIp(t header.MessageType, st header.MessageSubType, vpnIp iputil.VpnIp, p, _, _ []byte) {
  357. msg := &NebulaMeta{}
  358. err := msg.Unmarshal(p)
  359. if tw.metaFilter == nil || msg.Type == *tw.metaFilter {
  360. tw.lastReply = testLhReply{
  361. nebType: t,
  362. nebSubType: st,
  363. vpnIp: vpnIp,
  364. msg: msg,
  365. }
  366. }
  367. if err != nil {
  368. panic(err)
  369. }
  370. }
  371. // assertIp4InArray asserts every address in want is at the same position in have and that the lengths match
  372. func assertIp4InArray(t *testing.T, have []*Ip4AndPort, want ...*udp.Addr) {
  373. if !assert.Len(t, have, len(want)) {
  374. return
  375. }
  376. for k, w := range want {
  377. if !(have[k].Ip == uint32(iputil.Ip2VpnIp(w.IP)) && have[k].Port == uint32(w.Port)) {
  378. assert.Fail(t, fmt.Sprintf("Response did not contain: %v:%v at %v; %v", w.IP, w.Port, k, translateV4toUdpAddr(have)))
  379. }
  380. }
  381. }
  382. // assertUdpAddrInArray asserts every address in want is at the same position in have and that the lengths match
  383. func assertUdpAddrInArray(t *testing.T, have []*udp.Addr, want ...*udp.Addr) {
  384. if !assert.Len(t, have, len(want)) {
  385. return
  386. }
  387. for k, w := range want {
  388. if !(have[k].IP.Equal(w.IP) && have[k].Port == w.Port) {
  389. assert.Fail(t, fmt.Sprintf("Response did not contain: %v at %v; %v", w, k, have))
  390. }
  391. }
  392. }
  393. func translateV4toUdpAddr(ips []*Ip4AndPort) []*udp.Addr {
  394. addrs := make([]*udp.Addr, len(ips))
  395. for k, v := range ips {
  396. addrs[k] = NewUDPAddrFromLH4(v)
  397. }
  398. return addrs
  399. }