router.go 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897
  1. //go:build e2e_testing
  2. // +build e2e_testing
  3. package router
  4. import (
  5. "context"
  6. "fmt"
  7. "net/netip"
  8. "os"
  9. "path/filepath"
  10. "reflect"
  11. "regexp"
  12. "sort"
  13. "sync"
  14. "sync/atomic"
  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/udp"
  22. "golang.org/x/exp/maps"
  23. )
  24. // outNatKey is the (from, to) pair used by outNat. Comparable struct, so it works as a map key without the
  25. // allocation cost of a string-concat key.
  26. type outNatKey struct {
  27. from, to netip.AddrPort
  28. }
  29. // fannedPacket pairs a UDP TX packet with its source control so the router can route it after popping from
  30. // the fan-in channel.
  31. type fannedPacket struct {
  32. from *nebula.Control
  33. pkt *udp.Packet
  34. }
  35. type R struct {
  36. // Simple map of the ip:port registered on a control to the control
  37. // Basically a router, right?
  38. controls map[netip.AddrPort]*nebula.Control
  39. // A map for inbound packets for a control that doesn't know about this address
  40. inNat map[netip.AddrPort]*nebula.Control
  41. // A last used map, if an inbound packet hit the inNat map then
  42. // all return packets should use the same last used inbound address for the outbound sender
  43. outNat map[outNatKey]netip.AddrPort
  44. // A map of vpn ip to the nebula control it belongs to
  45. vpnControls map[netip.Addr]*nebula.Control
  46. // Cached select infrastructure for RouteForAllUntilTxTun.
  47. // The controls map is immutable after NewR so the cases are good for the test lifetime.
  48. // We only rebuild if a different receiver is asked.
  49. selRecvCtl *nebula.Control
  50. selCases []reflect.SelectCase
  51. selCtls []*nebula.Control
  52. // Optional fan-in mode for hot-path benchmarks: one forwarder goroutine per control drains UDP TX into udpFanIn,
  53. // so RouteForAllUntilTxTun can do a fixed 2-way native select instead of paying reflect.Select per call.
  54. // Off by default (would otherwise interleave with tests that use GetFromUDP directly on the same control).
  55. // Enabled by EnableFanIn.
  56. udpFanIn chan fannedPacket
  57. stopFanIn chan struct{}
  58. fanInWG sync.WaitGroup
  59. fanInMu sync.Mutex
  60. fanInOn atomic.Bool
  61. ignoreFlows []ignoreFlow
  62. flow []flowEntry
  63. // A set of additional mermaid graphs to draw in the flow log markdown file
  64. // Currently consisting only of hostmap renders
  65. additionalGraphs []mermaidGraph
  66. // All interactions are locked to help serialize behavior
  67. sync.Mutex
  68. fn string
  69. cancelRender context.CancelFunc
  70. t testing.TB
  71. }
  72. type ignoreFlow struct {
  73. tun NullBool
  74. messageType header.MessageType
  75. subType header.MessageSubType
  76. //from
  77. //to
  78. }
  79. type mermaidGraph struct {
  80. title string
  81. content string
  82. }
  83. type NullBool struct {
  84. HasValue bool
  85. IsTrue bool
  86. }
  87. type flowEntry struct {
  88. note string
  89. packet *packet
  90. }
  91. type packet struct {
  92. from *nebula.Control
  93. to *nebula.Control
  94. packet *udp.Packet
  95. tun bool // a packet pulled off a tun device
  96. rx bool // the packet was received by a udp device
  97. }
  98. func (p *packet) WasReceived() {
  99. if p != nil {
  100. p.rx = true
  101. }
  102. }
  103. type ExitType int
  104. const (
  105. // KeepRouting the function will get called again on the next packet
  106. KeepRouting ExitType = 0
  107. // ExitNow does not route this packet and exits immediately
  108. ExitNow ExitType = 1
  109. // RouteAndExit routes this packet and exits immediately afterwards
  110. RouteAndExit ExitType = 2
  111. )
  112. type ExitFunc func(packet *udp.Packet, receiver *nebula.Control) ExitType
  113. // NewR creates a new router to pass packets in a controlled fashion between the provided controllers.
  114. // The packet flow will be recorded in a file within the mermaid directory under the same name as the test.
  115. // Renders will occur automatically, roughly every 100ms, until a call to RenderFlow() is made
  116. func NewR(t testing.TB, controls ...*nebula.Control) *R {
  117. ctx, cancel := context.WithCancel(context.Background())
  118. if err := os.MkdirAll("mermaid", 0755); err != nil {
  119. panic(err)
  120. }
  121. r := &R{
  122. controls: make(map[netip.AddrPort]*nebula.Control),
  123. vpnControls: make(map[netip.Addr]*nebula.Control),
  124. inNat: make(map[netip.AddrPort]*nebula.Control),
  125. outNat: make(map[outNatKey]netip.AddrPort),
  126. flow: []flowEntry{},
  127. ignoreFlows: []ignoreFlow{},
  128. fn: filepath.Join("mermaid", fmt.Sprintf("%s.md", t.Name())),
  129. t: t,
  130. cancelRender: cancel,
  131. }
  132. // Try to remove our render file
  133. os.Remove(r.fn)
  134. for _, c := range controls {
  135. addr := c.GetUDPAddr()
  136. if _, ok := r.controls[addr]; ok {
  137. panic("Duplicate listen address: " + addr.String())
  138. }
  139. for _, vpnAddr := range c.GetVpnAddrs() {
  140. r.vpnControls[vpnAddr] = c
  141. }
  142. r.controls[addr] = c
  143. }
  144. // Spin the renderer in case we go nuts and the test never completes
  145. go func() {
  146. clockSource := time.NewTicker(time.Millisecond * 100)
  147. defer clockSource.Stop()
  148. for {
  149. select {
  150. case <-ctx.Done():
  151. return
  152. case <-clockSource.C:
  153. r.Lock()
  154. r.renderHostmaps("clock tick")
  155. r.renderFlow()
  156. r.Unlock()
  157. }
  158. }
  159. }()
  160. return r
  161. }
  162. // AddRoute will place the nebula controller at the ip and port specified.
  163. // It does not look at the addr attached to the instance.
  164. // If a route is used, this will behave like a NAT for the return path.
  165. // Rewriting the source ip:port to what was last sent to from the origin
  166. func (r *R) AddRoute(ip netip.Addr, port uint16, c *nebula.Control) {
  167. r.Lock()
  168. defer r.Unlock()
  169. inAddr := netip.AddrPortFrom(ip, port)
  170. if _, ok := r.inNat[inAddr]; ok {
  171. panic("Duplicate listen address inNat: " + inAddr.String())
  172. }
  173. r.inNat[inAddr] = c
  174. }
  175. // RenderFlow renders the packet flow seen up until now and stops further automatic renders from happening.
  176. func (r *R) RenderFlow() {
  177. r.cancelRender()
  178. r.Lock()
  179. defer r.Unlock()
  180. r.renderFlow()
  181. }
  182. // CancelFlowLogs stops flow logs from being tracked and destroys any logs already collected
  183. func (r *R) CancelFlowLogs() {
  184. r.cancelRender()
  185. r.Lock()
  186. r.flow = nil
  187. r.Unlock()
  188. }
  189. // renderFlow writes the flow log to disk. Caller must hold r.Lock. renderFlow reads r.flow / r.additionalGraphs and
  190. // the *packet pointers stashed inside, all of which are mutated under the same lock by routing paths.
  191. func (r *R) renderFlow() {
  192. if r.flow == nil {
  193. return
  194. }
  195. f, err := os.OpenFile(r.fn, os.O_CREATE|os.O_TRUNC|os.O_RDWR, 0644)
  196. if err != nil {
  197. panic(err)
  198. }
  199. var participants = map[netip.AddrPort]struct{}{}
  200. var participantsVals []string
  201. fmt.Fprintln(f, "```mermaid")
  202. fmt.Fprintln(f, "sequenceDiagram")
  203. // Assemble participants
  204. for _, e := range r.flow {
  205. if e.packet == nil {
  206. continue
  207. }
  208. addr := e.packet.from.GetUDPAddr()
  209. if _, ok := participants[addr]; ok {
  210. continue
  211. }
  212. participants[addr] = struct{}{}
  213. sanAddr := normalizeName(addr.String())
  214. participantsVals = append(participantsVals, sanAddr)
  215. fmt.Fprintf(
  216. f, " participant %s as Nebula: %s<br/>UDP: %s\n",
  217. sanAddr, e.packet.from.GetVpnAddrs(), sanAddr,
  218. )
  219. }
  220. if len(participantsVals) > 2 {
  221. // Get the first and last participantVals for notes
  222. participantsVals = []string{participantsVals[0], participantsVals[len(participantsVals)-1]}
  223. }
  224. // Print packets
  225. h := &header.H{}
  226. for _, e := range r.flow {
  227. if e.packet == nil {
  228. //fmt.Fprintf(f, " note over %s: %s\n", strings.Join(participantsVals, ", "), e.note)
  229. continue
  230. }
  231. p := e.packet
  232. if p.tun {
  233. fmt.Fprintln(f, r.formatUdpPacket(p))
  234. } else {
  235. if err := h.Parse(p.packet.Data); err != nil {
  236. panic(err)
  237. }
  238. line := "--x"
  239. if p.rx {
  240. line = "->>"
  241. }
  242. fmt.Fprintf(f,
  243. " %s%s%s: %s(%s), index %v, counter: %v\n",
  244. normalizeName(p.from.GetUDPAddr().String()),
  245. line,
  246. normalizeName(p.to.GetUDPAddr().String()),
  247. h.TypeName(), h.SubTypeName(), h.RemoteIndex, h.MessageCounter,
  248. )
  249. }
  250. }
  251. fmt.Fprintln(f, "```")
  252. for _, g := range r.additionalGraphs {
  253. fmt.Fprintf(f, "## %s\n", g.title)
  254. fmt.Fprintln(f, "```mermaid")
  255. fmt.Fprintln(f, g.content)
  256. fmt.Fprintln(f, "```")
  257. }
  258. }
  259. func normalizeName(s string) string {
  260. rx := regexp.MustCompile("[\\[\\]\\:]")
  261. return rx.ReplaceAllLiteralString(s, "_")
  262. }
  263. // IgnoreFlow tells the router to stop recording future flows that matches the provided criteria.
  264. // messageType and subType will target nebula underlay packets while tun will target nebula overlay packets
  265. // NOTE: This is a very broad system, if you set tun to true then no more tun traffic will be rendered
  266. func (r *R) IgnoreFlow(messageType header.MessageType, subType header.MessageSubType, tun NullBool) {
  267. r.Lock()
  268. defer r.Unlock()
  269. r.ignoreFlows = append(r.ignoreFlows, ignoreFlow{
  270. tun,
  271. messageType,
  272. subType,
  273. })
  274. }
  275. func (r *R) RenderHostmaps(title string, controls ...*nebula.Control) {
  276. r.Lock()
  277. defer r.Unlock()
  278. s := renderHostmaps(controls...)
  279. if len(r.additionalGraphs) > 0 {
  280. lastGraph := r.additionalGraphs[len(r.additionalGraphs)-1]
  281. if lastGraph.content == s && lastGraph.title == title {
  282. // Ignore this rendering if it matches the last rendering added
  283. // This is useful if you want to track rendering changes
  284. return
  285. }
  286. }
  287. r.additionalGraphs = append(r.additionalGraphs, mermaidGraph{
  288. title: title,
  289. content: s,
  290. })
  291. }
  292. func (r *R) renderHostmaps(title string) {
  293. c := maps.Values(r.controls)
  294. sort.SliceStable(c, func(i, j int) bool {
  295. return c[i].GetVpnAddrs()[0].Compare(c[j].GetVpnAddrs()[0]) > 0
  296. })
  297. s := renderHostmaps(c...)
  298. if len(r.additionalGraphs) > 0 {
  299. lastGraph := r.additionalGraphs[len(r.additionalGraphs)-1]
  300. if lastGraph.content == s {
  301. // Ignore this rendering if it matches the last rendering added
  302. // This is useful if you want to track rendering changes
  303. return
  304. }
  305. }
  306. r.additionalGraphs = append(r.additionalGraphs, mermaidGraph{
  307. title: title,
  308. content: s,
  309. })
  310. }
  311. // InjectFlow can be used to record packet flow if the test is handling the routing on its own.
  312. // The packet is assumed to have been received
  313. func (r *R) InjectFlow(from, to *nebula.Control, p *udp.Packet) {
  314. r.Lock()
  315. defer r.Unlock()
  316. r.unlockedInjectFlow(from, to, p, false)
  317. }
  318. func (r *R) Log(arg ...any) {
  319. if r.flow == nil {
  320. return
  321. }
  322. r.Lock()
  323. r.flow = append(r.flow, flowEntry{note: fmt.Sprint(arg...)})
  324. r.t.Log(arg...)
  325. r.Unlock()
  326. }
  327. func (r *R) Logf(format string, arg ...any) {
  328. if r.flow == nil {
  329. return
  330. }
  331. r.Lock()
  332. r.flow = append(r.flow, flowEntry{note: fmt.Sprintf(format, arg...)})
  333. r.t.Logf(format, arg...)
  334. r.Unlock()
  335. }
  336. // unlockedInjectFlow is used by the router to record a packet has been transmitted, the packet is returned and
  337. // should be marked as received AFTER it has been placed on the receivers channel.
  338. // If flow logs have been disabled this function will return nil
  339. func (r *R) unlockedInjectFlow(from, to *nebula.Control, p *udp.Packet, tun bool) *packet {
  340. if r.flow == nil {
  341. return nil
  342. }
  343. r.renderHostmaps(fmt.Sprintf("Packet %v", len(r.flow)))
  344. if len(r.ignoreFlows) > 0 {
  345. var h header.H
  346. err := h.Parse(p.Data)
  347. if err != nil {
  348. panic(err)
  349. }
  350. for _, i := range r.ignoreFlows {
  351. if !tun {
  352. if i.messageType == h.Type && i.subType == h.Subtype {
  353. return nil
  354. }
  355. } else if i.tun.HasValue && i.tun.IsTrue {
  356. return nil
  357. }
  358. }
  359. }
  360. fp := &packet{
  361. from: from,
  362. to: to,
  363. packet: p.Copy(),
  364. tun: tun,
  365. }
  366. r.flow = append(r.flow, flowEntry{packet: fp})
  367. return fp
  368. }
  369. // OnceFrom will route a single packet from sender then return
  370. // If the router doesn't have the nebula controller for that address, we panic
  371. func (r *R) OnceFrom(sender *nebula.Control) {
  372. r.RouteExitFunc(sender, func(*udp.Packet, *nebula.Control) ExitType {
  373. return RouteAndExit
  374. })
  375. }
  376. // RouteUntilTxTun will route for sender and return when a packet is seen on receivers tun
  377. // If the router doesn't have the nebula controller for that address, we panic
  378. func (r *R) RouteUntilTxTun(sender *nebula.Control, receiver *nebula.Control) []byte {
  379. tunTx := receiver.GetTunTxChan()
  380. udpTx := sender.GetUDPTxChan()
  381. for {
  382. select {
  383. // Maybe we already have something on the tun for us
  384. case b := <-tunTx:
  385. r.Lock()
  386. np := udp.Packet{Data: make([]byte, len(b))}
  387. copy(np.Data, b)
  388. r.unlockedInjectFlow(receiver, receiver, &np, true)
  389. r.Unlock()
  390. return b
  391. // Nope, lets push the sender along
  392. case p := <-udpTx:
  393. r.Lock()
  394. a := sender.GetUDPAddr()
  395. c := r.getControl(a, p.To, p)
  396. if c == nil {
  397. r.Unlock()
  398. panic("No control for udp tx " + a.String())
  399. }
  400. fp := r.unlockedInjectFlow(sender, c, p, false)
  401. c.InjectUDPPacket(p) // copies internally; original is ours to release
  402. fp.WasReceived()
  403. r.Unlock()
  404. p.Release()
  405. }
  406. }
  407. }
  408. // RouteForAllUntilTxTun will route for everyone and return when a packet is seen on the receiver's tun.
  409. // If a control's UDP TX address can't be matched to a registered control, we panic.
  410. //
  411. // For allocation-sensitive callers (hot-path benchmarks, in particular relay
  412. // benches with 3+ controls), call EnableFanIn() first.
  413. func (r *R) RouteForAllUntilTxTun(receiver *nebula.Control) []byte {
  414. if r.fanInOn.Load() {
  415. return r.routeFanIn(receiver)
  416. }
  417. return r.routeReflect(receiver)
  418. }
  419. // routeFanIn is the alloc-free path used when EnableFanIn is in effect.
  420. func (r *R) routeFanIn(receiver *nebula.Control) []byte {
  421. tunTx := receiver.GetTunTxChan()
  422. for {
  423. select {
  424. case p := <-tunTx:
  425. r.Lock()
  426. if r.flow != nil {
  427. np := udp.Packet{Data: make([]byte, len(p))}
  428. copy(np.Data, p)
  429. r.unlockedInjectFlow(receiver, receiver, &np, true)
  430. }
  431. r.Unlock()
  432. return p
  433. case fp := <-r.udpFanIn:
  434. r.routeUDP(fp.from, fp.pkt)
  435. }
  436. }
  437. }
  438. // routeReflect is the default reflect.Select-based path. Pays the boxing allocation per call but doesn't interfere
  439. // with tests that pull packets directly from controls' UDP TX channels via GetFromUDP.
  440. func (r *R) routeReflect(receiver *nebula.Control) []byte {
  441. sc, cm := r.selectCasesFor(receiver)
  442. for {
  443. x, rx, _ := reflect.Select(sc)
  444. if x == 0 {
  445. p := rx.Interface().([]byte)
  446. r.Lock()
  447. if r.flow != nil {
  448. np := udp.Packet{Data: make([]byte, len(p))}
  449. copy(np.Data, p)
  450. r.unlockedInjectFlow(cm[x], cm[x], &np, true)
  451. }
  452. r.Unlock()
  453. return p
  454. }
  455. r.routeUDP(cm[x], rx.Interface().(*udp.Packet))
  456. }
  457. }
  458. // EnableFanIn switches RouteForAllUntilTxTun to the alloc-free fan-in path.
  459. // One forwarder goroutine per registered control drains UDP TX into a shared channel that RouteForAllUntilTxTun selects
  460. // on alongside the receiver's TUN TX channel.
  461. func (r *R) EnableFanIn() {
  462. r.fanInMu.Lock()
  463. defer r.fanInMu.Unlock()
  464. if r.fanInOn.Load() {
  465. return
  466. }
  467. r.udpFanIn = make(chan fannedPacket, 32)
  468. r.stopFanIn = make(chan struct{})
  469. for _, c := range r.controls {
  470. r.startFanInWorker(c)
  471. }
  472. r.fanInOn.Store(true)
  473. r.t.Cleanup(r.stopFanInWorkers)
  474. }
  475. // startFanInWorker spawns a goroutine that drains c's UDP TX into r.udpFanIn.
  476. func (r *R) startFanInWorker(c *nebula.Control) {
  477. r.fanInWG.Add(1)
  478. udpTx := c.GetUDPTxChan()
  479. go func() {
  480. defer r.fanInWG.Done()
  481. for {
  482. select {
  483. case <-r.stopFanIn:
  484. return
  485. case p := <-udpTx:
  486. select {
  487. case <-r.stopFanIn:
  488. p.Release()
  489. return
  490. case r.udpFanIn <- fannedPacket{from: c, pkt: p}:
  491. }
  492. }
  493. }
  494. }()
  495. }
  496. // stopFanInWorkers signals the fan-in goroutines to exit and waits for them.
  497. func (r *R) stopFanInWorkers() {
  498. r.fanInMu.Lock()
  499. wasOn := r.fanInOn.Swap(false)
  500. r.fanInMu.Unlock()
  501. if !wasOn {
  502. return
  503. }
  504. close(r.stopFanIn)
  505. r.fanInWG.Wait()
  506. }
  507. // routeUDP forwards a UDP TX packet from the named source control to the destination control derived from p.To,
  508. // releasing the source packet after InjectUDPPacket has copied its bytes into a fresh pool slot.
  509. func (r *R) routeUDP(from *nebula.Control, p *udp.Packet) {
  510. r.Lock()
  511. defer r.Unlock()
  512. a := from.GetUDPAddr()
  513. c := r.getControl(a, p.To, p)
  514. if c == nil {
  515. panic(fmt.Sprintf("No control for udp tx %s", p.To))
  516. }
  517. fp := r.unlockedInjectFlow(from, c, p, false)
  518. c.InjectUDPPacket(p) // copies internally; original is ours to release
  519. fp.WasReceived()
  520. p.Release()
  521. }
  522. // selectCasesFor returns the SelectCase array used by routeReflect: one slot for the receiver's TUN TX channel followed
  523. // by one per control's UDP TX channel. Cached for the test lifetime, only rebuilt if the receiver changes.
  524. func (r *R) selectCasesFor(receiver *nebula.Control) ([]reflect.SelectCase, []*nebula.Control) {
  525. r.Lock()
  526. defer r.Unlock()
  527. if r.selRecvCtl == receiver && r.selCases != nil {
  528. return r.selCases, r.selCtls
  529. }
  530. sc := make([]reflect.SelectCase, len(r.controls)+1)
  531. cm := make([]*nebula.Control, len(r.controls)+1)
  532. sc[0] = reflect.SelectCase{Dir: reflect.SelectRecv, Chan: reflect.ValueOf(receiver.GetTunTxChan())}
  533. cm[0] = receiver
  534. i := 1
  535. for _, c := range r.controls {
  536. sc[i] = reflect.SelectCase{Dir: reflect.SelectRecv, Chan: reflect.ValueOf(c.GetUDPTxChan())}
  537. cm[i] = c
  538. i++
  539. }
  540. r.selRecvCtl = receiver
  541. r.selCases = sc
  542. r.selCtls = cm
  543. return sc, cm
  544. }
  545. // RouteExitFunc will call the whatDo func with each udp packet from sender.
  546. // whatDo can return:
  547. // - exitNow: the packet will not be routed and this call will return immediately
  548. // - routeAndExit: this call will return immediately after routing the last packet from sender
  549. // - keepRouting: the packet will be routed and whatDo will be called again on the next packet from sender
  550. func (r *R) RouteExitFunc(sender *nebula.Control, whatDo ExitFunc) {
  551. h := &header.H{}
  552. for {
  553. p := sender.GetFromUDP(true)
  554. r.Lock()
  555. if err := h.Parse(p.Data); err != nil {
  556. panic(err)
  557. }
  558. receiver := r.getControl(sender.GetUDPAddr(), p.To, p)
  559. if receiver == nil {
  560. r.Unlock()
  561. panic("Can't RouteExitFunc for host: " + p.To.String())
  562. }
  563. e := whatDo(p, receiver)
  564. switch e {
  565. case ExitNow:
  566. r.Unlock()
  567. p.Release()
  568. return
  569. case RouteAndExit:
  570. fp := r.unlockedInjectFlow(sender, receiver, p, false)
  571. receiver.InjectUDPPacket(p)
  572. fp.WasReceived()
  573. r.Unlock()
  574. p.Release()
  575. return
  576. case KeepRouting:
  577. fp := r.unlockedInjectFlow(sender, receiver, p, false)
  578. receiver.InjectUDPPacket(p)
  579. fp.WasReceived()
  580. default:
  581. panic(fmt.Sprintf("Unknown exitFunc return: %v", e))
  582. }
  583. r.Unlock()
  584. p.Release()
  585. }
  586. }
  587. // RouteUntilAfterMsgType will route for sender until a message type is seen and sent from sender
  588. // If the router doesn't have the nebula controller for that address, we panic
  589. func (r *R) RouteUntilAfterMsgType(sender *nebula.Control, msgType header.MessageType, subType header.MessageSubType) {
  590. h := &header.H{}
  591. r.RouteExitFunc(sender, func(p *udp.Packet, r *nebula.Control) ExitType {
  592. if err := h.Parse(p.Data); err != nil {
  593. panic(err)
  594. }
  595. if h.Type == msgType && h.Subtype == subType {
  596. return RouteAndExit
  597. }
  598. return KeepRouting
  599. })
  600. }
  601. func (r *R) RouteForAllUntilAfterMsgTypeTo(receiver *nebula.Control, msgType header.MessageType, subType header.MessageSubType) {
  602. h := &header.H{}
  603. r.RouteForAllExitFunc(func(p *udp.Packet, r *nebula.Control) ExitType {
  604. if r != receiver {
  605. return KeepRouting
  606. }
  607. if err := h.Parse(p.Data); err != nil {
  608. panic(err)
  609. }
  610. if h.Type == msgType && h.Subtype == subType {
  611. return RouteAndExit
  612. }
  613. return KeepRouting
  614. })
  615. }
  616. func (r *R) InjectUDPPacket(sender, receiver *nebula.Control, packet *udp.Packet) {
  617. r.Lock()
  618. defer r.Unlock()
  619. fp := r.unlockedInjectFlow(sender, receiver, packet, false)
  620. receiver.InjectUDPPacket(packet)
  621. fp.WasReceived()
  622. }
  623. // RouteForUntilAfterToAddr will route for sender and return only after it sees and sends a packet destined for toAddr
  624. // finish can be any of the exitType values except `keepRouting`, the default value is `routeAndExit`
  625. // If the router doesn't have the nebula controller for that address, we panic
  626. func (r *R) RouteForUntilAfterToAddr(sender *nebula.Control, toAddr netip.AddrPort, finish ExitType) {
  627. if finish == KeepRouting {
  628. finish = RouteAndExit
  629. }
  630. r.RouteExitFunc(sender, func(p *udp.Packet, r *nebula.Control) ExitType {
  631. if p.To == toAddr {
  632. return finish
  633. }
  634. return KeepRouting
  635. })
  636. }
  637. // RouteForAllExitFunc will route for every registered controller and calls the whatDo func with each udp packet from
  638. // whatDo can return:
  639. // - exitNow: the packet will not be routed and this call will return immediately
  640. // - routeAndExit: this call will return immediately after routing the last packet from sender
  641. // - keepRouting: the packet will be routed and whatDo will be called again on the next packet from sender
  642. func (r *R) RouteForAllExitFunc(whatDo ExitFunc) {
  643. sc := make([]reflect.SelectCase, len(r.controls))
  644. cm := make([]*nebula.Control, len(r.controls))
  645. i := 0
  646. for _, c := range r.controls {
  647. sc[i] = reflect.SelectCase{
  648. Dir: reflect.SelectRecv,
  649. Chan: reflect.ValueOf(c.GetUDPTxChan()),
  650. Send: reflect.Value{},
  651. }
  652. cm[i] = c
  653. i++
  654. }
  655. for {
  656. x, rx, _ := reflect.Select(sc)
  657. r.Lock()
  658. p := rx.Interface().(*udp.Packet)
  659. receiver := r.getControl(cm[x].GetUDPAddr(), p.To, p)
  660. if receiver == nil {
  661. r.Unlock()
  662. panic("Can't RouteForAllExitFunc for host: " + p.To.String())
  663. }
  664. e := whatDo(p, receiver)
  665. switch e {
  666. case ExitNow:
  667. r.Unlock()
  668. p.Release()
  669. return
  670. case RouteAndExit:
  671. fp := r.unlockedInjectFlow(cm[x], receiver, p, false)
  672. receiver.InjectUDPPacket(p)
  673. fp.WasReceived()
  674. r.Unlock()
  675. p.Release()
  676. return
  677. case KeepRouting:
  678. fp := r.unlockedInjectFlow(cm[x], receiver, p, false)
  679. receiver.InjectUDPPacket(p)
  680. fp.WasReceived()
  681. default:
  682. panic(fmt.Sprintf("Unknown exitFunc return: %v", e))
  683. }
  684. r.Unlock()
  685. p.Release()
  686. }
  687. }
  688. // FlushAll will route for every registered controller, exiting once there are no packets left to route
  689. func (r *R) FlushAll() {
  690. sc := make([]reflect.SelectCase, len(r.controls))
  691. cm := make([]*nebula.Control, len(r.controls))
  692. i := 0
  693. for _, c := range r.controls {
  694. sc[i] = reflect.SelectCase{
  695. Dir: reflect.SelectRecv,
  696. Chan: reflect.ValueOf(c.GetUDPTxChan()),
  697. Send: reflect.Value{},
  698. }
  699. cm[i] = c
  700. i++
  701. }
  702. // Add a default case to exit when nothing is left to send
  703. sc = append(sc, reflect.SelectCase{
  704. Dir: reflect.SelectDefault,
  705. Chan: reflect.Value{},
  706. Send: reflect.Value{},
  707. })
  708. for {
  709. x, rx, ok := reflect.Select(sc)
  710. if !ok {
  711. return
  712. }
  713. r.Lock()
  714. p := rx.Interface().(*udp.Packet)
  715. receiver := r.getControl(cm[x].GetUDPAddr(), p.To, p)
  716. if receiver == nil {
  717. r.Unlock()
  718. panic("Can't FlushAll for host: " + p.To.String())
  719. }
  720. receiver.InjectUDPPacket(p)
  721. r.Unlock()
  722. p.Release()
  723. }
  724. }
  725. // getControl performs or seeds NAT translation and returns the control for toAddr, p from fields may change
  726. // This is an internal router function, the caller must hold the lock
  727. func (r *R) getControl(fromAddr, toAddr netip.AddrPort, p *udp.Packet) *nebula.Control {
  728. if newAddr, ok := r.outNat[outNatKey{from: fromAddr, to: toAddr}]; ok {
  729. p.From = newAddr
  730. }
  731. c, ok := r.inNat[toAddr]
  732. if ok {
  733. r.outNat[outNatKey{from: c.GetUDPAddr(), to: fromAddr}] = toAddr
  734. return c
  735. }
  736. return r.controls[toAddr]
  737. }
  738. func (r *R) formatUdpPacket(p *packet) string {
  739. var packet gopacket.Packet
  740. var srcAddr netip.Addr
  741. packet = gopacket.NewPacket(p.packet.Data, layers.LayerTypeIPv6, gopacket.Lazy)
  742. if packet.ErrorLayer() == nil {
  743. v6 := packet.Layer(layers.LayerTypeIPv6).(*layers.IPv6)
  744. if v6 == nil {
  745. panic("not an ipv6 packet")
  746. }
  747. srcAddr, _ = netip.AddrFromSlice(v6.SrcIP)
  748. } else {
  749. packet = gopacket.NewPacket(p.packet.Data, layers.LayerTypeIPv4, gopacket.Lazy)
  750. v6 := packet.Layer(layers.LayerTypeIPv4).(*layers.IPv4)
  751. if v6 == nil {
  752. panic("not an ipv6 packet")
  753. }
  754. srcAddr, _ = netip.AddrFromSlice(v6.SrcIP)
  755. }
  756. from := "unknown"
  757. if c, ok := r.vpnControls[srcAddr]; ok {
  758. from = c.GetUDPAddr().String()
  759. }
  760. udpLayer := packet.Layer(layers.LayerTypeUDP).(*layers.UDP)
  761. if udpLayer == nil {
  762. panic("not a udp packet")
  763. }
  764. data := packet.ApplicationLayer()
  765. return fmt.Sprintf(
  766. " %s-->>%s: src port: %v<br/>dest port: %v<br/>data: \"%v\"\n",
  767. normalizeName(from),
  768. normalizeName(p.to.GetUDPAddr().String()),
  769. udpLayer.SrcPort,
  770. udpLayer.DstPort,
  771. string(data.Payload()),
  772. )
  773. }