2
0

router.go 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767
  1. //go:build e2e_testing
  2. // +build e2e_testing
  3. package router
  4. import (
  5. "context"
  6. "fmt"
  7. "net"
  8. "os"
  9. "path/filepath"
  10. "reflect"
  11. "sort"
  12. "strconv"
  13. "strings"
  14. "sync"
  15. "testing"
  16. "time"
  17. "github.com/google/gopacket"
  18. "github.com/google/gopacket/layers"
  19. "github.com/slackhq/nebula"
  20. "github.com/slackhq/nebula/header"
  21. "github.com/slackhq/nebula/iputil"
  22. "github.com/slackhq/nebula/udp"
  23. "golang.org/x/exp/maps"
  24. )
  25. type R struct {
  26. // Simple map of the ip:port registered on a control to the control
  27. // Basically a router, right?
  28. controls map[string]*nebula.Control
  29. // A map for inbound packets for a control that doesn't know about this address
  30. inNat map[string]*nebula.Control
  31. // A last used map, if an inbound packet hit the inNat map then
  32. // all return packets should use the same last used inbound address for the outbound sender
  33. // map[from address + ":" + to address] => ip:port to rewrite in the udp packet to receiver
  34. outNat map[string]net.UDPAddr
  35. // A map of vpn ip to the nebula control it belongs to
  36. vpnControls map[iputil.VpnIp]*nebula.Control
  37. ignoreFlows []ignoreFlow
  38. flow []flowEntry
  39. // A set of additional mermaid graphs to draw in the flow log markdown file
  40. // Currently consisting only of hostmap renders
  41. additionalGraphs []mermaidGraph
  42. // All interactions are locked to help serialize behavior
  43. sync.Mutex
  44. fn string
  45. cancelRender context.CancelFunc
  46. t testing.TB
  47. }
  48. type ignoreFlow struct {
  49. tun NullBool
  50. messageType header.MessageType
  51. subType header.MessageSubType
  52. //from
  53. //to
  54. }
  55. type mermaidGraph struct {
  56. title string
  57. content string
  58. }
  59. type NullBool struct {
  60. HasValue bool
  61. IsTrue bool
  62. }
  63. type flowEntry struct {
  64. note string
  65. packet *packet
  66. }
  67. type packet struct {
  68. from *nebula.Control
  69. to *nebula.Control
  70. packet *udp.Packet
  71. tun bool // a packet pulled off a tun device
  72. rx bool // the packet was received by a udp device
  73. }
  74. func (p *packet) WasReceived() {
  75. if p != nil {
  76. p.rx = true
  77. }
  78. }
  79. type ExitType int
  80. const (
  81. // KeepRouting the function will get called again on the next packet
  82. KeepRouting ExitType = 0
  83. // ExitNow does not route this packet and exits immediately
  84. ExitNow ExitType = 1
  85. // RouteAndExit routes this packet and exits immediately afterwards
  86. RouteAndExit ExitType = 2
  87. )
  88. type ExitFunc func(packet *udp.Packet, receiver *nebula.Control) ExitType
  89. // NewR creates a new router to pass packets in a controlled fashion between the provided controllers.
  90. // The packet flow will be recorded in a file within the mermaid directory under the same name as the test.
  91. // Renders will occur automatically, roughly every 100ms, until a call to RenderFlow() is made
  92. func NewR(t testing.TB, controls ...*nebula.Control) *R {
  93. ctx, cancel := context.WithCancel(context.Background())
  94. if err := os.MkdirAll("mermaid", 0755); err != nil {
  95. panic(err)
  96. }
  97. r := &R{
  98. controls: make(map[string]*nebula.Control),
  99. vpnControls: make(map[iputil.VpnIp]*nebula.Control),
  100. inNat: make(map[string]*nebula.Control),
  101. outNat: make(map[string]net.UDPAddr),
  102. flow: []flowEntry{},
  103. ignoreFlows: []ignoreFlow{},
  104. fn: filepath.Join("mermaid", fmt.Sprintf("%s.md", t.Name())),
  105. t: t,
  106. cancelRender: cancel,
  107. }
  108. // Try to remove our render file
  109. os.Remove(r.fn)
  110. for _, c := range controls {
  111. addr := c.GetUDPAddr()
  112. if _, ok := r.controls[addr]; ok {
  113. panic("Duplicate listen address: " + addr)
  114. }
  115. r.vpnControls[c.GetVpnIp()] = c
  116. r.controls[addr] = c
  117. }
  118. // Spin the renderer in case we go nuts and the test never completes
  119. go func() {
  120. clockSource := time.NewTicker(time.Millisecond * 100)
  121. defer clockSource.Stop()
  122. for {
  123. select {
  124. case <-ctx.Done():
  125. return
  126. case <-clockSource.C:
  127. r.renderHostmaps("clock tick")
  128. r.renderFlow()
  129. }
  130. }
  131. }()
  132. return r
  133. }
  134. // AddRoute will place the nebula controller at the ip and port specified.
  135. // It does not look at the addr attached to the instance.
  136. // If a route is used, this will behave like a NAT for the return path.
  137. // Rewriting the source ip:port to what was last sent to from the origin
  138. func (r *R) AddRoute(ip net.IP, port uint16, c *nebula.Control) {
  139. r.Lock()
  140. defer r.Unlock()
  141. inAddr := net.JoinHostPort(ip.String(), fmt.Sprintf("%v", port))
  142. if _, ok := r.inNat[inAddr]; ok {
  143. panic("Duplicate listen address inNat: " + inAddr)
  144. }
  145. r.inNat[inAddr] = c
  146. }
  147. // RenderFlow renders the packet flow seen up until now and stops further automatic renders from happening.
  148. func (r *R) RenderFlow() {
  149. r.cancelRender()
  150. r.renderFlow()
  151. }
  152. // CancelFlowLogs stops flow logs from being tracked and destroys any logs already collected
  153. func (r *R) CancelFlowLogs() {
  154. r.cancelRender()
  155. r.flow = nil
  156. }
  157. func (r *R) renderFlow() {
  158. if r.flow == nil {
  159. return
  160. }
  161. f, err := os.OpenFile(r.fn, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0644)
  162. if err != nil {
  163. panic(err)
  164. }
  165. var participants = map[string]struct{}{}
  166. var participantsVals []string
  167. fmt.Fprintln(f, "```mermaid")
  168. fmt.Fprintln(f, "sequenceDiagram")
  169. // Assemble participants
  170. for _, e := range r.flow {
  171. if e.packet == nil {
  172. continue
  173. }
  174. addr := e.packet.from.GetUDPAddr()
  175. if _, ok := participants[addr]; ok {
  176. continue
  177. }
  178. participants[addr] = struct{}{}
  179. sanAddr := strings.Replace(addr, ":", "-", 1)
  180. participantsVals = append(participantsVals, sanAddr)
  181. fmt.Fprintf(
  182. f, " participant %s as Nebula: %s<br/>UDP: %s\n",
  183. sanAddr, e.packet.from.GetVpnIp(), sanAddr,
  184. )
  185. }
  186. if len(participantsVals) > 2 {
  187. // Get the first and last participantVals for notes
  188. participantsVals = []string{participantsVals[0], participantsVals[len(participantsVals)-1]}
  189. }
  190. // Print packets
  191. h := &header.H{}
  192. for _, e := range r.flow {
  193. if e.packet == nil {
  194. //fmt.Fprintf(f, " note over %s: %s\n", strings.Join(participantsVals, ", "), e.note)
  195. continue
  196. }
  197. p := e.packet
  198. if p.tun {
  199. fmt.Fprintln(f, r.formatUdpPacket(p))
  200. } else {
  201. if err := h.Parse(p.packet.Data); err != nil {
  202. panic(err)
  203. }
  204. line := "--x"
  205. if p.rx {
  206. line = "->>"
  207. }
  208. fmt.Fprintf(f,
  209. " %s%s%s: %s(%s), index %v, counter: %v\n",
  210. strings.Replace(p.from.GetUDPAddr(), ":", "-", 1),
  211. line,
  212. strings.Replace(p.to.GetUDPAddr(), ":", "-", 1),
  213. h.TypeName(), h.SubTypeName(), h.RemoteIndex, h.MessageCounter,
  214. )
  215. }
  216. }
  217. fmt.Fprintln(f, "```")
  218. for _, g := range r.additionalGraphs {
  219. fmt.Fprintf(f, "## %s\n", g.title)
  220. fmt.Fprintln(f, "```mermaid")
  221. fmt.Fprintln(f, g.content)
  222. fmt.Fprintln(f, "```")
  223. }
  224. }
  225. // IgnoreFlow tells the router to stop recording future flows that matches the provided criteria.
  226. // messageType and subType will target nebula underlay packets while tun will target nebula overlay packets
  227. // NOTE: This is a very broad system, if you set tun to true then no more tun traffic will be rendered
  228. func (r *R) IgnoreFlow(messageType header.MessageType, subType header.MessageSubType, tun NullBool) {
  229. r.Lock()
  230. defer r.Unlock()
  231. r.ignoreFlows = append(r.ignoreFlows, ignoreFlow{
  232. tun,
  233. messageType,
  234. subType,
  235. })
  236. }
  237. func (r *R) RenderHostmaps(title string, controls ...*nebula.Control) {
  238. r.Lock()
  239. defer r.Unlock()
  240. s := renderHostmaps(controls...)
  241. if len(r.additionalGraphs) > 0 {
  242. lastGraph := r.additionalGraphs[len(r.additionalGraphs)-1]
  243. if lastGraph.content == s && lastGraph.title == title {
  244. // Ignore this rendering if it matches the last rendering added
  245. // This is useful if you want to track rendering changes
  246. return
  247. }
  248. }
  249. r.additionalGraphs = append(r.additionalGraphs, mermaidGraph{
  250. title: title,
  251. content: s,
  252. })
  253. }
  254. func (r *R) renderHostmaps(title string) {
  255. c := maps.Values(r.controls)
  256. sort.SliceStable(c, func(i, j int) bool {
  257. return c[i].GetVpnIp() > c[j].GetVpnIp()
  258. })
  259. s := renderHostmaps(c...)
  260. if len(r.additionalGraphs) > 0 {
  261. lastGraph := r.additionalGraphs[len(r.additionalGraphs)-1]
  262. if lastGraph.content == s {
  263. // Ignore this rendering if it matches the last rendering added
  264. // This is useful if you want to track rendering changes
  265. return
  266. }
  267. }
  268. r.additionalGraphs = append(r.additionalGraphs, mermaidGraph{
  269. title: title,
  270. content: s,
  271. })
  272. }
  273. // InjectFlow can be used to record packet flow if the test is handling the routing on its own.
  274. // The packet is assumed to have been received
  275. func (r *R) InjectFlow(from, to *nebula.Control, p *udp.Packet) {
  276. r.Lock()
  277. defer r.Unlock()
  278. r.unlockedInjectFlow(from, to, p, false)
  279. }
  280. func (r *R) Log(arg ...any) {
  281. if r.flow == nil {
  282. return
  283. }
  284. r.Lock()
  285. r.flow = append(r.flow, flowEntry{note: fmt.Sprint(arg...)})
  286. r.t.Log(arg...)
  287. r.Unlock()
  288. }
  289. func (r *R) Logf(format string, arg ...any) {
  290. if r.flow == nil {
  291. return
  292. }
  293. r.Lock()
  294. r.flow = append(r.flow, flowEntry{note: fmt.Sprintf(format, arg...)})
  295. r.t.Logf(format, arg...)
  296. r.Unlock()
  297. }
  298. // unlockedInjectFlow is used by the router to record a packet has been transmitted, the packet is returned and
  299. // should be marked as received AFTER it has been placed on the receivers channel.
  300. // If flow logs have been disabled this function will return nil
  301. func (r *R) unlockedInjectFlow(from, to *nebula.Control, p *udp.Packet, tun bool) *packet {
  302. if r.flow == nil {
  303. return nil
  304. }
  305. r.renderHostmaps(fmt.Sprintf("Packet %v", len(r.flow)))
  306. if len(r.ignoreFlows) > 0 {
  307. var h header.H
  308. err := h.Parse(p.Data)
  309. if err != nil {
  310. panic(err)
  311. }
  312. for _, i := range r.ignoreFlows {
  313. if !tun {
  314. if i.messageType == h.Type && i.subType == h.Subtype {
  315. return nil
  316. }
  317. } else if i.tun.HasValue && i.tun.IsTrue {
  318. return nil
  319. }
  320. }
  321. }
  322. fp := &packet{
  323. from: from,
  324. to: to,
  325. packet: p.Copy(),
  326. tun: tun,
  327. }
  328. r.flow = append(r.flow, flowEntry{packet: fp})
  329. return fp
  330. }
  331. // OnceFrom will route a single packet from sender then return
  332. // If the router doesn't have the nebula controller for that address, we panic
  333. func (r *R) OnceFrom(sender *nebula.Control) {
  334. r.RouteExitFunc(sender, func(*udp.Packet, *nebula.Control) ExitType {
  335. return RouteAndExit
  336. })
  337. }
  338. // RouteUntilTxTun will route for sender and return when a packet is seen on receivers tun
  339. // If the router doesn't have the nebula controller for that address, we panic
  340. func (r *R) RouteUntilTxTun(sender *nebula.Control, receiver *nebula.Control) []byte {
  341. tunTx := receiver.GetTunTxChan()
  342. udpTx := sender.GetUDPTxChan()
  343. for {
  344. select {
  345. // Maybe we already have something on the tun for us
  346. case b := <-tunTx:
  347. r.Lock()
  348. np := udp.Packet{Data: make([]byte, len(b))}
  349. copy(np.Data, b)
  350. r.unlockedInjectFlow(receiver, receiver, &np, true)
  351. r.Unlock()
  352. return b
  353. // Nope, lets push the sender along
  354. case p := <-udpTx:
  355. outAddr := sender.GetUDPAddr()
  356. r.Lock()
  357. inAddr := net.JoinHostPort(p.ToIp.String(), fmt.Sprintf("%v", p.ToPort))
  358. c := r.getControl(outAddr, inAddr, p)
  359. if c == nil {
  360. r.Unlock()
  361. panic("No control for udp tx")
  362. }
  363. fp := r.unlockedInjectFlow(sender, c, p, false)
  364. c.InjectUDPPacket(p)
  365. fp.WasReceived()
  366. r.Unlock()
  367. }
  368. }
  369. }
  370. // RouteForAllUntilTxTun will route for everyone and return when a packet is seen on receivers tun
  371. // If the router doesn't have the nebula controller for that address, we panic
  372. func (r *R) RouteForAllUntilTxTun(receiver *nebula.Control) []byte {
  373. sc := make([]reflect.SelectCase, len(r.controls)+1)
  374. cm := make([]*nebula.Control, len(r.controls)+1)
  375. i := 0
  376. sc[i] = reflect.SelectCase{
  377. Dir: reflect.SelectRecv,
  378. Chan: reflect.ValueOf(receiver.GetTunTxChan()),
  379. Send: reflect.Value{},
  380. }
  381. cm[i] = receiver
  382. i++
  383. for _, c := range r.controls {
  384. sc[i] = reflect.SelectCase{
  385. Dir: reflect.SelectRecv,
  386. Chan: reflect.ValueOf(c.GetUDPTxChan()),
  387. Send: reflect.Value{},
  388. }
  389. cm[i] = c
  390. i++
  391. }
  392. for {
  393. x, rx, _ := reflect.Select(sc)
  394. r.Lock()
  395. if x == 0 {
  396. // we are the tun tx, we can exit
  397. p := rx.Interface().([]byte)
  398. np := udp.Packet{Data: make([]byte, len(p))}
  399. copy(np.Data, p)
  400. r.unlockedInjectFlow(cm[x], cm[x], &np, true)
  401. r.Unlock()
  402. return p
  403. } else {
  404. // we are a udp tx, route and continue
  405. p := rx.Interface().(*udp.Packet)
  406. outAddr := cm[x].GetUDPAddr()
  407. inAddr := net.JoinHostPort(p.ToIp.String(), fmt.Sprintf("%v", p.ToPort))
  408. c := r.getControl(outAddr, inAddr, p)
  409. if c == nil {
  410. r.Unlock()
  411. panic("No control for udp tx")
  412. }
  413. fp := r.unlockedInjectFlow(cm[x], c, p, false)
  414. c.InjectUDPPacket(p)
  415. fp.WasReceived()
  416. }
  417. r.Unlock()
  418. }
  419. }
  420. // RouteExitFunc will call the whatDo func with each udp packet from sender.
  421. // whatDo can return:
  422. // - exitNow: the packet will not be routed and this call will return immediately
  423. // - routeAndExit: this call will return immediately after routing the last packet from sender
  424. // - keepRouting: the packet will be routed and whatDo will be called again on the next packet from sender
  425. func (r *R) RouteExitFunc(sender *nebula.Control, whatDo ExitFunc) {
  426. h := &header.H{}
  427. for {
  428. p := sender.GetFromUDP(true)
  429. r.Lock()
  430. if err := h.Parse(p.Data); err != nil {
  431. panic(err)
  432. }
  433. outAddr := sender.GetUDPAddr()
  434. inAddr := net.JoinHostPort(p.ToIp.String(), fmt.Sprintf("%v", p.ToPort))
  435. receiver := r.getControl(outAddr, inAddr, p)
  436. if receiver == nil {
  437. r.Unlock()
  438. panic("Can't route for host: " + inAddr)
  439. }
  440. e := whatDo(p, receiver)
  441. switch e {
  442. case ExitNow:
  443. r.Unlock()
  444. return
  445. case RouteAndExit:
  446. fp := r.unlockedInjectFlow(sender, receiver, p, false)
  447. receiver.InjectUDPPacket(p)
  448. fp.WasReceived()
  449. r.Unlock()
  450. return
  451. case KeepRouting:
  452. fp := r.unlockedInjectFlow(sender, receiver, p, false)
  453. receiver.InjectUDPPacket(p)
  454. fp.WasReceived()
  455. default:
  456. panic(fmt.Sprintf("Unknown exitFunc return: %v", e))
  457. }
  458. r.Unlock()
  459. }
  460. }
  461. // RouteUntilAfterMsgType will route for sender until a message type is seen and sent from sender
  462. // If the router doesn't have the nebula controller for that address, we panic
  463. func (r *R) RouteUntilAfterMsgType(sender *nebula.Control, msgType header.MessageType, subType header.MessageSubType) {
  464. h := &header.H{}
  465. r.RouteExitFunc(sender, func(p *udp.Packet, r *nebula.Control) ExitType {
  466. if err := h.Parse(p.Data); err != nil {
  467. panic(err)
  468. }
  469. if h.Type == msgType && h.Subtype == subType {
  470. return RouteAndExit
  471. }
  472. return KeepRouting
  473. })
  474. }
  475. func (r *R) RouteForAllUntilAfterMsgTypeTo(receiver *nebula.Control, msgType header.MessageType, subType header.MessageSubType) {
  476. h := &header.H{}
  477. r.RouteForAllExitFunc(func(p *udp.Packet, r *nebula.Control) ExitType {
  478. if r != receiver {
  479. return KeepRouting
  480. }
  481. if err := h.Parse(p.Data); err != nil {
  482. panic(err)
  483. }
  484. if h.Type == msgType && h.Subtype == subType {
  485. return RouteAndExit
  486. }
  487. return KeepRouting
  488. })
  489. }
  490. func (r *R) InjectUDPPacket(sender, receiver *nebula.Control, packet *udp.Packet) {
  491. r.Lock()
  492. defer r.Unlock()
  493. fp := r.unlockedInjectFlow(sender, receiver, packet, false)
  494. receiver.InjectUDPPacket(packet)
  495. fp.WasReceived()
  496. }
  497. // RouteForUntilAfterToAddr will route for sender and return only after it sees and sends a packet destined for toAddr
  498. // finish can be any of the exitType values except `keepRouting`, the default value is `routeAndExit`
  499. // If the router doesn't have the nebula controller for that address, we panic
  500. func (r *R) RouteForUntilAfterToAddr(sender *nebula.Control, toAddr *net.UDPAddr, finish ExitType) {
  501. if finish == KeepRouting {
  502. finish = RouteAndExit
  503. }
  504. r.RouteExitFunc(sender, func(p *udp.Packet, r *nebula.Control) ExitType {
  505. if p.ToIp.Equal(toAddr.IP) && p.ToPort == uint16(toAddr.Port) {
  506. return finish
  507. }
  508. return KeepRouting
  509. })
  510. }
  511. // RouteForAllExitFunc will route for every registered controller and calls the whatDo func with each udp packet from
  512. // whatDo can return:
  513. // - exitNow: the packet will not be routed and this call will return immediately
  514. // - routeAndExit: this call will return immediately after routing the last packet from sender
  515. // - keepRouting: the packet will be routed and whatDo will be called again on the next packet from sender
  516. func (r *R) RouteForAllExitFunc(whatDo ExitFunc) {
  517. sc := make([]reflect.SelectCase, len(r.controls))
  518. cm := make([]*nebula.Control, len(r.controls))
  519. i := 0
  520. for _, c := range r.controls {
  521. sc[i] = reflect.SelectCase{
  522. Dir: reflect.SelectRecv,
  523. Chan: reflect.ValueOf(c.GetUDPTxChan()),
  524. Send: reflect.Value{},
  525. }
  526. cm[i] = c
  527. i++
  528. }
  529. for {
  530. x, rx, _ := reflect.Select(sc)
  531. r.Lock()
  532. p := rx.Interface().(*udp.Packet)
  533. outAddr := cm[x].GetUDPAddr()
  534. inAddr := net.JoinHostPort(p.ToIp.String(), fmt.Sprintf("%v", p.ToPort))
  535. receiver := r.getControl(outAddr, inAddr, p)
  536. if receiver == nil {
  537. r.Unlock()
  538. panic("Can't route for host: " + inAddr)
  539. }
  540. e := whatDo(p, receiver)
  541. switch e {
  542. case ExitNow:
  543. r.Unlock()
  544. return
  545. case RouteAndExit:
  546. fp := r.unlockedInjectFlow(cm[x], receiver, p, false)
  547. receiver.InjectUDPPacket(p)
  548. fp.WasReceived()
  549. r.Unlock()
  550. return
  551. case KeepRouting:
  552. fp := r.unlockedInjectFlow(cm[x], receiver, p, false)
  553. receiver.InjectUDPPacket(p)
  554. fp.WasReceived()
  555. default:
  556. panic(fmt.Sprintf("Unknown exitFunc return: %v", e))
  557. }
  558. r.Unlock()
  559. }
  560. }
  561. // FlushAll will route for every registered controller, exiting once there are no packets left to route
  562. func (r *R) FlushAll() {
  563. sc := make([]reflect.SelectCase, len(r.controls))
  564. cm := make([]*nebula.Control, len(r.controls))
  565. i := 0
  566. for _, c := range r.controls {
  567. sc[i] = reflect.SelectCase{
  568. Dir: reflect.SelectRecv,
  569. Chan: reflect.ValueOf(c.GetUDPTxChan()),
  570. Send: reflect.Value{},
  571. }
  572. cm[i] = c
  573. i++
  574. }
  575. // Add a default case to exit when nothing is left to send
  576. sc = append(sc, reflect.SelectCase{
  577. Dir: reflect.SelectDefault,
  578. Chan: reflect.Value{},
  579. Send: reflect.Value{},
  580. })
  581. for {
  582. x, rx, ok := reflect.Select(sc)
  583. if !ok {
  584. return
  585. }
  586. r.Lock()
  587. p := rx.Interface().(*udp.Packet)
  588. outAddr := cm[x].GetUDPAddr()
  589. inAddr := net.JoinHostPort(p.ToIp.String(), fmt.Sprintf("%v", p.ToPort))
  590. receiver := r.getControl(outAddr, inAddr, p)
  591. if receiver == nil {
  592. r.Unlock()
  593. panic("Can't route for host: " + inAddr)
  594. }
  595. r.Unlock()
  596. }
  597. }
  598. // getControl performs or seeds NAT translation and returns the control for toAddr, p from fields may change
  599. // This is an internal router function, the caller must hold the lock
  600. func (r *R) getControl(fromAddr, toAddr string, p *udp.Packet) *nebula.Control {
  601. if newAddr, ok := r.outNat[fromAddr+":"+toAddr]; ok {
  602. p.FromIp = newAddr.IP
  603. p.FromPort = uint16(newAddr.Port)
  604. }
  605. c, ok := r.inNat[toAddr]
  606. if ok {
  607. sHost, sPort, err := net.SplitHostPort(toAddr)
  608. if err != nil {
  609. panic(err)
  610. }
  611. port, err := strconv.Atoi(sPort)
  612. if err != nil {
  613. panic(err)
  614. }
  615. r.outNat[c.GetUDPAddr()+":"+fromAddr] = net.UDPAddr{
  616. IP: net.ParseIP(sHost),
  617. Port: port,
  618. }
  619. return c
  620. }
  621. return r.controls[toAddr]
  622. }
  623. func (r *R) formatUdpPacket(p *packet) string {
  624. packet := gopacket.NewPacket(p.packet.Data, layers.LayerTypeIPv4, gopacket.Lazy)
  625. v4 := packet.Layer(layers.LayerTypeIPv4).(*layers.IPv4)
  626. if v4 == nil {
  627. panic("not an ipv4 packet")
  628. }
  629. from := "unknown"
  630. if c, ok := r.vpnControls[iputil.Ip2VpnIp(v4.SrcIP)]; ok {
  631. from = c.GetUDPAddr()
  632. }
  633. udp := packet.Layer(layers.LayerTypeUDP).(*layers.UDP)
  634. if udp == nil {
  635. panic("not a udp packet")
  636. }
  637. data := packet.ApplicationLayer()
  638. return fmt.Sprintf(
  639. " %s-->>%s: src port: %v<br/>dest port: %v<br/>data: \"%v\"\n",
  640. strings.Replace(from, ":", "-", 1),
  641. strings.Replace(p.to.GetUDPAddr(), ":", "-", 1),
  642. udp.SrcPort,
  643. udp.DstPort,
  644. string(data.Payload()),
  645. )
  646. }