router.go 19 KB

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