github.com/xtls/xray-core@v1.8.12-0.20240518155711-3168d27b0bdb/app/dispatcher/fakednssniffer.go (about)

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