sniffer.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. package dispatcher
  2. import (
  3. "context"
  4. "github.com/xtls/xray-core/common"
  5. "github.com/xtls/xray-core/common/errors"
  6. "github.com/xtls/xray-core/common/net"
  7. "github.com/xtls/xray-core/common/protocol/bittorrent"
  8. "github.com/xtls/xray-core/common/protocol/http"
  9. "github.com/xtls/xray-core/common/protocol/quic"
  10. "github.com/xtls/xray-core/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, c) }, 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 bittorrent.SniffBittorrent(b) }, false, net.Network_TCP},
  34. {func(c context.Context, b []byte) (SniffResult, error) { return quic.SniffQUIC(b) }, false, net.Network_UDP},
  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 = errors.New("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. s := si.protocolSniffer
  53. if si.metadataSniffer || si.network != network {
  54. continue
  55. }
  56. result, err := s(c, payload)
  57. if err == common.ErrNoClue {
  58. pendingSniffer = append(pendingSniffer, si)
  59. continue
  60. }
  61. if err == nil && result != nil {
  62. return result, nil
  63. }
  64. }
  65. if len(pendingSniffer) > 0 {
  66. s.sniffer = pendingSniffer
  67. return nil, common.ErrNoClue
  68. }
  69. return nil, errUnknownContent
  70. }
  71. func (s *Sniffer) SniffMetadata(c context.Context) (SniffResult, error) {
  72. var pendingSniffer []protocolSnifferWithMetadata
  73. for _, si := range s.sniffer {
  74. s := si.protocolSniffer
  75. if !si.metadataSniffer {
  76. pendingSniffer = append(pendingSniffer, si)
  77. continue
  78. }
  79. result, err := s(c, nil)
  80. if err == common.ErrNoClue {
  81. pendingSniffer = append(pendingSniffer, si)
  82. continue
  83. }
  84. if err == nil && result != nil {
  85. return result, nil
  86. }
  87. }
  88. if len(pendingSniffer) > 0 {
  89. s.sniffer = pendingSniffer
  90. return nil, common.ErrNoClue
  91. }
  92. return nil, errUnknownContent
  93. }
  94. func CompositeResult(domainResult SniffResult, protocolResult SniffResult) SniffResult {
  95. return &compositeResult{domainResult: domainResult, protocolResult: protocolResult}
  96. }
  97. type compositeResult struct {
  98. domainResult SniffResult
  99. protocolResult SniffResult
  100. }
  101. func (c compositeResult) Protocol() string {
  102. return c.protocolResult.Protocol()
  103. }
  104. func (c compositeResult) Domain() string {
  105. return c.domainResult.Domain()
  106. }
  107. func (c compositeResult) ProtocolForDomainResult() string {
  108. return c.domainResult.Protocol()
  109. }
  110. type SnifferResultComposite interface {
  111. ProtocolForDomainResult() string
  112. }
  113. type SnifferIsProtoSubsetOf interface {
  114. IsProtoSubsetOf(protocolName string) bool
  115. }