tun_disabled.go 2.8 KB

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