mirror of
https://github.com/XTLS/Xray-core.git
synced 2025-04-30 01:08:33 +00:00
Add Fake DNS support (#309)
Co-authored-by: Xiaokang Wang <xiaokangwang@outlook.com> Co-authored-by: loyalsoldier <10487845+Loyalsoldier@users.noreply.github.com> Co-authored-by: kslr <kslrwang@gmail.com>
This commit is contained in:
parent
db32ce6fd9
commit
f50eff5ebb
43 changed files with 1351 additions and 301 deletions
|
@ -1,6 +1,8 @@
|
|||
package dispatcher
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/xtls/xray-core/common"
|
||||
"github.com/xtls/xray-core/common/protocol/bittorrent"
|
||||
"github.com/xtls/xray-core/common/protocol/http"
|
||||
|
@ -12,30 +14,46 @@ type SniffResult interface {
|
|||
Domain() string
|
||||
}
|
||||
|
||||
type protocolSniffer func([]byte) (SniffResult, error)
|
||||
type protocolSniffer func(context.Context, []byte) (SniffResult, error)
|
||||
|
||||
type Sniffer struct {
|
||||
sniffer []protocolSniffer
|
||||
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
|
||||
}
|
||||
|
||||
func NewSniffer() *Sniffer {
|
||||
return &Sniffer{
|
||||
sniffer: []protocolSniffer{
|
||||
func(b []byte) (SniffResult, error) { return http.SniffHTTP(b) },
|
||||
func(b []byte) (SniffResult, error) { return tls.SniffTLS(b) },
|
||||
func(b []byte) (SniffResult, error) { return bittorrent.SniffBittorrent(b) },
|
||||
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) }, false},
|
||||
{func(c context.Context, b []byte) (SniffResult, error) { return tls.SniffTLS(b) }, false},
|
||||
{func(c context.Context, b []byte) (SniffResult, error) { return bittorrent.SniffBittorrent(b) }, false},
|
||||
},
|
||||
}
|
||||
if sniffer, err := newFakeDNSSniffer(ctx); err == nil {
|
||||
ret.sniffer = append(ret.sniffer, sniffer)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
var errUnknownContent = newError("unknown content")
|
||||
|
||||
func (s *Sniffer) Sniff(payload []byte) (SniffResult, error) {
|
||||
var pendingSniffer []protocolSniffer
|
||||
for _, s := range s.sniffer {
|
||||
result, err := s(payload)
|
||||
func (s *Sniffer) Sniff(c context.Context, payload []byte) (SniffResult, error) {
|
||||
var pendingSniffer []protocolSnifferWithMetadata
|
||||
for _, si := range s.sniffer {
|
||||
s := si.protocolSniffer
|
||||
if si.metadataSniffer {
|
||||
continue
|
||||
}
|
||||
result, err := s(c, payload)
|
||||
if err == common.ErrNoClue {
|
||||
pendingSniffer = append(pendingSniffer, s)
|
||||
pendingSniffer = append(pendingSniffer, si)
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -51,3 +69,55 @@ func (s *Sniffer) Sniff(payload []byte) (SniffResult, error) {
|
|||
|
||||
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
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue