XrayR/app/mydispatcher/sniffer.go
xrayrgoon 974abc9a98
Some checks failed
CodeQL / Analyze (go) (push) Failing after 4m49s
Build and Release / build (386, freebsd) (push) Failing after 8m40s
Build and Release / build (386, linux) (push) Failing after 7m10s
Build and Release / build (386, windows) (push) Failing after 6m49s
Build and Release / build (amd64, darwin) (push) Failing after 7m8s
Build and Release / build (amd64, freebsd) (push) Failing after 7m31s
Build and Release / build (amd64, linux) (push) Failing after 7m20s
Build and Release / build (amd64, openbsd) (push) Failing after 7m4s
Build and Release / build (amd64, windows) (push) Failing after 7m9s
Build and Release / build (arm, 5, linux) (push) Failing after 6m44s
Build and Release / build (arm, 6, linux) (push) Failing after 6m42s
Build and Release / build (arm, 7, freebsd) (push) Failing after 6m32s
Build and Release / build (arm, 7, linux) (push) Failing after 6m43s
Build and Release / build (arm64, android) (push) Failing after 6m59s
Build and Release / build (arm64, darwin) (push) Failing after 6m54s
Build and Release / build (arm64, freebsd) (push) Failing after 6m52s
Build and Release / build (arm64, linux) (push) Failing after 7m5s
Build and Release / build (mips, linux) (push) Failing after 12m35s
Build and Release / build (mips64, linux) (push) Failing after 7m4s
Build and Release / build (mips64le, linux) (push) Failing after 6m39s
Build and Release / build (mipsle, linux) (push) Failing after 11m56s
Build and Release / build (ppc64le, linux) (push) Failing after 6m54s
Build and Release / build (riscv64, linux) (push) Failing after 8m10s
Build and Release / build (s390x, linux) (push) Failing after 6m56s
Close inactive issues / close-issues (push) Successful in 25s
xray-core v25.3.6 and other updates (#748)
2025-03-21 02:07:22 +08:00

138 lines
3.8 KiB
Go

package mydispatcher
import (
"context"
"github.com/xtls/xray-core/common"
"github.com/xtls/xray-core/common/net"
"github.com/xtls/xray-core/common/protocol/bittorrent"
"github.com/xtls/xray-core/common/protocol/http"
"github.com/xtls/xray-core/common/protocol/quic"
"github.com/xtls/xray-core/common/protocol/tls"
)
type SniffResult interface {
Protocol() string
Domain() string
}
type protocolSniffer func(context.Context, []byte) (SniffResult, error)
type protocolSnifferWithMetadata struct {
protocolSniffer protocolSniffer
// A Metadata sniffer will be invoked on connection establishment only, with nil body,
// for both TCP and UDP connections
// It will not be shown as a traffic type for routing unless there is no other successful sniffing.
metadataSniffer bool
network net.Network
}
type Sniffer struct {
sniffer []protocolSnifferWithMetadata
}
func NewSniffer(ctx context.Context) *Sniffer {
ret := &Sniffer{
sniffer: []protocolSnifferWithMetadata{
{func(c context.Context, b []byte) (SniffResult, error) { return http.SniffHTTP(b, ctx) }, false, net.Network_TCP},
{func(c context.Context, b []byte) (SniffResult, error) { return tls.SniffTLS(b) }, false, net.Network_TCP},
{func(c context.Context, b []byte) (SniffResult, error) { return bittorrent.SniffBittorrent(b) }, false, net.Network_TCP},
{func(c context.Context, b []byte) (SniffResult, error) { return quic.SniffQUIC(b) }, false, net.Network_UDP},
{func(c context.Context, b []byte) (SniffResult, error) { return bittorrent.SniffUTP(b) }, false, net.Network_UDP},
},
}
if sniffer, err := newFakeDNSSniffer(ctx); err == nil {
others := ret.sniffer
ret.sniffer = append(ret.sniffer, sniffer)
fakeDNSThenOthers, err := newFakeDNSThenOthers(ctx, sniffer, others)
if err == nil {
ret.sniffer = append([]protocolSnifferWithMetadata{fakeDNSThenOthers}, ret.sniffer...)
}
}
return ret
}
var errUnknownContent = newError("unknown content")
func (s *Sniffer) Sniff(c context.Context, payload []byte, network net.Network) (SniffResult, error) {
var pendingSniffer []protocolSnifferWithMetadata
for _, si := range s.sniffer {
s := si.protocolSniffer
if si.metadataSniffer || si.network != network {
continue
}
result, err := s(c, payload)
if err == common.ErrNoClue {
pendingSniffer = append(pendingSniffer, si)
continue
}
if err == nil && result != nil {
return result, nil
}
}
if len(pendingSniffer) > 0 {
s.sniffer = pendingSniffer
return nil, common.ErrNoClue
}
return nil, errUnknownContent
}
func (s *Sniffer) SniffMetadata(c context.Context) (SniffResult, error) {
var pendingSniffer []protocolSnifferWithMetadata
for _, si := range s.sniffer {
s := si.protocolSniffer
if !si.metadataSniffer {
pendingSniffer = append(pendingSniffer, si)
continue
}
result, err := s(c, nil)
if err == common.ErrNoClue {
pendingSniffer = append(pendingSniffer, si)
continue
}
if err == nil && result != nil {
return result, nil
}
}
if len(pendingSniffer) > 0 {
s.sniffer = pendingSniffer
return nil, common.ErrNoClue
}
return nil, errUnknownContent
}
func CompositeResult(domainResult SniffResult, protocolResult SniffResult) SniffResult {
return &compositeResult{domainResult: domainResult, protocolResult: protocolResult}
}
type compositeResult struct {
domainResult SniffResult
protocolResult SniffResult
}
func (c compositeResult) Protocol() string {
return c.protocolResult.Protocol()
}
func (c compositeResult) Domain() string {
return c.domainResult.Domain()
}
func (c compositeResult) ProtocolForDomainResult() string {
return c.domainResult.Protocol()
}
type SnifferResultComposite interface {
ProtocolForDomainResult() string
}
type SnifferIsProtoSubsetOf interface {
IsProtoSubsetOf(protocolName string) bool
}