sniffer.go 3.7 KB

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