tun_disabled.go 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. package overlay
  2. import (
  3. "context"
  4. "fmt"
  5. "io"
  6. "log/slog"
  7. "net/netip"
  8. "strings"
  9. "github.com/rcrowley/go-metrics"
  10. "github.com/slackhq/nebula/iputil"
  11. "github.com/slackhq/nebula/overlay/tio"
  12. "github.com/slackhq/nebula/routing"
  13. )
  14. type disabledTun struct {
  15. read chan []byte
  16. vpnNetworks []netip.Prefix
  17. // Track these metrics since we don't have the tun device to do it for us
  18. tx metrics.Counter
  19. rx metrics.Counter
  20. l *slog.Logger
  21. numReaders int
  22. batchRet [1][]byte
  23. }
  24. func (t *disabledTun) Read() ([][]byte, error) {
  25. r, ok := <-t.read
  26. if !ok {
  27. return nil, io.EOF
  28. }
  29. t.tx.Inc(1)
  30. if t.l.Enabled(context.Background(), slog.LevelDebug) {
  31. t.l.Debug("Write payload", "raw", prettyPacket(r))
  32. }
  33. t.batchRet[0] = r
  34. return t.batchRet[:], nil
  35. }
  36. func newDisabledTun(vpnNetworks []netip.Prefix, queueLen int, metricsEnabled bool, l *slog.Logger) *disabledTun {
  37. tun := &disabledTun{
  38. vpnNetworks: vpnNetworks,
  39. read: make(chan []byte, queueLen),
  40. l: l,
  41. numReaders: 1,
  42. }
  43. if metricsEnabled {
  44. tun.tx = metrics.GetOrRegisterCounter("messages.tx.message", nil)
  45. tun.rx = metrics.GetOrRegisterCounter("messages.rx.message", nil)
  46. } else {
  47. tun.tx = &metrics.NilCounter{}
  48. tun.rx = &metrics.NilCounter{}
  49. }
  50. return tun
  51. }
  52. func (*disabledTun) Activate() error {
  53. return nil
  54. }
  55. func (*disabledTun) RoutesFor(addr netip.Addr) routing.Gateways {
  56. return routing.Gateways{}
  57. }
  58. func (t *disabledTun) Networks() []netip.Prefix {
  59. return t.vpnNetworks
  60. }
  61. func (*disabledTun) Name() string {
  62. return "disabled"
  63. }
  64. func (t *disabledTun) handleICMPEchoRequest(b []byte) bool {
  65. out := make([]byte, len(b))
  66. out = iputil.CreateICMPEchoResponse(b, out)
  67. if out == nil {
  68. return false
  69. }
  70. // attempt to write it, but don't block
  71. select {
  72. case t.read <- out:
  73. default:
  74. t.l.Debug("tun_disabled: dropped ICMP Echo Reply response")
  75. }
  76. return true
  77. }
  78. func (t *disabledTun) Write(b []byte) (int, error) {
  79. t.rx.Inc(1)
  80. // Check for ICMP Echo Request before spending time doing the full parsing
  81. if t.handleICMPEchoRequest(b) {
  82. if t.l.Enabled(context.Background(), slog.LevelDebug) {
  83. t.l.Debug("Disabled tun responded to ICMP Echo Request", "raw", prettyPacket(b))
  84. }
  85. } else if t.l.Enabled(context.Background(), slog.LevelDebug) {
  86. t.l.Debug("Disabled tun received unexpected payload", "raw", prettyPacket(b))
  87. }
  88. return len(b), nil
  89. }
  90. func (t *disabledTun) SupportsMultiqueue() bool {
  91. return true
  92. }
  93. func (t *disabledTun) NewMultiQueueReader() error {
  94. t.numReaders++
  95. return nil
  96. }
  97. func (t *disabledTun) Readers() []tio.Queue {
  98. out := make([]tio.Queue, t.numReaders)
  99. for i := range t.numReaders {
  100. out[i] = t
  101. }
  102. return out
  103. }
  104. func (t *disabledTun) Close() error {
  105. if t.read != nil {
  106. close(t.read)
  107. t.read = nil
  108. }
  109. return nil
  110. }
  111. type prettyPacket []byte
  112. func (p prettyPacket) String() string {
  113. var s strings.Builder
  114. for i, b := range p {
  115. if i > 0 && i%8 == 0 {
  116. s.WriteString(" ")
  117. }
  118. s.WriteString(fmt.Sprintf("%02x ", b))
  119. }
  120. return s.String()
  121. }