1
0

sniffer.go 3.0 KB

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