sniffer.go 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. package dispatcher
  2. import (
  3. "context"
  4. "github.com/v2fly/v2ray-core/v5/common"
  5. "github.com/v2fly/v2ray-core/v5/common/net"
  6. "github.com/v2fly/v2ray-core/v5/common/protocol"
  7. "github.com/v2fly/v2ray-core/v5/common/protocol/bittorrent"
  8. "github.com/v2fly/v2ray-core/v5/common/protocol/http"
  9. "github.com/v2fly/v2ray-core/v5/common/protocol/quic"
  10. "github.com/v2fly/v2ray-core/v5/common/protocol/tls"
  11. )
  12. type SniffResult interface {
  13. Protocol() string
  14. Domain() string
  15. }
  16. type protocolSniffer func(context.Context, []byte) (SniffResult, error)
  17. type protocolSnifferWithMetadata struct {
  18. protocolSniffer protocolSniffer
  19. // A Metadata sniffer will be invoked on connection establishment only, with nil body,
  20. // for both TCP and UDP connections
  21. // It will not be shown as a traffic type for routing unless there is no other successful sniffing.
  22. metadataSniffer bool
  23. network net.Network
  24. }
  25. type Sniffer struct {
  26. sniffer []protocolSnifferWithMetadata
  27. }
  28. func NewSniffer(ctx context.Context) *Sniffer {
  29. ret := &Sniffer{
  30. sniffer: []protocolSnifferWithMetadata{
  31. {func(c context.Context, b []byte) (SniffResult, error) { return http.SniffHTTP(b) }, false, net.Network_TCP},
  32. {func(c context.Context, b []byte) (SniffResult, error) { return tls.SniffTLS(b) }, false, net.Network_TCP},
  33. {func(c context.Context, b []byte) (SniffResult, error) { return quic.SniffQUIC(b) }, false, net.Network_UDP},
  34. {func(c context.Context, b []byte) (SniffResult, error) { return bittorrent.SniffBittorrent(b) }, false, net.Network_TCP},
  35. {func(c context.Context, b []byte) (SniffResult, error) { return bittorrent.SniffUTP(b) }, false, net.Network_UDP},
  36. },
  37. }
  38. if sniffer, err := newFakeDNSSniffer(ctx); err == nil {
  39. others := ret.sniffer
  40. ret.sniffer = append(ret.sniffer, sniffer)
  41. fakeDNSThenOthers, err := newFakeDNSThenOthers(ctx, sniffer, others)
  42. if err == nil {
  43. ret.sniffer = append([]protocolSnifferWithMetadata{fakeDNSThenOthers}, ret.sniffer...)
  44. }
  45. }
  46. return ret
  47. }
  48. var errUnknownContent = newError("unknown content")
  49. func (s *Sniffer) Sniff(c context.Context, payload []byte, network net.Network) (SniffResult, error) {
  50. var pendingSniffer []protocolSnifferWithMetadata
  51. for _, si := range s.sniffer {
  52. sniffer := si.protocolSniffer
  53. if si.metadataSniffer {
  54. continue
  55. }
  56. if si.network != network {
  57. continue
  58. }
  59. result, err := sniffer(c, payload)
  60. if err == common.ErrNoClue {
  61. pendingSniffer = append(pendingSniffer, si)
  62. continue
  63. } else if err == protocol.ErrProtoNeedMoreData { // Sniffer protocol matched, but need more data to complete sniffing
  64. s.sniffer = []protocolSnifferWithMetadata{si}
  65. return nil, protocol.ErrProtoNeedMoreData
  66. }
  67. if err == nil && result != nil {
  68. return result, nil
  69. }
  70. }
  71. if len(pendingSniffer) > 0 {
  72. s.sniffer = pendingSniffer
  73. return nil, common.ErrNoClue
  74. }
  75. return nil, errUnknownContent
  76. }
  77. func (s *Sniffer) SniffMetadata(c context.Context) (SniffResult, error) {
  78. var pendingSniffer []protocolSnifferWithMetadata
  79. for _, si := range s.sniffer {
  80. s := si.protocolSniffer
  81. if !si.metadataSniffer {
  82. pendingSniffer = append(pendingSniffer, si)
  83. continue
  84. }
  85. result, err := s(c, nil)
  86. if err == common.ErrNoClue {
  87. pendingSniffer = append(pendingSniffer, si)
  88. continue
  89. }
  90. if err == nil && result != nil {
  91. return result, nil
  92. }
  93. }
  94. if len(pendingSniffer) > 0 {
  95. s.sniffer = pendingSniffer
  96. return nil, common.ErrNoClue
  97. }
  98. return nil, errUnknownContent
  99. }
  100. func CompositeResult(domainResult SniffResult, protocolResult SniffResult) SniffResult {
  101. return &compositeResult{domainResult: domainResult, protocolResult: protocolResult}
  102. }
  103. type compositeResult struct {
  104. domainResult SniffResult
  105. protocolResult SniffResult
  106. }
  107. func (c compositeResult) Protocol() string {
  108. return c.protocolResult.Protocol()
  109. }
  110. func (c compositeResult) Domain() string {
  111. return c.domainResult.Domain()
  112. }
  113. func (c compositeResult) ProtocolForDomainResult() string {
  114. return c.domainResult.Protocol()
  115. }
  116. type SnifferResultComposite interface {
  117. ProtocolForDomainResult() string
  118. }
  119. type SnifferIsProtoSubsetOf interface {
  120. IsProtoSubsetOf(protocolName string) bool
  121. }