github.com/xraypb/Xray-core@v1.8.1/app/dispatcher/fakednssniffer.go (about)

     1  package dispatcher
     2  
     3  import (
     4  	"context"
     5  	"strings"
     6  
     7  	"github.com/xraypb/Xray-core/common"
     8  	"github.com/xraypb/Xray-core/common/net"
     9  	"github.com/xraypb/Xray-core/common/session"
    10  	"github.com/xraypb/Xray-core/core"
    11  	"github.com/xraypb/Xray-core/features/dns"
    12  )
    13  
    14  // newFakeDNSSniffer Creates a Fake DNS metadata sniffer
    15  func newFakeDNSSniffer(ctx context.Context) (protocolSnifferWithMetadata, error) {
    16  	var fakeDNSEngine dns.FakeDNSEngine
    17  	{
    18  		fakeDNSEngineFeat := core.MustFromContext(ctx).GetFeature((*dns.FakeDNSEngine)(nil))
    19  		if fakeDNSEngineFeat != nil {
    20  			fakeDNSEngine = fakeDNSEngineFeat.(dns.FakeDNSEngine)
    21  		}
    22  	}
    23  
    24  	if fakeDNSEngine == nil {
    25  		errNotInit := newError("FakeDNSEngine is not initialized, but such a sniffer is used").AtError()
    26  		return protocolSnifferWithMetadata{}, errNotInit
    27  	}
    28  	return protocolSnifferWithMetadata{protocolSniffer: func(ctx context.Context, bytes []byte) (SniffResult, error) {
    29  		Target := session.OutboundFromContext(ctx).Target
    30  		if Target.Network == net.Network_TCP || Target.Network == net.Network_UDP {
    31  			domainFromFakeDNS := fakeDNSEngine.GetDomainFromFakeDNS(Target.Address)
    32  			if domainFromFakeDNS != "" {
    33  				newError("fake dns got domain: ", domainFromFakeDNS, " for ip: ", Target.Address.String()).WriteToLog(session.ExportIDToError(ctx))
    34  				return &fakeDNSSniffResult{domainName: domainFromFakeDNS}, nil
    35  			}
    36  		}
    37  
    38  		if ipAddressInRangeValueI := ctx.Value(ipAddressInRange); ipAddressInRangeValueI != nil {
    39  			ipAddressInRangeValue := ipAddressInRangeValueI.(*ipAddressInRangeOpt)
    40  			if fkr0, ok := fakeDNSEngine.(dns.FakeDNSEngineRev0); ok {
    41  				inPool := fkr0.IsIPInIPPool(Target.Address)
    42  				ipAddressInRangeValue.addressInRange = &inPool
    43  			}
    44  		}
    45  
    46  		return nil, common.ErrNoClue
    47  	}, metadataSniffer: true}, nil
    48  }
    49  
    50  type fakeDNSSniffResult struct {
    51  	domainName string
    52  }
    53  
    54  func (fakeDNSSniffResult) Protocol() string {
    55  	return "fakedns"
    56  }
    57  
    58  func (f fakeDNSSniffResult) Domain() string {
    59  	return f.domainName
    60  }
    61  
    62  type fakeDNSExtraOpts int
    63  
    64  const ipAddressInRange fakeDNSExtraOpts = 1
    65  
    66  type ipAddressInRangeOpt struct {
    67  	addressInRange *bool
    68  }
    69  
    70  type DNSThenOthersSniffResult struct {
    71  	domainName           string
    72  	protocolOriginalName string
    73  }
    74  
    75  func (f DNSThenOthersSniffResult) IsProtoSubsetOf(protocolName string) bool {
    76  	return strings.HasPrefix(protocolName, f.protocolOriginalName)
    77  }
    78  
    79  func (DNSThenOthersSniffResult) Protocol() string {
    80  	return "fakedns+others"
    81  }
    82  
    83  func (f DNSThenOthersSniffResult) Domain() string {
    84  	return f.domainName
    85  }
    86  
    87  func newFakeDNSThenOthers(ctx context.Context, fakeDNSSniffer protocolSnifferWithMetadata, others []protocolSnifferWithMetadata) (
    88  	protocolSnifferWithMetadata, error,
    89  ) { // nolint: unparam
    90  	// ctx may be used in the future
    91  	_ = ctx
    92  	return protocolSnifferWithMetadata{
    93  		protocolSniffer: func(ctx context.Context, bytes []byte) (SniffResult, error) {
    94  			ipAddressInRangeValue := &ipAddressInRangeOpt{}
    95  			ctx = context.WithValue(ctx, ipAddressInRange, ipAddressInRangeValue)
    96  			result, err := fakeDNSSniffer.protocolSniffer(ctx, bytes)
    97  			if err == nil {
    98  				return result, nil
    99  			}
   100  			if ipAddressInRangeValue.addressInRange != nil {
   101  				if *ipAddressInRangeValue.addressInRange {
   102  					for _, v := range others {
   103  						if v.metadataSniffer || bytes != nil {
   104  							if result, err := v.protocolSniffer(ctx, bytes); err == nil {
   105  								return DNSThenOthersSniffResult{domainName: result.Domain(), protocolOriginalName: result.Protocol()}, nil
   106  							}
   107  						}
   108  					}
   109  					return nil, common.ErrNoClue
   110  				}
   111  				newError("ip address not in fake dns range, return as is").AtDebug().WriteToLog()
   112  				return nil, common.ErrNoClue
   113  			}
   114  			newError("fake dns sniffer did not set address in range option, assume false.").AtWarning().WriteToLog()
   115  			return nil, common.ErrNoClue
   116  		},
   117  		metadataSniffer: false,
   118  	}, nil
   119  }